Invoking DSPAM from Maildrop

Using maildrop, you have per-user control over:

Major advantages of this approach include

Step One: Compile/Install Maildrop

This will vary greatly by platform and package management system, so figure it out for your own setup if it's not listed here. Please add yours if it is not shown:

Linux - Gentoo:  emerge maildrop  # (no USE flags are required)

Step Two: Configure your MTA to deliver via Maildrop

This topic will not be covered here, as this howto aims to be free of ties to a specific MTA as it should be suitable for any. The author uses Qmail 1.03-r15 and VPopMail 5.4.6-r1 as provided by Gentoo Linux, and plans to publish a guide for that setup. You may choose to enable maildrop globally (saves administration time), or only for accounts you configure.

Step Three: Set up your mail filter

Create/edit a file named .mailfilter in whichever location is appropriate for your setup. The author uses /var/vpopmail/domains/$domain/$username/.mailfilter. This file may be configured globally or per-user.

The file should contain at the very least the following single line:

File: .mailfilter:

to .maildir/

...or whatever path is appropriate for your system. You may use either mbox or maildir stores: append a trailing slash for a maildir, and leave off for an mbox file.

The above hardly gives any reason for using maildrop, though, and dspam is not yet called. You'll probably want at least the following mailfilter (username@domain.com should match the user you're setting this up for):

File: .mailfilter:

xfilter "/usr/bin/dspam --user username@domain.com --stdout --deliver=innocent,spam"
# If it's spam, we'll delete it.
if (/^X-DSPAM-Result: Spam.*$/)
{
        to "/dev/null"
}
to ".maildir/"

NOTE: Please ensure that the user maildrop runs as has permission to run dspam as any user if you use virtual domains! For me, this meant adding "Trust vpopmail" to dspam.conf.

The maildrop filter file man page (man maildropfilter) is very good. Please read it for a more thorough explanation of what the available commands are.

Please feel free to E-mail me at cshobe@seattleserver.com if you have any questions. SomeLinuxGuy on AIM or Yahoo, 194523 on ICQ.

Example Setups follow - please add your own

Along with the man page, these examples should be enough to get you started. When you have a working setup, please post your results and configuration below!

Example 1: DSpam trained by SpamAssassin, plus antivirus filtering, user training by moving messages into special folder only

I wanted to use dspam as the main spam fighting tool for stuff that gets past RBL checks (which I do at the SMTP level). I further wanted to use spamassassin to catch anything dspam missed, especially during the initial training period or for lazy users. It occured to me that I could use these messages identified as spam to train dspam automatically. I also wanted antivirus filtering, and for the sake of efficiency, I wanted the mailfilter configured so that no more checks than necessary are ever run - as soon as the message is known as a spam/virus, processing ends. Thus SpamAssassin is only used as a final check on mail known to be virus-free which dspam believes to be innocent. I turned off all the network checks and bayesian functionality in spamassassin, and configured it to attach the Spam-Level header I'm filtering by.

I also really hate dspam setups which require forwarding messages around, using some screwy CGI to manage quarantined messages, sticking signatures in message bodies, spamassassin-marked subject lines, and other evil stuff. I'm happy enough getting my users competant enough to use "E-Mail", without going for "Uber-l33t hacked-up Spam Filtration MegaSystem". I believe that A> E-mail should remain as unmangled as possible (extra headers are okay) and B> spam filtering must be transparent and not require extra user interfaces. Thus, the user "trains" the system simply by dragging spam messages into their Spam folder, and false positives into Spam/Not Spam. BASH and cron do the rest. Your users will have to use IMAP for this to work. Outlook Express, Thunderbird, KMail, and Apple Mail are all great IMAP clients. Squirrelmail makes a great web-based counterpart.

File: dspam-antispam:

DEST=".maildir"
# If it's a virus, we delete it without further processing.
if (`/usr/bin/clamdscan --no-summary --stdout - | grep -c 'FOUND'` == 1)
{
        to "/dev/null"
}
xfilter "/usr/bin/dspam --user username@domain.com --stdout --deliver=innocent,spam"
# If it's spam, we'll filter it.
if (/^X-DSPAM-Result: Spam.*$/)
{
        to "$DEST/.Spam.Filtered/"
}
xfilter "/usr/bin/spamc"
# SpamAssassin-tagged spam goes into Spam folder so DSpam picks it up for learning (script runs every 5 minutes from cron):
if (/^X-Spam-Level: \*\*\*\*\*.*$/)
{
        to "$DEST/.Spam/"
}
to "$DEST/"

And the accompanying BASH script which should be called from cron (crontab -e) once every 5 minutes with the following entry in the crontab:

*/5 * * * * dspam-antispam_update

Place the file anywhere within your path, or specify any directory in the crontab.

File: dspam-antispam_update:

#!/bin/sh
(c) 2005 Casey Allen Shobe <cshobe@seattleserver.com>
Released under BSD license.  See http://opensource.org/licenses/bsd-license.php

# Bail if already running (in case we are slammed with spam to train from):
processes=$(ps ax)
if [ `echo "${processes}" | grep dspam-antispam_update | wc -l` -gt 1 ]; then
        echo "ERROR: dspam_antispam_update is already running!"
        exit 1
fi

# Subscripts (these should be in your path, otherwise specify the directory here:
cutscript=dspam-antispam_update-cut
filterscript=dspam-antispam_update-filter

vmailroot=/var/vpopmail/domains
for domain in `find "${vmailroot}" -type d -maxdepth 1 -mindepth 1 | cut -d '/' -f 5 | sort`; do
  if [ `find "${vmailroot}/${domain}/" -type d -name ".Spam" | wc -l` -gt 0 ]; then
    echo ${domain}
    for user in `find "${vmailroot}/${domain}/" -type d -maxdepth 1 -mindepth 1 | cut -d '/' -f 6 | sort`; do
      maildir="${vmailroot}/${domain}/${user}/.maildir"
      if [ `find "${vmailroot}/${domain}/${user}/" -type d -name ".Spam" | wc -l` -gt 0 ]; then
        echo " - ${user}@${domain}"
        for dir in {cur,new}; do  # because SA delivers to new
          if [ -d "${maildir}/.Spam/${dir}/" ]; then
            find "${maildir}/.Spam/${dir}/" -type f \
                 -exec ${cutscript} {} Spam \; \
                 -exec ${filterscript} "${user}@${domain}" spam error {} \; \
                 -exec mv {} "${maildir}/.Spam.Filtered/cur/" \;
          fi
        done
        if [ -d "${maildir}/.Spam.Not Spam/cur" ]; then
          find "${maildir}/.Spam.Not Spam/cur/" -type f \
               -exec ${cutscript} {} Non-Spam \; \
               -exec ${filterscript} "${user}@${domain}" innocent error {} \; \
               -exec mv {} "${maildir}/cur/" \; #TODO: Should call maildrop? 
        fi
      fi
    done
  fi
done

File: dspam-antispam_update-cut:

#!/bin/sh
output=`echo "${1}" | cut -d '/' -f 10`
echo "    ${2} - ${output}"

File: dspam-antispam_update-filter:

#!/bin/sh
cat "${4}" | /usr/bin/dspam --user ${1} --class=${2} --source=${3} --stdout
# Note: this isn't actually piped to stdout without --deliver=spam,innocent

last edited 2006-01-07 02:50:36 by FrankLuithle