Simple Spamassassin setup with Postfix and Dovecot on Ubuntu Breezy

Below is a simple Spamassassin setup for use with Postfix; I also cover how to train Spamassassin on a Maildir mail box (I use Dovecot).

Some of the below is cribbed from I've simplified it and left more of the configuration at the defaults. You don't have to do this on a locally-hosted Postfix server: the instructions are the same for any email server which can receive email (it just so happens mine isn't open to the outside world and is just passed email by fetchmail). I'm working on Ubuntu Breezy.

Disclaimer: Use these instructions at your own risk. I am not an expert on spam filtering: this set of instructions just gave me what I needed to do my own local spam filtering. If you set it up and it loses you the email clinching a one million dollar contract, I assume no responsibility.

By the way, you need to do all of the below as root.

Install Spamassassin

apt-get install spamassassin spamc

Configure Spamassassin user and group

We want it to run as non-root, so add a spamd user and group:

# groupadd spamd
# useradd -g spamd -s /bin/false -d /var/log/spamassassin spamd
# mkdir /var/log/spamassassin
# chown spamd:spamd /var/log/spamassassin

(This sets the spamd user's home directory as /var/log/spamassassin.)

Configure Spamassassin

Edit /etc/default/spamassassin so these options are set:



OPTIONS="--create-prefs --max-children 2 --username spamd \
-H ${SAHOME} -s ${SAHOME}spamd.log"

--max-children spawns the specified number of child processes (you might need more on a busy server), --username specifies the username spamd runs under, -H sets the home directory, -s sets the log file.

(I left the rest of the file alone, and didn't touch /etc/spamassassin/

Start the Spamassassin daemon (spamd)

/etc/init.d/spamassassin start

(By default, spamassassin gets added to the startup scripts by Ubuntu, so it will start/stop with your system.)

Configure Postfix to use Spamassassin as a filter

This makes Postfix pipe email to Spamassassin once it's been received. Edit /etc/postfix/ and add this line as the first line of the file:

smtp      inet  n       -       -       -       -       smtpd
        -o content_filter=spamassassin

Add this to the end of the same file:

spamassassin unix -     n       n       -       -       pipe
        user=spamd argv=/usr/bin/spamc -f -e  
        /usr/sbin/sendmail -oi -f ${sender} ${recipient}

I bet you're asking yourself "What the hell?!". I know I was. As far as I can tell, this sets up an after-queue content filter, and this config. does the following:

  1. Sets up a content filter called spamassassin with type unix (i.e. listening on a Unix socket).
  2. "- n n - -" means the filter is private, privileged (any pipe daemon needs privileges), not chrooted (pipe daemons can't be chrooted), has no wakeup set, and uses the default for maximum processes spawned, respectively.
  3. pipe sets the filter up using the pipe daemon: stuff gets passed into it by Postfix, then it either returns what was passed in, possibly changed (e.g. with headers added or the body sanitised), or a code indicating what the filter did.
  4. userd specifies the user to run the filter as.
  5. argv sets the command for the pipe daemon to run over messages (i.e. this is the actual filter command). In this case, the command is:
    /usr/bin/spamc -f -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}
    This runs spamc (the Spamassassin client program), piping its output into the sendmail command; spamc passes the email being filtered to the Spamassassin daemon (spamd) which is running in the background; spamc gets the email back with a few spam headers to show the email has been checked, and possibly with its content rewritten to show the standard Spamassassin "Spam detection software, running on the system 'briar', has identified this incoming email as possible spam" if the email is spam. The ${sender} and ${recipient} markers are interpolated by Postfix, so that sendmail can take the output from spamc and deliver the message with the correct from and to addresses.

Reload Postfix for the configuration to take:

/etc/init.d/postfix reload

Train the Spamassassin filter

This was the bit where I had to do the most research. I'm using Maildir format for my email, under dovecot; email for localhost accounts goes in /home/user/Maildir.

To do my training, I created a new Junk folder for my localhost Postfix account: I did this by adding the folder via Thunderbird. Next I got a load of existing spam from my Trash folder, and moved it to the Junk folder.

Then, to train the filter on the Junk folder, I used sa-learn like this (you need to be root, which is why the sudo is there):

sudo sa-learn --spam -u spamd --dir /home/ell/Maildir/.Junk/* -D

You can also train it what the good stuff looks like, e.g. run it over a clean inbox (no spam):

sudo sa-learn --ham -u spamd --dir /home/ell/Maildir/.INBOX/* -D

There are probably spam corpuses (corpi?) you can use for this or some other smart method I missed, but this seems to work.


Get the content out of an existing spam, send it to an account on your protected server from a free email account (you could even set up a Hotmail account to get the most accurate spam scenario), and see if Spamassassin marks it. Check the logs (/var/log/spamassassin and /var/log/mail.log) to see what happened to the email. If Postfix is using Spamassassin properly, you should see something like this in the logs:

Jan 26 14:56:10 localhost postfix/pipe[12139]: 9CBD5DA4BF: \
to=<ell@localhost>, relay=spamassassin, delay=17, status=sent (localhost)

(Notice the mention of postfix/pipe.)

Spamassassin might not mark the email, as it will be coming from a legitimate email address. The important thing is that the logs report that Spamassassin was applied.


I now get very little spam delivered to my inbox: most of it gets marked as spam by the Postfix server using Spamassassin, and Thunderbird deletes any emails with a SpamAssassin spam header for me. I periodically train the filter to make it improve, using the stuff Thunderbird has decided is junk.


Originally, this was at the top of this post, but it's kind of irrelevant. I've included it here so you know why I put myself through this lunacy.

I have a couple of legacy email accounts which still get the occasional proper email, plus endless spam. I use the excellent fetchmail to download email from these moribund accounts and send it to my local Postfix server instead. I then read my local email account via the Dovecot imap server (setup to use Maildir layouts) in the Thunderbird email client. A fairly complex setup, but one which has worked well for me over the past three or four years.

However, a vast amount of spam used to hit my old email accounts, and I'd have to wait for Thunderbird to sort it out (which it does well) once fetchmail passed it to the local Postfix server. I got tired of having to teach the Thunderbird junk controls, so decided instead to setup my local Postfix server with Spamassassin: the stuff that fetchmail then pulls down and sends to my local Postfix server goes through Spamassassin before it hits Thunderbird. As you can tell Thunderbird to trust Spamassassin SPAM headers, it will automatically delete anything which Spamassassin has already decided is spam. Which means I don't have to teach Thunderbird, and can just teach Spamassassin instead (which is an automatic process), and let it learn by itself too as it finds more spam.


The plural of "corpus" is

The plural of "corpus" is "corpora." HTH. :)

Really helpful even in december 2012

This was really helpful even in december 2012.

I just launched, and tries to avoid spam from the emails listed on the frontpage. This I hope helps.

What is the -f option for

spamassassin unix - n n - - pipe
user=spamd argv=/usr/bin/spamc -f -e
/usr/sbin/sendmail -oi -f ${sender} ${recipient}

This is a very elegant way of doing it - I have seen several examples that use a script to call spamc and in turn sendmail.
What is the -f for in the spamc call? It isn't in the man for spamc. Is this a typo?
Also the man page for spamc says for the -e option "Note that there is a very slight chance mail will be lost here, because if the fork-and-exec fails there's no place to put the mail message." I still like this option.

If anyone is curious, the -f

If anyone is curious, the -f option used to be a "fail-safe" switch instructing spamc to pipe out the message unscanned if it could not connect to spamd. Even at the time of the writing of this article it had long been obsolete, being the default behaviour.

> apt-get install

> apt-get install spamassassin spamc
Seems like a misprint.

Help! i cannot start spamassassin

I tried to follow but i got this error instead. I cannot start the spam assassin

Error as follow:

warn: archive-iterator: no access to start: 2 at /usr/share/perl5/Mail/SpamAssassin/ line 771.

Please help..

Crikey, I haven't got a clue

Crikey, I haven't got a clue I'm afraid. It's been a long time since I did this. Apologies for not being able to help.


Very helpful indeed.

Very useful

Thank you for this detailed guide, it works perfect in my Ubuntu Server 11.04.
Best regards!

The plural of 'corpus' ...

Is 'corpora'. And thanks for the lil' how-to. :)

there's always one...

there's always one...


After writing "There are probably spam corpuses (corpi?) you can use for this", you didn't expect anyone to comment with the correct form? Personally I couldn't care less which form people use, but it seemed like you actually wanted to know. Sorry if I offended you, that wasn't the intention.


correct form is 'corpora' (decl. IV.)

Apologies, I intended my

Apologies, I intended my response in a light-hearted fashion. Should have done a smiley probably. :)

Training question

Im also using Maidir format. But my setup differentiated from yours slightly. It looks like the root of my Maildir/ directory IS my inbox. That is to say I have no Maildir/.Inbox directory. The Maildir/ directory does however have the rest of the imap "folders" in it... Maildir/.Spam , Maildir/Trash for example.

My question is, would running:
sudo sa-learn --ham -u spamd --dir Maildir/* -D
also inadvertently drill into those .Spam, .Trash folders and improperly learn their contents as Ham? Im guessing not, but I don't know whats under the hood of sa-learn to be sure.

Thanks, John

To be on the safe side, I'd

To be on the safe side, I'd probably copy the mail from that directory somewhere else, and train on the copy.


Thanks for this, the magic Postfix config lines made it all work!

Glad it helped.

Glad it helped.


Just thanking you for the time you contributed to this article

Spamassassin and Spam Deletion

"most of it gets stopped by the Postfix server using Spamassassin"

I don't think this part is right. From

"SpamAssassin itself will not delete any emails. It's only a filter which reads email in, and passes that same email out, modified in some way. If you want to delete emails, or redirect emails, you need to do it in whatever program calls SpamAssassin. "

The site then goes on to explain how to set up a procmail filter to drop spam at the server, it that is what you want to do.

In your case, do you think what is happening is that Thunderbird's Bayesian filter can learn what is junk instantly because of SpamAssassin headers? Thus you can achieve your end result, very little spam in the Inbox, but all the filtering is done by Thunderbird. I don't see Postfix dropping mail on the floor. Please correct me if I am wrong.

Thank you for this mini-howto. I used it to set up Spamassassin on an Ubuntu server running Courrier IMAP in literally minutes, and it is working great. I also use Thunderbird. It is also easy to set a filter in Squirrelmail (web mail) to filter spamassassinated messages to the Inbox.Junk folder:

options/message filtering:

If Header contains X-Spam-Flag: YES then move to Junk

I'm pretty sure you're

I'm pretty sure you're right: a bad choice of wording by me. I think at the time I wrote this I realised what was happening with the headers and Thunderbird, and that SpamAssassin wasn't actually dropping anything. I just didn't express it very well.

Thanks for the guide. I'd be

Thanks for the guide. I'd be running with just rbl's but spam was getting through more and more. I installed spamassassin, and it correctly identifies most spam, I train it every time it misses something.

I forgot to mention I'm

I forgot to mention I'm running it on a vm, and io and memory can be an issue, but so far so good. I only let 2 spamassassin processes run at once.