Postfix

Postfix - 將被未知收件人拒絕的電子郵件轉發到垃圾郵件學習郵箱

  • November 20, 2014

在少數交易所之前,我有 Postfix + BitDefender FRAMS 作為衛生網關執行。BD FRAMS 可以通過從專用郵箱下載垃圾郵件和 HAM 電子郵件來學習它的貝斯過濾器。因為我們有持續向未知收件人發送垃圾郵件,所以我有想法將這個有用的垃圾郵件來源直接重定向到垃圾郵件學習郵箱。

我的配置:

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_restrictions =
#  permit_mynetworks
#  reject_invalid_hostname
#  permit

smtpd_restriction_classes = verify_sender
verify_sender =
 reject_unverified_sender

smtpd_sender_restrictions =
 permit_mynetworks

smtpd_recipient_restrictions =
 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_unlisted_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_restrictions =
 #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/後綴/傳輸:

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'

我為 cron 從 AD 填充中繼使用者的腳本(請為您分享):

#!/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)))'
       attributes = ['proxyAddresses']
       searchresults = ldapconnection.search_s(basedn, scope, filter, attributes)
       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()

如果有人知道如何做到這一點,我將不勝感激。謝謝。

您的請求有點複雜,因為這很重要。根據設計,Postfix 將根據 maps 的積極結果執行某些操作。例如,在您的transport_maps中,如果收件人從地圖查找中獲得肯定結果,它將向特定主機發送電子郵件。relay_recipient_maps但是,如果您的查找有負面結果,您想要執行某些操作 - 重定向到另一個郵箱。由於您的地圖類型是hash我認為沒有其他方法,除非涉及 sql/tcp 地圖以在地圖中實現否定結果邏輯。

對於 sql 解決方案,這是一個想法:

在這個例子中,我將使用 sqlite。假設您有一個表,其中有一列名為 relay_recipient。現在查詢

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

mailboxspam@example.com只要接收者在 relay_recipient_maps 中不存在,就會返回。將這些地圖放在virtual_alias參數上。然後每當電子郵件發送給未知使用者時,它就會別名為mailboxspam@example.com

引用自:https://serverfault.com/questions/638548