Adding SpamAssassin filtering to your mail server

posted | about 6 minutes to read

tags: dovecot postfix sieve spamassassin tutorial system administration

This post is part of a series:
  1. A definitive Postfix/Dovecot mail server guide
  2. Adding SpamAssassin filtering to your mail server

Last week, I finally decided it was time to move forward with getting all of my mail self-hosted. I’d been using my mail server primarily for sending automated messages, but my previous mail service was really limiting me in terms of what I was able to do, so I finally bit the bullet and went for it. Of course, as soon as I did, I found myself overwhelmed - all of the stuff that had previously just filtered into the spam folder wasn’t filtering anymore. I had neglected to set up any filtering! I went and looked for some tutorials, but I ran into the same problem as I did when I was first setting up my mail server - all of the top Google results are missing a bunch of key information - so I’m going to give this the same treatment as I did the initial Postfix/Dovecot setup guide and walk through start to finish. As part of this effort, I’ve also updated the initial setup guide to include some additional configuration to make using the server more user friendly out of the box and to make it easier to work through this guide.

I’m going to assume you’ve started with my initial setup guide and have a working mail server, and proceed from that point. This should take about an hour or so to get through, including setup as well as testing.

Setting up SpamAssassin

The first step is, obviously, downloading and setting up SpamAssassin. You can do this on Debian-based Linux distributions with apt-get install spamassassin spamc or, on Fedora derivatives, yum install spamassassin spamc. Since I’m running on Debian, the debian-spamd user automatically gets created for me, but if your distro doesn’t do this, make sure to create a user. I’m going to reference debian-spamd in the guide, but just replace that with your created user if necessary.

Once you’ve got this installed, go ahead and create a log directory so if we need to keep an eye on things we can - I used /var/log/spamassassin - and then change ownership of the directory to your spamassassin user.

Next, open up /etc/default/spamassassin and check the following:

Finally, we need to configure the SpamAssassin settings. Open /etc/spamassassin/ Most of these options won’t need to be messed with. I made the following changes in my environment:

Go ahead and run systemctl start spamassassin at this time. The service is configured and ready to start reviewing your email.

Next, we need to configure Postfix to actually use SpamAssassin as a content filter.. All the changes here need to be made in /etc/postfix/

After the first uncommented line, add:

Then, go to the bottom of the file and add the following:

Here, double check the /usr/sbin/sendmail path above. This should match the folder path in the sendmail_path variable in /etc/postfix/ and may vary based on your distribution.

Also, you’ll need to remove or comment out the header_checks stuff we did in the last tutorial - while that was fine for what we were setting up then, at this point we need to let SpamAssassin handle the headers.

Once you’ve made the above edits, run a quick postfix check to see if it spots any config issues and resolve as necessary. Then, systemctl postfix reload and you’re good to go.

Implementing a Sieve filter

What you’ll notice at this point is that even though you have spam getting tagged by SpamAssassin, it’s not going to your junk mail. This is because we haven’t told Dovecot how to actually handle mail marked as spam. We’re going to use Sieve to fix that, which is a pretty widely used ruleset for sorting mail. Run apt-get install dovecot-sieve dovecot-managesieved or the appropriate equivalent for your distro to get the packages you’ll need.

First, we’ll make the changes to the Dovecot config. Open up /etc/dovecot/dovecot.conf and add the following block:

plugin {
  sieve = ~/.dovecot.sieve
  sieve_default = /var/lib/dovecot/sieve/spamassassin.sieve
  sieve_dir = ~/sieve
  sieve_global_dir = /var/lib/dovecot/sieve

Also, add mail_plugins = $mail_plugins sieve to the protocol lmtp { block in this file. Save and exit, but don’t restart Dovecot yet - we still need to set up the actual Sieve filter.

Navigate to /var/lib/dovecot and create a new sieve directory here. Inside there, create spamassassin.sieve with the following contents:

require ["fileinto", "mailbox"];

if header :contains "X-Spam-Flag" "YES" {
  fileinto :create "Spam";

Basically all we’re doing here is checking to see if SpamAssassin has flagged something as spam, and if so, moving it directly to the Spam folder. (If you named your Spam folder something different in the namespace inbox { block in /etc/dovecot/dovecot.conf, use that instead here.) Run sievec spamassassin.sieve to compile the Sieve rule, and then chown vmail:vmail spamassassin.* to get the ownership set properly.

At this point, you can restart Dovecot. It should now route mail properly to your Spam folder.

Sieve is super powerful, so you can also use it to write any custom routing rules that you might want in your mailbox. You can also do this on a user by user basis by editing the .dovecot.sieve file in the root of any user’s mail directory in /var/vmail if you don’t want to set rules globally.

Testing your setup

If you don’t receive much spam or haven’t put your system into production yet, there’s something called the GTUBE that you can use to make sure that things are working as intended. Send an email to an address on your mailserver with the following string:


If everything’s set up correctly, this should filter to your Spam folder and show as having a spam score of about 1000.

That’s all there is to it - if you’ve gotten this far, you’ve successfully configured spam filtering on your mailserver! Please drop a line in the comments below if this helped you or if you have suggestions to improve the guide.