Today I am going to show how to create a simple spam filter running on your linux box using SpamAssassin and Postfix. It basically works on any linux distribution which has these 2 packages installed.
I am going to assume that you already have a fresh install of postfix and spamassasin.
Spamassasin: how to create a simple spam filter using bash and spamc
First we have to create a linux user. The spam filter will run under that user. I am going to use user: spamcheck for now:
1 | # useradd -d /var/spamcheck -m -c "SpamAssasin Filter" -s /bin/false spamcheck |
Then we create a filter file which invoques spamassassin‘s binary spamc. Name the file spamcheck for example and create it in /bin/spamcheck with the following content:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #!/bin/bash # ----------------------------------------------------------------- # File: spamcheck # Purpose: SpamAssassin shell-based filter # Location: /bin # Usage: Call this script from master.cf (Postfix) # Certified: CentOS (any version), Spamassassin 3.x, Postfix # ----------------------------------------------------------------- # Variables SENDMAIL="/usr/sbin/sendmail -i" EGREP=/bin/egrep # Exit codes from EX_UNAVAILABLE=69 # Number of *'s in X-Spam-level header needed to sideline message: # (Eg. Score of 5.5 = "*****" ) SPAMLIMIT=10 # Clean up when done or when aborting. trap "rm -f /var/filter/out.$$" 0 1 2 3 15 # Pipe message to spamc cat | /usr/bin/spamc -u filter | sed 's/^\.$/../' > /var/filter/out.$$ # Are there more than $SPAMLIMIT stars in X-Spam-Level header? : if $EGREP -q "^X-Spam-Level: \*{$SPAMLIMIT,}" < /var/filter/out.$$ then # Option 1: Move high scoring messages to sideline dir so # a human can look at them later: # mv out.$$ $SIDELINE_DIR/`date +%Y-%m-%d_%R`-$$ # Option 2: Divert to an alternate e-mail address: $SENDMAIL admin@vrem.ro < /var/filter/out.$$ # Option 3: Delete the message # rm -f /var/filter/out.$$ else $SENDMAIL "$@" < /var/filter/out.$$ fi # Postfix returns the exit status of the Postfix sendmail command. exit $? |
Now set the right permissions the SpamAssasin shell script and /var/spamcheck folder:
1 2 3 | # chown root:spamcheck /bin/spamcheck # chmod 755 /bin/spamcheck # chmod 777 /var/spamcheck |
Now go to postfix configuration folder (/etc/postfix) and edit master.cf file. Add somewhere at the beggining of the file the entry bellow:
1 2 3 | # Spam Check with SpamAssassin spamcheck unix - n n - 10 pipe flags=Rq user=filter argv=/bin/spamcheck -f ${sender} -- ${recipient} |
Spamassassin filter test
Save the file and reload postfix (service postfix reload). Spamassassin daemon (spamd) daemon should be running in order to have a working spam filter for postfix. You can check the status of spamd using:
1 | # service spamd status |
Send yourself an email and check postfix logs (tail -f /var/log/maillog) to see if the filter is working. If you’re seeing something like in the link bellow, then you succeded:
1 2 3 4 5 6 7 8 9 10 11 12 | Jun 26 21:34:38 zira postfix/qmgr[20148]: 80F39261795: from=<myemail@gmail.com>, size=1823, nrcpt=1 (queue active) Jun 26 21:34:38 zira spamd[9697]: spamd: connection from localhost [127.0.0.1] at port 42727 Jun 26 21:34:38 zira spamd[9697]: spamd: processing message <CANLJf1oeYowX_7+_mV-sGOD4apFbWXvYmmX3PTWZEirSgNyCkg@mail.gmail.com> for filter:496 Jun 26 21:34:39 zira postfix/smtpd[20175]: disconnect from mail-ie0-f171.google.com[209.85.223.171] Jun 26 21:34:40 zira spamd[9697]: spamd: clean message (-7.5/5.0) for filter:496 in 1.8 seconds, 1911 bytes. Jun 26 21:34:40 zira spamd[9697]: spamd: result: . -7 - AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,HTML_MESSAGE,MTX_FAIL,MTX_NONE,RCVD_IN_DNSWL_LOW,SPF_PASS,USER_IN_WHITELIST_TO scantime=1.8,size=1911,user=filter,uid=496,required_score=5.0,rhost=localhost,raddr=127.0.0.1,rport=42727,mid=<CANLJf1oeYowX_7+_mV-sGOD4apFbWXvYmmX3PTWZEirSgNyCkg@mail.gmail.com>,bayes=0.000000,autolearn=ham Jun 26 21:34:40 zira spamd[25164]: prefork: child states: II Jun 26 21:34:40 zira postfix/pickup[20149]: E407526185B: uid=502 from=<myemail@gmail.com> Jun 26 21:34:40 zira postfix/cleanup[20186]: E407526185B: message-id=<CANLJf1oeYowX_7+_mV-sGOD4apFbWXvYmmX3PTWZEirSgNyCkg@mail.gmail.com> Jun 26 21:34:40 zira opendkim[1115]: E407526185B: no signing table match for 'myemail@gmail.com' Jun 26 21:34:40 zira postfix/pipe[20187]: 80F39261795: to=<myemail@server_with_spam_filter>, relay=spamcheck, delay=2.5, delays=0.51/0.01/0/2, dsn=2.0.0, status=sent (delivered via spamcheck service) Jun 26 21:34:40 zira postfix/qmgr[20148]: 80F39261795: removed |
1 Comment
Append the following line for local mail delivery to all virtual domains listed inside the MySQL table. Finally, we need to add these three parameters to tell Postfix to configure the virtual domains, users and aliases.