Mailing List Archive

SPF aware userland mailfilter script
Everyone,

Hello, hope the holidays treated you all well! I've had this kicking around
for a while and I recently updated it and realized I'd never posted it here
so I'm doing so now. Its a "courier-maildrop" centric mailfilter script
which facilitates per-user spam filtering ala 'maildrop' which affords a
great deal of flexability as to how to behave based on the return values of
single or multiple calls to various filtering agents etc.. etc..

Bear in mind, this was written with my setup in mind (qmail, sqwebmail,
maildrop, and vpopmail (btw: if you have qmailadmin installed, your users
have the ability to turn spam checking on and off using this method, without
ever bothering you) however a few changes to binaries being called and
perhaps it will do the trick for you.

You can download the textual filter from here: http://6o4.ca/mailfilter.txt

or provided it doesn't get all buggered in transit I'll paste it here:

#
# File: /home/vpopmail/etc/mailfilter
# Author: James Couzens <jcouzens@codeshare.ca>
# Date: Feb 18, 2004
#
# Info:
# 'mailfilter' script for Courier-MTA's maildrop package.
#
# Desc:
# Mailfilter to facilitate per-user spam checking with vPopMail.
# A user may place .mailfilter in their homedir (virtual ala vpopmail or
# otherwise) to supercede this"virtual" homedir to supercede calls to this
# script which is intended for global use, which facilitates individual per
user
# behaviour (such as automagically moving mail to specific folders as well
as
# perhaps making additional passes through various differing anti-spam
filters).
#
# This script represents my interpretation of how per-user SpamAssassin
# functionality could be made available on a per user basis and is based on
an
# original script I found through my good friend Google.
#
# Use:
# Add the following line to any users .qmail file, or any valid
.qmail
# file for that matter.
#
# |/var/qmail/bin/preline /usr/local/bin/maildrop
/home/vpopmail/etc/mailfilter
#
# Caveats:
# This script relies on the 'Courier-MTA' version of maildirmake
which
# is present as part of the MailDrop package, but just in case you happen to
# change the 'maildirmake' binary path to use qmail's... change it back
because
# this script calls maildirmake with the -f 'make a folder' option.
#
# Why when making the folders do I use the macro for the appropriate folder,
but
# when referencing the same folder elsewhere in the file do I place a '.' in
# front? This is because the '.' is added by maildirmake and you are not
# permitted to create directories that start with a '.'. Because a '.' is
added
# when referencing the folder literally as a directory, it must be added.
#
#
----------------------------------------------------------------------------
--
# CHANGELOG
#
----------------------------------------------------------------------------
--
#
# 0.1 : February 18, 2004 - Initial Release
# 0.2 : November 21, 2004 - Major Update
#
# Added SPF header check for "Received-SPF: fail" headers which
triggers
# a move to the user's ".Spam" folder identically to how the X-Spam header
# check works.
#
# For more information about SPF see http://spf.pobox.com. For a C library
# with qmail, Sendmail, and Courier patches see http://libSPF.org
#
# 0.3 : January 1, 2005 - Added move to trash option
# 0.4 : January 3, 2005 - Added SPF supercede option
#
#
----------------------------------------------------------------------------
--

#
----------------------------------------------------------------------------
--
# Variables
#
----------------------------------------------------------------------------
--

VHOME="$PWD/Maildir"
USERNAME=`echo ${PWD##*/}`
USERHOST=`PWDTMP=${PWD%/*}; echo ${PWDTMP##*/}`
MAXMSG="262144"

#
----------------------------------------------------------------------------
--
# Behaviour switch variables (0 - disable, 1 - enable)
#
----------------------------------------------------------------------------
--

# Enable checks for 'Recieved-SPF: fail'
ENABLE_SPF_CHECK=1

# If found move messages failing SPF checks to the Trash
TRASH_SPF=1

# If enabled (1), move messages to a special SPF Trash folder
SEPARATE_SPF_TRASH=1

# If enabled (1), checks matching as both Spam AND SPF, will be handled as
if
# they were only marked as SPF failures and moved appropriately. This is
only
# of value if you wish to have SPF failures moved to their own special dir
# really.
SPF_SUPERCEDE=1

# If found move messages designated as Spam to the Trash
TRASH_SPAM=0

# ignore, delcared here for clarity
SPAM_DELIVERY=0

#
----------------------------------------------------------------------------
--
# Maildir subfolder name variables
#
----------------------------------------------------------------------------
--

TRASH_DIR="Trash"
SPAM_DIR="Spam"
SPF_TRASH_DIR="SPF-Trash"

# ignore, delcared here for clarity
TMP_DIR="$SPAM_DIR"

#
----------------------------------------------------------------------------
--
# binary related variables (path and binary name)
#
----------------------------------------------------------------------------
--

SHELL="/bin/sh"
SPAMC="/usr/local/bin/spamc"
MAILDIRMAKE="/usr/local/bin/maildirmake"
VUSERINFO="/home/vpopmail/bin/vuserinfo"
DELIVERQUOTA="/usr/local/bin/deliverquota"
BOUNCESAYING="/var/qmail/bin/bouncesaying"

#
----------------------------------------------------------------------------
--
# logging related variables
#
----------------------------------------------------------------------------
--

LOGGING=1
LOGFILE="/home/vpopmail/maildrop.log"


#
----------------------------------------------------------------------------
--
# If Logging is enabled, logfile path should be writable by the user
vpopmail
# is running as (in most cases this will be vpopmail:vchkpw)
#
----------------------------------------------------------------------------
--

if ($LOGGING == 1)
{
logfile "$LOGFILE"
log $VMAILDIR
log $USERNAME
log $USERHOST
log $SPAMFOLDER
log "$VMAILDIR$SPAMFOLDER"
}

#
----------------------------------------------------------------------------
--
# Perform 'message size' evaluation and if successful, pass off to 'spamc'
#
----------------------------------------------------------------------------
--

if ($SIZE < $MAXMSG)
{
# pass the message through SpamAssassin

exception {
xfilter "$SPAMC -p 1025 -f -u $USERNAME@$USERHOST"
}
}

#
----------------------------------------------------------------------------
--
# Look for 'maildirsize', if it doesn't exist, create it
#
----------------------------------------------------------------------------
--

`test -e $VHOME/maildirsize`

if ($RETURNCODE == 1)
{
`$VUSERINFO -q $USERNAME@$USERHOST > $VHOME/maildirsize`
}


#
----------------------------------------------------------------------------
--
# include user's personal mailfilter
#
----------------------------------------------------------------------------
--

`test -e $VHOME/.mailfilter`

if ($RETURNCODE == 1)
{
exception {
include $VHOME/.mailfilter
}
}


#
----------------------------------------------------------------------------
--
# if spam folder doesn't exist, create
#
----------------------------------------------------------------------------
--

`test -d $VHOME/.$SPAM_DIR`

if ($RETURNCODE == 1)
{
`$MAILDIRMAKE -f $SPAM_DIR $VHOME`
}


#
----------------------------------------------------------------------------
--
# Parse headers (2821/2822 possibly entire message + body) for the
SpamAssassin
# 'X-Spam-Flag' header to be set with a value of "YES". You will need to
# configure SpamAssassin to tag headers with this option. RTFM.
#
----------------------------------------------------------------------------
--

if (/^X-Spam-Flag: *YES/)
{
if ($TRASH_SPAM == 1)
{
TMP_DIR="$TRASH_DIR"
}
else
{
TMP_DIR=".$SPAM_DIR"
}


SPAM_DELIVERY=1
}


#
----------------------------------------------------------------------------
--
# Parse headers (2821/2822 possibly entire message + body) for a
'Received-SPF'
# header to be set with a value of 'fail'. Don't be a tard and apply
positive
# reactions to SPF values such as 'pass'.
#
----------------------------------------------------------------------------
--

if ($ENABLE_SPF_CHECK == 1)
{
if (/^Received-SPF: fail/)
{
if ($TRASH_SPF == 1)
{
if ($SEPARATE_SPF_TRASH == 1)
{
`test -d $VHOME/.$SPF_TRASH_DIR`

if ($RETURNCODE == 1)
{
`$MAILDIRMAKE -f $SPF_TRASH_DIR $VHOME`
}

TMP_DIR=".$SPF_TRASH_DIR"
}
else
{
TMP_DIR=".$TRASH_DIR"
}
}
else
{
TMP_DIR=".$SPAM_DIR"
}

# exception {
# xfilter "$DELIVERQUOTA -w 90 $VHOME/$TMP_DIR"
# }
}

SPAM_DELIVERY=1
}


#
----------------------------------------------------------------------------
--
# Deliver the mail normally
#
----------------------------------------------------------------------------
--

if ($SPAM_DELIVERY == 0)
{
exception {
xfilter "$DELIVERQUOTA -w 90 $VHOME"
}
}
else
{
if ($SPF_SUPERCEDE == 0)
{
TMP_DIR="$SPF_TRASH_DIR"
}

exception {
xfilter "$DELIVERQUOTA -w 90 $VHOME/$TMP_DIR"
}
}


#
----------------------------------------------------------------------------
--
# returncode 77 means Maildir over-quota, so bounce the mail
#
----------------------------------------------------------------------------
--

if ($RETURNCODE == 77)
{
to "|$BOUNCESAYING 'user is over quota'"
}

# end of mailfilter

Cheers,

James

James Couzens,
Programmer
-----------------------------------------------------------------
http://libspf.org -- ANSI C Sender Policy Framework library
http://libsrs.org -- ANSI C Sender Rewriting Scheme library
-----------------------------------------------------------------

-------
To unsubscribe, change your address, or temporarily deactivate your subscription,
please go to http://v2.listbox.com/member/?listname=spf-devel@v2.listbox.com
Re: SPF aware userland mailfilter script [ In reply to ]
Everyone,

I just realized two things, firstly a typo in the filter its self (please
re-download from http://6o4.ca/mailfilter.txt) where I missed a preceeding
'.' before the reference to the Spam dir which would result in your MTA
farting out a complaint or two.. Secondly why I posted the mailfilter... I
just wanted to state that in addition to being a great way to handle
per-user anti-spam on your MTA, its "SPF aware" such that it will recognize
messages which "fail" SPF checks and can move them to the "spam" folder or
alternatively to a special folder designated purely for SPF failures.

As always, feedback, suggestions.. are welcome.

Cheers,

James

James Couzens,
Programmer
-----------------------------------------------------------------
http://libspf.org -- ANSI C Sender Policy Framework library
http://libsrs.org -- ANSI C Sender Rewriting Scheme library
-----------------------------------------------------------------

-------
To unsubscribe, change your address, or temporarily deactivate your subscription,
please go to http://v2.listbox.com/member/?listname=spf-devel@v2.listbox.com