Updated guide to getting seamless server side spam filtering running on Ubuntu
When I started using my mobile phone for email I quickly hit a problem - I needed server side spam filtering that could be trained on the go to keep email volumes reasonable. The solution described here provides just that: spam is automatically filtered out and marked as read on the server. Moving email from my inbox to spam folder or vice versa trains the spam filter automatically.
I originally solved the problem of per-user baysean spam filtering using dspam, writing up a short guide back in 2011. Time has marched on and dspam is no longer supported on Ubuntu, meaning that it's time to move to another solution.
This document describes setting up Postfix and Dovecot to integrate into Bogofilter through the Dovecot Antispam plugin. This arrangement means:
1. Only users that are configured to use Bogofilter have it running.
2. Moving emails in / out of the Junk folder triggers re-training of Bogofilter.
3. Spam filtering happens server side, making email workable on mobile devices.
There are lots of good tutorials on the web on how to do this part, so I'll not attempt to replicate them here. Do make sure that inbound and outbound email are fully working before attempting the rest of the steps, and make sure you have a backup of your working configuration!
Install bogofilter and postfix-pcre with apt-get install bogofilter postfix-pcre
.
Edit /etc/postfix/master.cf and add a new configuration line for bogofilter:
bogofilter unix - n n - 10 pipe
flags=Ru user=vmail argv=/usr/local/bin/bogofilter-scan.sh /var/spool/bogofilter/${recipient} ${sender} ${recipient}
Some explanation:
Setup a filter that will trigger bogofilter. To do this create a new file /etc/postfix/bogofilter_access:
/./ FILTER bogofilter:bogofilter
Now configure postfix to use this filter and so pass mail to bogofilter. Edit /etc/postfix/main.cf:
bogofilter_destination_recipient_limit = 1
smtpd_client_restrictions = permit_sasl_authenticated reject_rbl_client zen.spamhaus.org check_client_access pcre:/etc/postfix/bogofilter_access
Some explanation:
Add the script that runs Bogofilter for mail delivery - /usr/local/bin/bogofilter-scan.sh:
#!/bin/bash
#Arg 1 - directory of the user's Bogofilter DB
#Arg 2 - sender
#Arg 3 - Recipient
if [ ! -d $1 ]; then
tee | /usr/sbin/sendmail -i -f $2 $3
exit 0;
fi
/usr/bin/bogofilter -e -u -p -l -d "$1" | /usr/sbin/sendmail -i -f $2 $3
exit 0
Remember to make the script executable (chmod +x
) then test. If everything is working correctly you should now have an X-Bogosity header in incoming email.
Now that postfix and bogofilter can identify and flag an email as spam, I want to move it to a dedicated Spam folder per user. To do this I can use the sieve functionality in dovecot's LDA (Local Delivery Agent).
To kick things off we need to tell postfix how to deliver email through dovecot. Add the following to master.cf:
# Dovecot local delivery agent - allows us to use sieve filters for spam
dovecot unix - n n - - pipe
flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -f ${sender} -d ${recipient}
Note that I'm using the vmail user again so that all mail files are kept under a common ownership.
To make postfix use the dovecot delivery agent add the following to main.cf:
# Dovecot for local delivery
dovecot_destination_recipient_limit = 1
virtual_transport = dovecot
These two changes gets email as far as dovecot, now we need to configure dovecot to look for the spam headers and redirect it to the Spam folder if present:
In /etc/dovecot/conf.d/15-lda.conf enable the sieve plugin for the LDA:
protocol lda {
...
mail_plugins = sieve
...
In /etc/dovecot/conf.d/90-plugin.conf configure a location for storing the global sieve filter files:
plugin {
...
sieve_before = /etc/sieve/conf.d/before
sieve_after = /etc/sieve/conf.d/after
...
Now we need to create an appropriate filter that will check for the spam headers. I did this in /etc/sieve/conf.d/before/spam-folder.sieve (found here):
require ["regex", "fileinto", "imap4flags"];
# Catch mail tagged as Spam, except Spam retrained and delivered to the mailbox
if header :regex "X-Bogosity" "^(Spam)" {
# Mark as read
setflag "\\Seen";
# Move into the Junk folder
fileinto "Spam";
# Stop processing here
stop;
}
The final step is to compile the script ready for dovecot to use (discovered here):
sievec /etc/sieve/conf.d/before/
To test this part of the configuration out ensure that the user has an IMAP folder called "Spam" at the top level of their account. I'm not sure what happens if this doesn't exist, but I doubt it works.
I've tested this setp on Ubuntu 16.04 with apt-get install dovecot-antispam
. Earlier versions of Ubuntu were problematic (see the old guide from 2011).
Start by creating the script to run when moving email from spam to ham or vice versa - /usr/local/bin/bogofilter-mark-mail.sh:
#!/bin/bash
#Arg 1 - directory of the user's Bogofilter DB
#Arg 2 - spam or ham
if [ ! -d "$1" ]; then
exit 0;
fi
if [ "$2" == "ham" ]; then
/usr/bin/bogofilter -e -p -l -Sn -d "$1"
exit 0;
fi;
if [ "$2" == "spam" ]; then
/usr/bin/bogofilter -e -p -l -Ns -d "$1"
exit 0;
fi;
Remember to make the script executable (chmod +x
).
Enable the antispam plugin in /etc/dovecot/conf.d/20-imap.conf:
protocol imap {
...
mail_plugins = antispam
...
And then configure it in /etc/dovecot/conf.d/90-plugin.conf
plugin {
...
antispam_backend = pipe
antispam_debug_target = syslog
antispam_signature = X-Bogosity
antispam_signature_missing = move
antispam_spam = Spam
antispam_trash = trash;Trash;Deleted Items; Deleted Messages
antispam_verbose_debug = 1
antispam_pipe_program = /usr/local/bin/bogofilter-mark-mail.sh
antispam_pipe_program_args = /var/spool/bogofilter/%u
antispam_pipe_program_spam_arg = spam
antispam_pipe_program_notspam_arg = ham
antispam_pipe_tmpdir = /tmp
...
Now moving an email from the user's inbox to the Spam folder will trigger bogofilter to learn this email as spam, and vice versa.
Migrating from dspam to bogofilter means giving up all of the existing learning. To initialise the bogofilter with my existing server side mail I ran some bulk imports:
bogofilter -s -d /var/spool/bogofilter/colin@owlfish.com -B /var/spool/vmail/owlfish.com/colin/.Spam
bogofilter -n -d /var/spool/bogofilter/colin@owlfish.com -B /var/spool/vmail/owlfish.com/colin
I've been using dspam to do server side spam filtering for 6 years, making managing email much more pleasant. I need to see how well Bogofilter works in its place, but I'm hoping for similarly good results.
Please let me know if this page is of any help - and do send corrections and edits!
The full list of my published Software
Made with PubTal 3.5
Copyright 2021 Colin StewartEmail: colin at owlfish.com