Spamassassin-Postfix in Debian Etch

For the HOME server or low volume business


Last Updated March 15th 2012 SEE BOTTOM
This post is a bit of a mess at the moment so be sure to read it all the way through before you begin. I'll reformat it when I get time and inclination. In this post I present my setup experience with spamassassin first, then later I add Real Time Blackhole lookup to Postfix to block mail before it even hits spamassassin. I suggest you get spamassassin working first before you add RBL's. They generate additional internet traffic per message that may not be necessary.

First you need to get postfix working so you can insert spamassassin filtering in the deliver mechanism.
Make sure Postfix delivers mail to the ~/Maildir directory before continuing...

For Postfix setup instructions from scratch, See:

Make sure it works FIRST, adding procmail to a non working or untested mail delivery system will only make things worse.
Send yourself mail from an outside source. I've used this one before.

Don't continue unless you are able to receive mail and have verified the mail is being delivered to the users Mail/ directory.

Now that it's working, we'll make a few changes:
Install spamassassin using default distrubution and make sure procmail is installed

#apt-get install spamassassin procmail

First, enable spamassassin.
Change /etc/default/spamassassin to enabled like this:
My system is very low volume so I only allow three child processes. You may need to alter the --max-children option
Common sense tells me this is the maximum number of active spamd processes that will be spawned for mail. If you are likely to have more than three connections open on port 25 you probably should increase this number. See the Wiki at: Spamassassin Procmail and Postfix for more information

# /etc/default/spamassassin
# Duncan Findlay
# WARNING: please read README.spamd before using.
   # There may be security risks.
# Change to one to enable spamd
# Options
   # See man spamd for possible options. The -d option is automatically added.
# SpamAssassin uses a preforking model, so be careful! You need to
   # make sure --max-children is not set to anything higher than 5,
   # unless you know what you're doing.
OPTIONS="--create-prefs --max-children 3 --helper-home-dir"
# Pid file
   # Where should spamd write its PID to file? If you use the -u or
   # --username option above, this needs to be writable by that user.
   # Otherwise, the init script will not be able to shut spamd down.
# Set nice level of spamd
#NICE="--nicelevel 15"

Then start spamassassin

#/etc/init.d/spamassassin restart

Spamassassin (spamd) runs as a daemon. Whem mail comes in, procmail calls spamassassin (the daemon name) which executes spamc to actually filter the mail. This setup decreases the time it takes to load an instance of spamd (config and cf files are already scanned) and a spearate instance of spamc is neceeary to guarantee a unique pipe for each postfix process. It's a slick setup, thanks to Duncan & CO.

If you installed postfix using defaults and haven't changed them, procmail is already in the delivery loop (Debian etch install default). If you followed the How To Forge guide at the link above, it's been removed after testing authentication. Noted here so you don't get confused later. But you'll still need to look at the procmailrc and verify it's similar or just like that below. Be careful, if you see :0fw and other stuff in the procmailrc, it got there somehow. If you are the only person installing software, make your file looks exactly like below before you proceed. Otherwise your mail might not get delivered. If there is already a procmailrc you may want to just rename it and create a new one so you have a copy of any changes that have been added already.

You need to make a few changes to the default setup to get procmail to deliver mail to Maildir/ style folders.
The default procmail install has no /etc/procmailrc so you'll need to create one

Create /etc/procmailrc and make it look like below.
nano /etc/procmailrc

MAILDIR =       $HOME/Maildir/
#LOGFILE =      $MAILDIR/from
LOCKFILE=       $HOME/.lockmail

THIS IS THE FIRST VERSION, we'll add a few lines at tbe bottom after we are sure it's working.

Logfile is optional and will create a log of who delivered mail in the users Maildir/ directory.
Now enable procmail in postfix and restart postfix:

#postconf -e 'mailbox_command = /usr/bin/procmail -a $EXTENSION'
#/etc/init.d/postfix restart

At this point spamassassin is running but not in the mail delivery loop...
Procmail will be called for each incoming mail and deposit that mail into the appropriate users ~/Maildir
Send yourself mail to be sure it's getting delivered. This should work using courier or dovecot or any other Maildir/ mail delivery system. Keep in mind that neither dovecot or courier are effected at this point. Only postfix and it's delivery mechanism so don't go changing dovecot or courier to find your mail if it's not being delivered. It will end up in /var/mail if your config is not correct but don't change any of the directories, just make sure procmail is configured correctly. In this mode procmail does nothing at all, it will run for all incoming mail and deliver mail normally so it's kind of a waste unless you are going to filter or redirect mail.

In case your delivery gets messed up:
#postconf -e 'mailbox_command ='
#/etc/init.d/postfix restart
This will reset postfix to normal deliver, without procmail.
Be sure postfix is set to "Maildir/" style mailboxes or things will go south real fast. (home_mailbox = Maildir/ in /etc/postfix/ )

Send yourself more test email and make sure it's delivered to your ~Maildir/
Verify mail is actually in ~/Maildir folder again to be sure so you don't get confused. Both Dovecot and Courier will try to find where postfix puts mail, which can mess us up at this stage if you're not careful.

[*note] Based on my understanding of how this works; Spamassassin does not deliver mail, it just filters it. Procmail uses a temporary open ended file called a pipe to send mail through spamassassin which is then input to procmail so it could be processed further if desired. Since procmail's default output is Maildir/ that's were the mail it ends up because that's where we set the default procmail output. That means that procmail is an active pipe (provided by an executable vs a Unix | pipe) and spamassassin is configured as it's input by the settings in procmailrc. Understaniding this simple flow makes all the difference when configuring spamassassin features. This is apparently not the only way to use spamassassin with postfix. there is also a mail filter option in postfix that will pipe incoming mail through spamassassin as a filter directly but I haven't tried it. In that case the filtered mail would be returned to /var/mail where postfix would deliver it normally. I'm not sure what the rationale for using procmail is in relation to filters. I suspec it's because procmail is easier to configure and much more flexible than using a filter alone plus filters can be difficult to debug. If I get the postfix filter option to work I'll post config for that as well. I have a separate sever to play with...:) It may also be a performance issue. It may also be faster using the mail filter option but somewhat confusing so everybody hurd's to the known working config rather than figure it out for themselves. Like us?

The initial default spamassassin config will work for starters but you may want to add some extra .cf files to filter more specifically. See Google search for spamassassin filters and check my I found a few useful .cf scripts and such (chickenpox etc) that are very effective at tagging hairballs, grime, gak, chicken legs, fish odors, smutty momma's, penile insults, medical scams, nice watches for almost nothing, expensive software for almost nothing, and other undesirable email things...

Now that you've tested things you can add spamassassin to the mix and test it again.For testing, try filtering all mail by making it look like below by adding the italic parts. You can customize spamassassin options on a per-user basis by moving the italicized code to ~/procmailrc for the appropriate user. There are even some GUI's that will write such a file and more from screen options.

MAILDIR =       $HOME/Maildir/ 
#LOGFILE =      $MAILDIR/from
LOCKFILE=       $HOME/.lockmail
| /usr/bin/spamassassin

The ":0fw" colon-zero-f-w is a filtering option for procmail, see the procmail docs for more uses. It's essentially telling procmail to send ALL mail through spamassassin via a system pipe because it's in the /etc/procmailrc config file. Mail can then be processed further if necessary or desired. One could use another pipe to add text if a subject matched "xyz" or whatever... Again, adding this to a user specific procmailrc (/home/username/procmailrc) causes it to be applied only to that user.

Save the file, no need to restart spamassassin at this point since it wasn't modified and procmail has no daemon. This example /etc/procmairc works on low volume systems like my home server that gest spammed by off shore sites thinking you have gold in your coffers or stubs in your pants...;)

Test your setup again. If it won't work try stopping postfix, spamassassin and courier or dovecot. Then restart spamassassin first, then postfix then courier or dovecot and test it again. If it still won't work, restart the system before you modify more files. Sometimes things need to be reset like file locks or pid files etc to start working properly. Test again...

If it still won't work, here are copies of my relevant files:
I also use several spamassassin .cf files that add spam checking beyond the default. You'll find them in /etc/spamassassin

DO NOT JUST COPY MY CONFIG TO YOUR SYSTEM, Postfix has system specific information like $mynetworks and $myhostname

I don't have a forum for discussion at the moment but you can email me with questions unless I get which case you'll get nothing...:
But you are welcome to post this elsewhere and someone will help you further.

Update Jan 5th 2008

As of yesterday, having gotten tired of seeing 20+ spam messages at a time and up to 50 or so a day, I added some useful Realtime Blacklist entries to postfix that prevent mail from certian places from even being accepted. Spamassassin is a great second line but I prefer not to even accept mail that's from known offshore or traitorous local sites. It's proven to be quite effective. To choose the proper RBL I simply examine the spam-x: header for which list or test it was rejected on then add that list to the config below. Be aware that these lists are not all the same. Some are sender restrictions and some are recepient restrictions and others are body tests that require additional software. Postfix will not work properly if they are put in the wrong place.

To add them: you can use Webmin or edit the postfix config directly.
In webmin, open servers ->postfix -> smpt server options.
At the bottom is a box where you can place the names of various RBL's. Make sure to tick the box to use the list... (duh)
I currently use:,
I also use have a sender restriction (up a few lines in the center of the screen) of: reject_rhsbl_sender

Save And Apply and you should be set.

To add RBL's to postfix manually:
EDIT /etc/postfix/

smtpd_client_restrictions = permit_mynetworks, reject_rbl_client, reject_rbl_client
default_rbl_reply = $rbl_code Service unavailable; $rbl_class [$rbl_what] blocked using $rbl_domain${rbl_reason?; $rbl_reason}
Look for the line "smtpd_client_restrictions" adding it if it's not there. The "defualt_rbl_reply" lets people know why their mail wont' be delivered. You'll probably need the permit_mynetworks (the postfix default) entry if you are on any kind of network. I have a server on the internet with NAT redirection to my Desktop. If I want to be able to send mail using pop3 I need to allow relaying from my internal networks. My internet firewall has all ports closed with the exception of the webserver (80) mail (25) In a business environment this may not be what you want (allowing all internal network users to relay mail or use IMAP) so you'll have to read the postfix documentation and/or find more information. This places a reject_rbl_client option in the postfix configuration so that it will check these lists for incoming IP addresses and deny them deliver if they are on any of the lists indicated.
Adding a SENDER restruction:
smtpd_sender_restrictions = reject_rhsbl_sender

This adds a scan through to all OUTGOING mail to help me notice if my mail system is being abused. It can also be useful in a business environment to prevent users from sending nonsense or heaven forbid ... spam! Rrfc_ignorant is mainly for tagging systems that don't adhere to, or completely ignore RFC mail standards. In this context it's a bit superflous but it illustrates how to use a "sender" restriction.

Now restart postfix and test the setup
#/etc/init.d/postfix restart

Spamhaus supplies a test server that echo's it's interaction with your server back to you in a message.
Send mail to: and if it's working properly you'll see something similar to this returned via email to your mail server.

Testing your SBL block. See for more info. Please note that this test will not tell you if your server is open for relaying. Instead, it tests to see if your server blocks email from IP addresses listed in various blocking lists; in this case, the SBL list. Here's how the conversation looked from Note that some sites don't apply the SBL block to postmaster, so I use your envelope sender as the To: address. I connected to and here's the conversation I had:

220 ESMTP Postfix (Debian/GNU)
mail from:<>
250 2.1.0 Ok
rcpt to:<>
554 5.7.1 Service unavailable; Client host [] blocked using;
Terminating conversation

This shows you that your configuration is indeed looking up addresses in the spamhaus database.
While you can mix SORBS or Spamhaus lists, I suggest you try the zen list from spamhaus. It's a combination list that works well for me.

I've added my current to an updated file for your convenience.
Please dont' use my config as your own, it's highly unlikely it will work. It's included here ONLY for reference and to help you get a decent, low spam mail system working. From experience the most useful .cf files are and Copy them to your /etc/spamassassin directory and restart the spamd daemon. With this RBL setup I see less than two spams a week and they are usually tagged by spamassassin. I have noted a few that get through so there is still work to be done.

#/etc/init.d/spamassassin restart

Output from my Logwatch for comparison:

Messages rejected using Anti-Spam site 170 Time(s) identified 170 spam messages:[] : 2 Time(s)[] : 2 Time(s)[] : 2 Time(s)[] : 4 Time(s)[] : 2 Time(s)[] : 2 Time(s)[] : 12 Time(s)[] : 8 Time(s)[] : 6 Time(s)[] : 2 Time(s)[] : 2 Time(s)[] : 2 Time(s)[] : 8 Time(s)[] : 6 Time(s)[] : 2 Time(s)[] : 2 Time(s)[] : 4 Time(s)[] : 4 Time(s)[] : 8 Time(s)[] : 2 Time(s)[] : 2 Time(s)[] : 2 Time(s)
  unknown[] : 4 Time(s)
  unknown[] : 2 Time(s)
  unknown[] : 2 Time(s)
  unknown[] : 2 Time(s)
  unknown[] : 4 Time(s)
  unknown[] : 4 Time(s)
  unknown[] : 8 Time(s)
  unknown[] : 4 Time(s)
  unknown[] : 8 Time(s)
  unknown[] : 2 Time(s)
  unknown[] : 2 Time(s)
  unknown[] : 2 Time(s)
  unknown[] : 2 Time(s)
  unknown[] : 2 Time(s)
  unknown[] : 2 Time(s)
  unknown[] : 2 Time(s)
  unknown[] : 4 Time(s)
  unknown[] : 2 Time(s)
  unknown[] : 12 Time(s)
  unknown[] : 2 Time(s)
  unknown[] : 12 Time(s)


Updated March 15th 2012

Newer versions of Postfix have come out since this was written and I've had more time to experiment with my setup to reduce spam as well as network traffic. Most of the above applies with the exception of RBL placement. In the above I used sender restrictions to scan IPs for know spam sites using blocklists. I find it better to place the RBL check under the recepient options instead. It works better and may reduce DNS lookup and/or IP lookup trafficfor incoming mail. I still use spamassassin as configured above but in my postfix config I have added the use of a map_rbl for and reduced the number of blocklists used. Of most importance is removing sender restrictions and adding the blocklists to the recipient restriction stage of the mail session. As you can see below I use the SORBS.NET list as the only filter for client restrictions (who connects). This means there is only one network hit upon connection which speeds up the session for valid mail. The maps_rbl_domans points to which looks up the address of who is connected and searches the blocklist, disconnecting if the client is listed. As you can see I have no sender restrictions. I've added recipient restricitons in a specific order below starting with zen.spamhaus then bl.spamcop then multi.surbl which is the recommended way to use these blocklists according to SURBL.ORG. They recommend using ZEN.SPAMHAUS as first line and SURBL.ORG as second. I've added SPAMHAUS to the list to reject known spammer because its more effective for me. Note I use an access_client blocklist for those that are persistent and aren't caught by the blocklists but the list seems unnecessary now so you can either add it or not, its up to you. Lastly, the header checks are a way to block based on content and although it works fine I find it slow and unnecessary now that my blocklists are working well. If you don't have any _checks files in your postfix/maps/ directory you can ignore the last three lines below. NOTE: If you are using Webmin you can easily add these checks through the menu system at any time and it will generate the files plus their databases for you.

Following are the relevant parts from my

maps_rbl_domains =
smtpd_client_restrictions = sleep 1 reject_unauth_pipelining check_client_access hash:/etc/postfix/maps/access_client reject_unknown_reverse_client_hostname reject_maps_rbl

smtpd_recipient_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination reject_invalid_hostname reject_non_fqdn_sender reject_unknown_sender_domain reject_non_fqdn_recipient reject_unknown_recipient_domain reject_rbl_client reject_rbl_client reject_rbl_client

header_checks = regexp:/etc/postfix/maps/header_checks
mime_header_checks = regexp:/etc/postfix/maps/mime_header_checks
body_checks = regexp:/etc/postfix/maps/body_checks
Just click above and send it as-is and I'll know you found it useful.