Apache SpamAssassin is a long-established spam filter that scores messages using hundreds of rules, DNS blocklists and Bayesian learning. If a message's score passes a threshold, it is marked as spam. This guide installs SpamAssassin and connects it to Postfix.
Before you start
- A working Postfix mail server with root access.
- A local DNS resolver is recommended so blocklist lookups are not rate-limited.
Tip: On MdmHost cPanel hosting SpamAssassin is already available – turn it on per account in cPanel → Email → Spam Filters. This guide is for self-managed servers.
Install SpamAssassin
- Ubuntu/Debian:
sudo apt install -y spamassassin spamc spamass-milter - AlmaLinux/Rocky:
sudo dnf install -y epel-release && sudo dnf install -y spamassassin spamass-milter
Enable the daemon: sudo systemctl enable --now spamd (service may be spamassassin on older Debian/Ubuntu releases).
Configure scoring
Edit /etc/spamassassin/local.cf (AlmaLinux: /etc/mail/spamassassin/local.cf):
required_score 5.0
rewrite_header Subject [SPAM]
report_safe 0
use_bayes 1
bayes_auto_learn 1
whitelist_auth newsletter@trusted-example.com
blacklist_from *@spammy-example.net- required_score – 5.0 is the default; lower catches more spam but more false positives.
- report_safe 0 – adds headers instead of wrapping the message as an attachment.
- whitelist_auth – trusts a sender only when SPF or DKIM passes, which is safer than
whitelist_from.
Check the syntax with spamassassin --lint.
Connect SpamAssassin to Postfix
- Start the milter:
sudo systemctl enable --now spamass-milter. - Find its socket in the service defaults file (for example
/run/spamass/spamass.sockon Debian/Ubuntu,/run/spamass-milter/postfix/sockon AlmaLinux). - Add to
/etc/postfix/main.cf(or append to existingsmtpd_milters):smtpd_milters = unix:/run/spamass/spamass.sock milter_default_action = accept - Reload Postfix.
The milter adds X-Spam-Status and X-Spam-Flag headers; you can then file spam into Junk with a Dovecot Sieve rule.
Keep rules updated
sudo sa-update && sudo systemctl restart spamdMost packages install a daily cron job or timer for sa-update; check that it runs.
Train the Bayes filter
sa-learn --spam /home/user/Maildir/.Junk/cur
sa-learn --ham /home/user/Maildir/cur
sa-learn --dump magicBayes needs at least 200 spam and 200 ham messages before it is used. Run training as the same user spamd uses for its Bayes database.
Test it
Send yourself a message containing the GTUBE test string (published on the SpamAssassin website). It should score very high and be marked as spam.
Troubleshooting
- No X-Spam headers: the milter is not running or the socket path is wrong; check
journalctl -u spamass-milter. - Legitimate mail marked spam: view the rule hits in
X-Spam-Status; fix the sender's SPF/DKIM or whitelist withwhitelist_auth. - High CPU: lower
--max-childrenfor spamd or skip scanning large messages (spamc's default size limit helps).
FAQ: SpamAssassin
What is a good required_score?
Start with 5.0. If little spam gets through and you see false positives, raise it; if too much spam arrives, lower it slowly.
Should SpamAssassin reject mail?
Usually it tags mail and lets users' Junk folders handle it. Rejecting at SMTP time is possible for very high scores.
SpamAssassin or Rspamd?
Rspamd is faster and more modern; SpamAssassin is simple and integrated in many control panels.
