Courier and SpamAssassin

Date: 12 December 2006

Needed FreeBSD Ports

  • lang/perl5 SpamAssassin requires Perl 5.6 or higher. Note: Remeber to run use.perl ports before builing SpamAssassin.
  • mail/p5-Mail-SpamAssassin
  • databases/mysql40-server
  • databases/p5-DBD-mysql Needed so SpamAssassin can talk to MySQL

/usr/local/etc/mail/spamassassin/local.cf

I like to store users' settings in a MySQL database. See the SpamAssassin SQL README for instructions on setting that up.

user_scores_dsn                 DBI:mysql:Accounts:localhost
user_scores_sql_username        sa
user_scores_sql_password        <password>
user_scores_sql_table           SA_userprefs

MySQL Table

CREATE TABLE SA_userprefs (
         username        varchar(128)    default ''      NOT NULL,
         preference      varchar(30)     default ''      NOT NULL,
         value           varchar(100)    default ''      NOT NULL,
         prefid          int(11)         UNSIGNED        NOT NULL
auto_increment,
         PRIMARY KEY (prefid),
         INDEX (username)
) COMMENT = "Accounts' SpamAssassin preferences.";

GRANT SELECT,DELETE,INSERT,UPDATE on Accounts.* to
         sa IDENTIFIED by '<passwd>';

/usr/local/etc/rc.d/spamd.sh

You need to tell spamd to look for user settings in the database.

${PREFIX}/bin/spamd -x -d -q -u courier

/usr/local/etc/maildroprc

This step can be skipped if you are not using maildrop or do not want to quarantine Spam for your users.

Add this to maildroprc. Note: I create the Spam folder from a precreated folder if it doesn’t exist. You could use maildirmake to do it instead.

# Spam Filter
import RECIPIENT

xfilter "/usr/local/bin/spamc -u $RECIPIENT"

if (/^X-Spam-Status: Yes/:h)
{
`test -d "./Maildir/.Spam/"`
        if ($RETURNCODE != 0)
        {
                # If not, copy one from the pre-existing skel directory.
                `cp -Rp /usr/local/etc/courier/skel/Maildir/.Spam ./Maildir/`
        }
        to "./Maildir/.Spam/."
}

Rejecting High Scores

You may also want to reject messages that score over a certain level. Here’s how you do it.

MAX_SPAM=15

# Spam Filter
import RECIPIENT

xfilter "/usr/local/bin/spamc -u $RECIPIENT"

if (/^X-Spam-Status: Yes, score=!-*[:digit:]+\.[:digit:]+! .*/:h)
{
        # Extract the spam score.
        HITS=$MATCH2
        #       logfile "/var/log/maildrop.log"
        #       log "Hits: $HITS 0: $MATCH 1: $MATCH1 2: $MATCH2"

        if ($HITS >= $MAX_SPAM)
        {
                # Set to 0, then there's no quota. Needed to deliver to
                # this glorious spam drop box.
                MAILDIRQUOTA='0'
                echo "Spam score on message from $CLEAN_FROM to $LOGNAME exceeds maximum value. ($HITS/$MAX_SPAM)"
                EXITCODE=0
                exit
        }
        to "./Maildir/.Spam/."
}