Postfix – renvoyé par les courriels des récepteurs inconnus à la boîte aux lettres SPAM-learning

J'ai Postfix + BitDefender FRAMS en tant que passerelle d'hygiène avant quelques échanges. BD FRAMS peut apprendre son filter Baesian en téléchargeant les courriels SPAM et HAM à partir de boîtes aux lettres dédiées. Parce que nous maintenons le stream de SPAM à des destinataires inconnus, j'ai l'idée de redirect cette source utile de courriels SPAM directement sur la boîte aux lettres SPAM-learning.

Mes configurations:

main.cf:

myhostname = posfix.example.com smtpd_banner = $myhostname #myorigin = example.com mydestination = local_recipient_maps = #virtual_alias_maps = hash:/etc/postfix/virtual local_transport = error:local mail delivery is disabled mynetworks = /etc/postfix/mynetworks smtpd_use_tls = yes #smtpd_tls_auth_only = yes smtpd_tls_key_file = /etc/ssl/certs/posfix.example.com.pem smtpd_tls_cert_file = /etc/ssl/certs/posfix.example.com.pem smtpd_tls_CApath = /etc/ssl/certs smtpd_tls_loglevel = 1 smtpd_tls_received_header = yes smtpd_tls_session_cache_timeout = 3600s relay_domains = mysql:/etc/postfix/relay_domains transport_maps = mysql:/etc/postfix/transport relay_recipient_maps = mysql:/etc/postfix/relay_recipient_maps show_user_unknown_table_name = no unknown_local_recipient_reject_code = 550 mailbox_size_limit = 102400000000 message_size_limit = 102400000 smtpd_delay_reject = yes smtpd_helo_required = yes #smtpd_helo_ressortingctions = # permit_mynetworks # reject_invalid_hostname # permit smtpd_ressortingction_classs = verify_sender verify_sender = reject_unverified_sender smtpd_sender_ressortingctions = permit_mynetworks smtpd_recipient_ressortingctions = reject_unknown_recipient_domain reject_non_fqdn_recipient permit_mynetworks reject_authenticated_sender_login_mismatch reject_unauth_destination check_recipient_access hash:/etc/postfix/recipient_access check_sender_access hash:/etc/postfix/sender_access #check_helo_access pcre:/etc/postfix/helo_access reject_non_fqdn_sender reject_unknown_sender_domain reject_unlistd_sender reject_invalid_hostname reject_unauth_pipelining check_sender_mx_access cidr:/etc/postfix/sender_mx_access #reject_non_fqdn_hostname #reject_unverified_sender #reject_multi_recipient_bounce permit #smtpd_data_ressortingctions = #reject_multi_recipient_bounce # Added by BitDefender on Mon Nov 3 15:27:43 EET 2014 smtpd_milters=unix:/var/spool/postfix/BitDefender/bdmilterd.sock milter_protocol = 2 milter_default_action = tempfail milter_connect_timeout = 30s milter_command_timeout = 30s milter_content_timeout = 30s # End of added lines 

/ etc / postfix / relay_domains:

 user = postfix password = postfix dbname = postfix query = SELECT name FROM relay_domains WHERE name='%s' 

/ etc / postfix / transport:

 user = postfix password = postfix dbname = postfix query = SELECT nexthop FROM relay_domains WHERE name='%s' 

/ etc / postfix / relay_recipient_maps:

 user = postfix password = postfix dbname = postfix query = SELECT email FROM relay_users WHERE email='%s' 

mon script pour relayer les users de relais de AD (partagé gentillement pour vous) pour cron:

 #!/usr/bin/python __author__ = 'tiv' import ldap import MySQLdb connections = { 1: ['dc.example.com', # AD domain controller 'EXAMPLE\\user', # AD user 'password', # AD user password 'dc=example, dc=local', # AD root DN 'mail.example.com'], # Exchange server 2: ['dc.example1.com', # AD domain controller 'EXAMPLE1\\user', # AD user 'password', # AD user password 'dc=example1, dc=local', # AD root DN 'mail.example1.com'], # Exchange server #3: 'dc.example2.com', # AD domain controller # 'EXAMPLE2\\user', # AD user # 'password', # AD user password # 'dc=example2, dc=local', # AD root DN # 'mail.example2.com'], # Exchange server } mysql = ['localhost', # host 'postfix', # user 'postfix', # password 'postfix'] # schema def main(): try: emails = [] domains = [] for i in connections: connection = connections[i] print('Processing LDAP server ' + connection[0] + ':') basedn = connections[i][3] nexthop = connections[i][4] lc = ldapconnection(connection) ls = ldapsearch(lc, basedn) rl = resultlist(ls) emails.extend(rl[0]) for domain in rl[1]: domains.append([domain, nexthop]) print('Processing of LDAP server ' + connection[0] + ' completed.') createdb(emails, domains, mysql) print('Operation completed successfully!') except: print('Error processing of LDAP server ' + connection[0] + '!') pass def ldapconnection(ldapserver): try: print(' Trying to connect to LDAP server ' + ldapserver[0] + '...') ldapconnection = ldap.initialize('ldap://' + ldapserver[0]) ldapconnection.simple_bind_s(ldapserver[1], ldapserver[2]) ldapconnection.protocol_version = ldap.VERSION3 ldapconnection.set_option(ldap.OPT_REFERRALS, 0) print(' Connection to LDAP server ' + ldapserver[0] + ' succesfull.') except: print('Error connecting to LDAP server ' + ldapserver[0] + '!') pass return ldapconnection def ldapsearch(ldapconnection, basedn): try: print(' Sending LDAP query request...') scope = ldap.SCOPE_SUBTREE filter = '(&(proxyAddresses=smtp:*)(!(objectClass=contact)))' atsortingbutes = ['proxyAddresses'] searchresults = ldapconnection.search_s(basedn, scope, filter, atsortingbutes) print(' LDAP query request results received.') except: print('Error sending LDAP query request!') pass return searchresults def resultlist(searchresults): try: print(' Processing LDAP query results...') emails = [] domains = [] for i in range(len(searchresults)): try: for j in range(len(searchresults[i][1]['proxyAddresses'])): r = searchresults[i][1]['proxyAddresses'][j].lower() if 'smtp:' in r: email = r[5:] emails.append(email) domain = email.split("@")[1] domains.append(domain) except: pass print(' LDAP query results processed.') except: print('Error processing LDAP query results!') pass return removedublicates(emails), removedublicates(domains) def createdb(emails, domains, mysql): try: print('Connecting to DB ' + mysql[3] + '...') try: db = MySQLdb.connect(host=mysql[0], user=mysql[1], passwd=mysql[2]) cursor = db.cursor() sql = 'CREATE SCHEMA IF NOT EXISTS ' + mysql[3] cursor.execute(sql) db.commit() except: pass try: db = MySQLdb.connect(host=mysql[0], user=mysql[1], passwd=mysql[2], db=mysql[3]) cursor = db.cursor() except: print('Error connecting to DB ' + mysql[3] + '!') print(' Check schemas and tables...') sql = ['CREATE TABLE IF NOT EXISTS ' + mysql[3] + '.relay_users (id INT NOT NULL, email LONGTEXT NULL, PRIMARY KEY (id))', 'CREATE TABLE IF NOT EXISTS ' + mysql[3] + '.relay_domains (id INT NOT NULL, name LONGTEXT NULL, nexthop LONGTEXT NULL, PRIMARY KEY (id))', 'TRUNCATE ' + mysql[3] + '.relay_users', 'TRUNCATE ' + mysql[3] + '.relay_domains'] for i in range(len(sql)): cursor.execute(sql[i]) db.commit() print(' Inserting domains...') for i in range(len(domains)): sql = 'INSERT INTO postfix.relay_domains (id, name, nexthop)' \ 'VALUES ("' + str(i) + '", "' + domains[i][0] + '", "smtp:[' + domains[i][1] + ']")' cursor.execute(sql) db.commit() print(' Inserting emails...') for i in range(len(emails)): sql = 'INSERT INTO postfix.relay_users (id, email)' \ 'VALUES ("' + str(i) + '", "' + emails[i] + '")' cursor.execute(sql) db.commit() db.close() print('Connection to DB ' + mysql[3] + ' closed.') except: print('Error while operating with DB ' + mysql[3] + '!') pass def removedublicates(input): seen = set() seen_add = seen.add return [x for x in input if not (x in seen or seen_add(x))] if __name__ == '__main__': main() 

Si quelqu'un sait, comment faire, j'apprécierai. Merci.

Votre request est un peu compliquée parce que cette question. Postfix, par design, exécutera quelque chose en fonction des résultats positifs des maps . Par exemple, dans votre mode de transport_maps , il enverra un courrier électronique à un hôte spécifique si le destinataire est un résultat positif de la search de maps. Mais, vous voulez exécuter quelque chose, redirigez vers une autre boîte aux lettres – s'il y a un résultat négatif de votre search relay_recipient_maps . Avec votre type de carte est hash , je pense qu'il n'y a pas d'autre moyen à less d'impliquer la carte sql / tcp pour implémenter une logique de résultat négatif dans la carte.

Pour la solution sql, voici l'idée:

Dans cet exemple, je vais utiliser sqlite. Supposons que vous ayez un tableau avec une colonne nommée relay_recipient. Maintenant, la requête

 select ifnull(select relay_recipient from mytable WHERE relay_recipient = %s, 'mailboxspam@example.com') 

renverra mailboxspam@example.com chaque fois que le destinataire n'existe pas dans relay_recipient_maps. Placez ces maps sur le paramètre virtual_alias . Ensuite, chaque fois que le courrier électronique envoyé à un user inconnu, il sera alias à mailboxspam@example.com

+1 pour @ tmpl7 a une excellente idée de la façon d'implémenter votre scénario avec sqlite

Maintenant, le problème est que vous n'avez pas implémenté la requête sql pour ifnull dans le paramètre virtual_alias_maps . Définissez d'abord les virtual_alias_maps dans main.cf

 virtual_alias_maps = mysql:/etc/postfix/redirect2spamlearning 

Le contenu de /etc/postfix/redirect2spamlearning

 user = postfix password = postfix dbname = postfix query = SELECT IFNULL((SELECT email FROM relay_users WHERE email='%s'), 'spamlearn@example.com') 

La logique est: si SELECT email FROM relay_users WHERE email='%s' ne renvoie rien aka null-value, alors le courrier électronique sera redirigé vers spamlearn@example.com.

  • Voir le violon SQL ici
  • Voir la documentation de virtual_alias_maps dans postconf (5) et virtual (5)