Use python scripting under qmail to filter mail and send text messages: Mei Jinsong Email: stephen.cn@gmail.com Time: September 10, 2004 thanks: HD, Liu Xin SMS so hot, if your mail server can Combine with SMS, how good? Under QMAIL, I use qmail_queue to solve mail filtering and SMS arrival notice. This mail system is implemented in FreeBSD 4.10. 1. There is not much to say for the installation of the mail system. It is recommended to see HD's http://bsd.huangdongdong.com/server/mail/qmail.html to install. If you have already installed a QMail VpopMail QMAIL_QUEUE patch, you will jump directly to 4 to continue installed. When newly installed mail servers have a few things to note is that when qmail installation steps should be changed to: cd / usr / ports / mail / qmail make WITH_QMAILQUEUE_PATCH = yes WITH_BIG_TODO_PATCH = yes WITH_OUTGOINGIP_PATCH = yes WITH_PRESERVE_CONFIG_FILES = yes extract cd / usr / ports / mail / qmail / work / qmail-1.03 fetch http://www.nimh.org/dl/qmail-smtpd.c cd / usr / ports / mail / qmail make WITH_QMAILQUEUE_PATCH = yes WITH_BIG_TODO_PATCH = yes WITH_OUTGOINGIP_PATCH = yes WITH_PRESERVE_CONFIG_FILES = YES Install Make Disable-Sendmail Make Enable-qmail Make Clean
When installing vpopmail, you may have a strange problem because port updates, it is preferred to use Vpopmail, it is best to install the webmin to delete the Vpopmail database, re-establish, and specify the user permission of the database. Since the installation of Webmin is not focus on this article, it will be ignored here.
2. About the anti-virus part in the article because of the systematic efficiency problem, I have not installed. Please decide whether to install it.
3, the anti-spam is of course, I use http://anti-spam.org.cn CBL service. You only need to change the SMTPD's script to: #! / Bin / sh qmailduid = `/ usr / bin / id-u qmails` Nofilesgid =` / usr / bin / id -g qmails` Exec / USR / local / BIN / TCPSERVER -H -R -L 0 -P / / / /USR/LOCAL/VPOPMAIL/etc/tcp.smtp.cdb -u "$ qLDUID" / -g "$ nofilesgid" -V -C100 0 SMTP RBLSMTPD / -r cblplus.anti-spam.org.cn / -r recomlays.ordb.org / / var / qmail / bin / qmail-smtpd / usr / local / vpopmail / bin / vchkpw-smtpd / usr / bin / true 2> &1
From http://anti-spam.org.cn/cgi-bin/rblclient/ (your mail server's DNS server IP address) sees the traffic of your mail server and the use of CBL services.
4, here is the focus. Filtering and SMS arrivals are required to be qmail_queue to do it, be sure to make this package. Using Python to implement this feature, of course you need to install Python. CD / USR / PORTS / LANG / PYTHON MAKE; Make Install; Make Clean Generally speaking this installation is very smooth. After the installation is over. CD / var / qmail / bin edits QMFill.py, the content is as follows:
#! / usr / local / bin / python -
Import OS, Sys, String, Time, Traceback, Re, Socket
Version = '1.1'PyVersion =' 1.0'Logging = 1Debug = 0QmailD = 82 # Here you need and / etc / password as user qmaild inside LogFile = NoneTestMode = NoneFilters = [] MailEnvelope = '' MailData = '' ValidActions = { 'trap': '', 'Drop': '', 'Block': ''}
# This is where you send messages to which server you pass through the UCP protocol: Host = "xxx.xxx.114.2" port = 9999 buf = 500 addr = (Host, Port)
# Create socket udpsock = socket.socket (socket.af_inet, socket.sock_dgram)
DEF_MSG = MSG; udpsock.sendto (DEF_MSG, ADDR)
# Close Socket Udpsock.close ()
DEF OPENLOG (): Global logfile
If not logging: return = os.open ('/ var / log / qmfilt ", os.o_append | os.o_wronly | Os.o_creat, 0744) Except: if TestMode: Print" can't create / var / LOG / QMFILT "ELSE: # indexit" Error Sys.exit (53)
Def log (message): message = time.asctime (time.localtime (time.time ()))) "-" Message "/ N" if logging: os.write (logfile, message) # indeicate a write error # sys.exit (53) IF TestMode: Print Message
Def showfilters (): if len (filters) == 0: Print "No filters" for f in filters: print "Filter -% s - action:% s regex:% s"% (f [0], f [1 ], f [2])
Def readfilters (): Global Filters
Try: file = Open ('/ var / qmail / control / qmfilt', 'r') configLines = file.readlines () file.close () Except: log ("can't read / var / qmail / control / qmfilt ") If not testmode: # indeicate a 'Cannot Read config file error' sys.exit (53) REG = Re.Compile ('(. *) :: ( ) :: (. ) ::') for Line in configLines: if line [0] == '#': Continue M = reg.match (line) IF m! = none: action = string.lower (m.Group (2)) if not validactions.has_key (action : Log ("INVALID ACTION IN Config File") Continue Filters.Append ([M.Group (1), String.Lower (M.Group (2)), M.Group (3)]) Def readDescriptor (dec): Result = '' While 1: Data = Os.Read (DESC, 16384) IF data == ': Break Result = Result Data
Return RESULT
DEF WRITEDESCRIPTOR (DESC, DATA): While Data: Num = Os.Write (DESC, DATA) DATA = DATA [NUM:]
Os.close (DESC)
Def filterhits (): for regex in filters: reg = re.compile (regex [2], re.m | re .i) match = reg.search (maildata) if match: log ("matched [% s]"% (regex [0])) Return Regex [1], regex [0]
Return None, None
Def StoreInTrap (HIT): try: pid = os.getpid () mailfile = os.open ('/ var / qmail / qmfilt / qmfilt.% s'% (PID), Os.o_Wronly | Os.o_creat | Os.o_EXCL , 0744) Except: log ("can't create /var/qmail/qmfilt/qmfilt.%"% (PID) # ingrote a write error sys.exit (53)
Try: # If there is a lot of problems if it is not masked, as for why I haven't figured it, if you find the problem, please tell me. "" (None, Inode, None, None, None, None) = Os.FStat (Mailfile) "" os.rename ('/ var / qmail / qmfilt / qmfilt.% S '% (PID),' /var/qmail/qmfilt/%s.mail '% (inode) Except: log ("can't rename /var/qmail/qmfilt/qmfilt.%S -> / var / qmail /Qmfilt/%S.mail "% (pid, inode) # indexit (53) try: envfile = os.open ('/ var / qmail / qmfilt /% s.envelope'% (inode) ), Os.o_Wronly | Os.o_creat | Os.o_EXCL, 0744) MESGFILE = Os.Open ('/ var / qmail / qmfilt /% s. qmfilt'% (inode), Os.o_Wronly | Os.o_Creat | OS. O_EXCL, 0744) writeDescriptor (mailFile, MailData) writeDescriptor (envFile, MailEnvelope) writeDescriptor (mesgFile, "Matched filter [% s] to file% s"% (hit, inode)) log ( "Matched filter [% s] to file % s "% (Hit, Inode) Except: log (" can't create / write files inTo trap ") # indexit (53)
Return 0
DEF senttoqmailqueue (): # Open a pipe to qmail queue fd0 = OS.PIPE () fd1 = Os.pipe () pid = Os.Fork () IF PID <0: log ("Error Couldn't fork" sys. EXIT (81) if pid == 0: # this is the child os.dup2 (fd0 [0], 0) Os.dup2 (FD1 [0], 1) i = 2 while (i <64): TRY: OS .close (i) Except: pass i = i 1 Os.chdir ('/ var / qmail') # time.sleep (10) Os.execv ("Bin / Qmail-Queue", ('bin / qmail-queue ',)) Something wrong "sys.exit (127) # this is only reached ost ire else: # this is the parent # close the readable descriptors Os.close (fd0 [0]) Os.close ( FD1 [0]) # send the data recvHdr = "Received: (QMFILT:% S);"% (Version) RecvHDR = RecvHDR Time.StrFTIME ("% D% B% Y% H:% M:% S" , Time.gmtime (Time.Time ())) RecvHDR = RecvHDR "-0000 / n" Os.Write (FD0 [1], Recvhdr) WriteDescriptor (fd0 [1], maildata) WriteScriptor (fd1 [1], mailenvelope )
# Catch the exit code to return results = os.waitpid (pid, 0) [1] if pyversion> '1.5.1': if os.wifexited (Result): Return Os.WexitStatus (Result) Else: Log ("DIDN 't exit normally ") sys.exit (81) Else: Return Result
Def Conver (MSG): MSG = msg.replace (chr (00), '') msg = msg.replace ('f', 'from:', 1) msg = msg.replace ('t', 'TO: ') RETURN MSG
Def Main (Argv, Stdout, Environ):
Global TestMode Global Maildata Global MAILENVELOPE GLOBAL PYVERSION
Pyversion = string.split (sys.version) [0]
IF LEN (Argv)> 1 and Argv [1] == '--Test': TestMode = 1
Os.setuid (QMAILD)
# Insure environment is Ok # try to open log openlog ()
If not os.path.exists ('/ var / qmail / qmfilt'): # indeicate a problem with the queue directory log ("Directory / VAR / QMAIL / QMFILT DOESN'T") If NOT TESTMODE: SYS.EXIT ( 61)
If os.path.exists ('/ var / qmail / control / qmfilt'): readfilters () else: if TestMode: Print "no filter file / var / qmail / control / qmfilt - no filters applied"
IF TestMode: showfilters ()
# Go no further if in test mode if testmode: sys.exit (0)
# Get the data
# Ied the data maildata = readDescriptor (0)
# Ie, mailenvelope = readscriptor (1) if debug: log (maildata) log (maileenvelop)
Action, hit = filterhits ()
If action == 'trap': StoreInTrap (HIT) if action == 'block': log ("matched filter [% s] and email was blocked / refused delivery"% (hIT)) SYS.EXIT (31) ife == 'Drop': log ("Matched Filter [% s] and email Was Dropped"% (HIT)) ife == none: sendtoqmailqueue () #LOG log (convert (mailenvelope)) #send sms mail_sms (Conver Mailenvelope)))
IF debug: log ("qmailqueue returned [% d]"% (result) sys.exit (0)
IF __NAME__ == "__main__": Try: main (sys.argv, sys.stdout, os.environ)
# Catch the sys.exit () Errors Except systemExit, val: sys.exit (val) Except: # Return A Fatal Error for the unknown error if TestMode: traceback.print_exc () sys.exit (81)
Then cd / var / qmail / control edit qmfilt reads as follows: # # This is the qmfilt control file # If any email comes in that matches this # filter, the mail will be redirected # to the filter directory # # A filter regular expression Must be on a single # line and in between a pair of '::' # Valid actions: # trap - Store in the trap directory # block - tell the smtp sender what we Worn n't take the mail # drop - accept the mail # Drop - Accept Mail, But Don't Queue It ## this will match any Executable Visual Basic Scripts VisualBasic :: Block :: ^ Content-Type: Application / OcTet-stream; / S Name = "(. * /. VBS): : Shs :: block :: ^ Content-Type: Application / OcTet-Stream; / S Name = "(. * /. Shs)" :: shb :: block :: ^ content-type: Application / Oct-stream ; / s name = "(. * /. shb)" :: com :: block :: ^ content-type: Application / OcTet-stream; / s name = "(. * /. com)" :: EXE: Block :: ^ Content-Type: Application / OcTet-Stream; / S Name = "(. * /. EXE)" :: Scr :: Block :: ^ Content-Type: Application / OcTet-stres; /S name="(.*.scr) ":: pif :: block :: ^ content-type: Application / OcTet-stream; / s name =" * /. PIF) ":: bat :: block :: ^ content-type: Application / OCTET-stream; / s name =" (. * /. BAT) "::
# This is the outlook date overflow bug date :: block :: ^ Date:. {160,} ::
Built a QMFILT file under / var / log, the content is empty chown qmails to establish a QMFILT directory under / var / qmail. Chown -r qmails is ok, let's enable our program to test the /var/qmail/bin/qmfilt.py --Test If returned to the first defined QMFil, congratulations. The content should be similar to the following: Filter - VisualBasic - Action: Block Regex: ^ Content-Type: Application / OcT-Stream; / S Name = "(. * /. VBS)" FILTER - SHS - ACTION: Block Regex: ^ Content-Type: Application / OCTET-Stream; / S Name = "(. * /. Shs)" Filter - SHB - Action: Block Regex: ^ Content-Type: Application / OCTET-STREAM; / S NAME = "(. * /. SHB)" Filter - COM - ACTION: Block Regex: ^ Content-Type: Application / OcTet-stream; / S Name = "(. * /. COM)" Filter - EXE - ACTION: Block Regex: ^ Content-Type: Application / OcTet-Stream; / S Name = "(. * /. EXE)" FILTER - SCR - ACTION: Block Regex: ^ Content-Type: Application / OcTet-stream; / S Name = "(. * /. SCR)" FILTER - PIF - ACTION: Block Regex: ^ Content-Type: Application / OcTet-Stream; / S Name = "(. * /. PIF)" Filter - Bat - Action : Block regex: ^ Content-Type: Application / OcTet-Stream; / S Name = "(. * /. BAT)" FILTER - DATE - ACTION: Block Regex: ^ Date:. {160,} Ok, let Our filter uses the CD / USR / local / vpopmail / etc. TCP.smtp content is as follows 127.:Allow ,ylayclient="" ,qmailqueue ="bin/qmfilt.py ": allow, qmailqueue =" bin / qmfilt. PY "then generate tcp.smtp.cdb text TCPRULES TCP.SMTP.CDB TCP.SMTP.TMP You can define the specified code you need to filter in the qmfilt file of / var / qmail / control, and then the test rule has taken effect. About SMS arrival notice, because of security and business problems. You cannot post the code of the server. I will tell you the mechanism. QMFilt.py This program will be sent to the specified server with UDP with UDP. After the server receives this packet, send the content of this packet with SMS. Of course, you can send information such as mail topics to your mobile phone, and you can change it according to your own situation. This program is based on http://sourceforge.net/projects/qmfilt/, but directly uses his code to cause can't be confident, you can pay attention to his code modification in this project. End, thank you!