This page is about how to install and use SpamAssassin for Sendmail on FreeBSD. Tested on FreeBSD 14.3.
What is SpamAssassin?
SpamAssassin is a filter system, that can detect spam mail. SpamAssassin is an open source project, that has been offered by Apache since 2001. The filter can be implemented as a mail filter for mail servers, such as Sendmail. Such a mail filter is also known as a milter. Unfortunately, the official documentation and the FreeBSD install instructions are rather old and outright wrong.
https://spamassassin.apache.org
How does SpamAssassin work?
SpamAssassin reads the headers of email and use a set of rules to detect known spam characteristics and apply a spam score to the headers. Email clients can then use this score to identify the email as spam and move it to another inbox for spam or trash.
Below, is an example of SpamAssassin score headers in a filtered message, that spoofed a Google GMail account and presented a crypto extortion scheme.
X-Spam-Checker-Version: SpamAssassin 4.0.2 (2025-08-27) on wopr
X-Spam-Flag: YES
X-Spam-Level: ********************
X-Spam-Status: Yes, score=20.7 required=3.8 tests=BITCOIN_EXTORT_01,
BITCOIN_SPAM_05,DKIM_ADSP_CUSTOM_MED,FORGED_GMAIL_RCVD,
FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,GB_HASHBL_BTC,HELO_MISC_IP,
NML_ADSP_CUSTOM_MED,RCVD_IN_BL_SPAMCOP_NET,RCVD_IN_DNSWL_BLOCKED,
RCVD_IN_MSPIKE_BL,RCVD_IN_MSPIKE_L5,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,
RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED,
RCVD_IN_ZEN_BLOCKED_OPENDNS,RDNS_NONE,SPOOFED_FREEMAIL,
SPOOFED_FREEMAIL_NO_RDNS,SPOOF_GMAIL_MID,SUBJ_ALL_CAPS,URIBL_BLOCKED,
URIBL_DBL_BLOCKED_OPENDNS autolearn=spam autolearn_force=no
version=4.0.2
Install SpamAssassin on FreeBSD.
# pkg install spamass-milter
Check the default configuration.
# cat /usr/local/etc/mail/spamassassin/init.pre | grep -v '^#' | grep -v '^$'
enable_compat welcomelist_blocklist
loadplugin Mail::SpamAssassin::Plugin::URIDNSBL
# cat /usr/local/etc/mail/spamassassin/local.cf | grep -v '^#' | grep -v '^$'
ifplugin Mail::SpamAssassin::Plugin::Shortcircuit
endif # Mail::SpamAssassin::Plugin::Shortcircuit
Update spam detection rules.
# sa-update && sa-compile
Test SpamAssassin with ham and spam manually.
You can filter mail folders through SpamAssassin and inspect the results in the mail client. In this example, ham and spam mail folders for Alpine is used for testing SpamAssassin manually. Alpine use the MBOX format.
$ ls mail
Ham Spam
$ spamassassin --mbox < mail/Ham > mail/SpamAssassin
$ spamassassin --mbox < mail/Spam >> mail/SpamAssassin
$ alpine
The spam mail folder can later be used for training SpamAssassin, which can scan it regularly.
You can also save ham and spam messages as plain-text files and filter those through SpamAssassin.
Settle on a maximum spam score.
Settle on a spam score for future use in the configuration. The default is 5. If DNS block lists are unavailable due to IP address range block or rate limiting, which is common, I recommend a score closer to 3,2.
Configure SpamAssassin.
If you want SpamAssassin to learn from human marked spam, then create a directory for such database.
# mkdir -m 700 -p /usr/local/etc/spamassassin
# nano /usr/local/etc/mail/spamassassin/init.pre
# cat /usr/local/etc/mail/spamassassin/init.pre | grep -v '^#' | grep -v '^$'
loadplugin Mail::SpamAssassin::Plugin::URIDNSBL
enable_compat welcomelist_blocklist
# nano /usr/local/etc/mail/spamassassin/local.cf
# cat /usr/local/etc/mail/spamassassin/local.cf | grep -v '^#' | grep -v '^$'
score RDNS_NONE 2.8
required_score 3.2
use_bayes 1
bayes_auto_learn 1
body_part_scan_size 200000
rawbody_part_scan_size 2000000
ifplugin Mail::SpamAssassin::Plugin::Shortcircuit
bayes_path /usr/local/etc/spamassassin/bayes
bayes_auto_learn 1
endif # Mail::SpamAssassin::Plugin::Shortcircuit
Test the Bayes learning and the new settings.
# sa-learn --spam /home/lightman/mail/Spam
If DNS block lists are unavailable due to IP address range block or rate limiting, which is common, then you might want do disable the use of DNS. This is probably especially a good practice for higher volume mail servers to maintain speed.
Configure FreeBSD to start SpamAssassin.
If the spam score reaches 10, then the message will be rejected at the port.
# nano /etc/rc.conf
# grep spam /etc/rc.conf
spamd_enable="YES"
spamd_flags="-c --max-children=10"
spamass_milter_enable="YES"
spamass_milter_socket="/var/run/spamd/spamass-milter.sock"
spamass_milter_flags="-r 10 -f -u spamd -p ${spamass_milter_socket}"
# find /usr/local/etc/rc.d -name '*spam*'
/usr/local/etc/rc.d/sa-spamd
/usr/local/etc/rc.d/spamass-milter
# service sa-spamd start
# service spamass-milter start
# ls -l /var/run/spamd
total 1
srw-r--r-- 1 root wheel 0 Mar 12 02:09 spamass-milter.sock
-rw-r--r-- 1 root spamd 5 Mar 9 18:19 spamd.pid
Configure Sendmail to use SpamAssassin milter on FreeBSD.
# cd /etc/mail
# nano $(hostname).mc
# grep spamassassin $(hostname).mc
INPUT_MAIL_FILTER(`spamassassin',`S=local:/var/run/spamd/spamass-milter.sock, F=T, T=C:15m;S:4m;R:4m;E:10m')
# make && make install
# service sendmail restart
# cd
Configure CRON for SpamAssassin.
# nano bin/spamassassin-update
# cat bin/spamassassin-update
#!/bin/sh
sa-update && sa-compile
service sa-spamd restart
service spamass-milter restart
sa-learn --spam /home/lightman/mail/Spam
# chmod 700 bin/spamassassin-update
# spamassassin-update
# nano /etc/crontab
# grep spam /etc/crontab
37 13 * * 5 root /root/bin/spamassassin-update >/dev/null 2>&1
# service cron restart
Configure Dovecot IMAP server for handling spam.
I am still testing this feature. If you have tips, let me know. Thanks.
If the server runs Dovecot IMAP server, or a similar IMAP server, it might support automatic handling of spam mail by reading mail headers, creating user spam folders and moving spam into those. The Pigeonhole Sieve plug-in for Dovecot can do this.
# pkg install dovecot-pigeonhole
Create the global script and compile it.
# mkdir -p /usr/local/etc/dovecot/sieve
# nano /usr/local/etc/dovecot/sieve/global.sieve
# cat /usr/local/etc/dovecot/sieve/global.sieve
require ["fileinto", "imap4flags"];
if header :contains "X-Spam-Flag" "YES" {
fileinto "Spam";
stop;
}
# sievec /usr/local/etc/dovecot/sieve/global.sieve
Configure Dovecot.
# nano /usr/local/etc/dovecot/dovecot.conf
# cat /usr/local/etc/dovecot/dovecot.conf | grep -v '^#' | grep -v '^$' | tail -n 6
protocol lda {
mail_plugins = sieve
}
plugin {
sieve_global_path = /usr/local/etc/dovecot/sieve/global.svbin
}
# service dovecot restart
Configure Alpine or other mail client for handling spam.
You can now configure your mail client for handling spam. The spam features of mail clients include looking in mail headers and using this information to move the mail to a spam folder or deleting it outright.
In Alpine, you can go to “Setup”, “Rules” and “Filters”. Here, you can create filtering rules. Create a new filter. If it has an “X-Spam-Status” mail header and the the value is “Yes”, then move the message to the “Spam” folder. You can also use other spam headers and options.
X-Spam-Checker-Version: SpamAssassin 4.0.2 (2025-08-27) on wopr
X-Spam-Flag: YES
X-Spam-Level: ********************
X-Spam-Status: Yes, score=20.7 required=3.8 tests=BITCOIN_EXTORT_01,
BITCOIN_SPAM_05,DKIM_ADSP_CUSTOM_MED,FORGED_GMAIL_RCVD,
FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,GB_HASHBL_BTC,HELO_MISC_IP,
NML_ADSP_CUSTOM_MED,RCVD_IN_BL_SPAMCOP_NET,RCVD_IN_DNSWL_BLOCKED,
Check SpamAssassin related entries in the system mail log.
Check for issues by following and scanning the system mail log, investigate specific messages and adjust configuration as necessary.
# tail -f /var/log/maillog
# grep -e spamc -e spamass /var/log/maillog
# grep 62CDwYJl046101 /var/log/maillog
