This lightweight patch extends netqmail to refuse spammy messages at SMTP time. This assumes incoming messages are scanned by SpamAssassin prior to reaching
qmail-queue, such as by setting
QMAILQUEUE to invoke SpamAssassin's
An environment variable
SPAMREFUSE is added to specify the Spam Assassin threshold over which messages are refused. By default, all
postmaster addresses are exempt. Different exemptions can be specified in
Status / Warranty
No warranty, express or implied is given - USE THIS SOFTWARE ENTIRELY AT YOUR OWN RISK. You will need to satisfy yourself as to the suitability of this software before deploying it in a production environment.
The documentation for this patch consists of this web page and the updated man pages:
Proceed as follows:
- Unpack the patch if you've downloaded a compressed version.
- Patch your qmail source: Enter your
netqmail-1.06source directory (already patched with qmail-logmsg) and type,
patch < path_to_the_patch/nq106-spamrefuse-v1.01.patch
which should apply the patch. If this fails, you will need to patch the failed parts by hand. If you're basing your installation on a Life with qmail (LWQ) style setup, you'd apply the patch then continue with
make setup checkin section 2.5.5.
- You can now compile qmail and install as normal.
- Spamrefuse assumes messages will be scanned by SpamAssassin. This is typically using
qmail-spamccalled using the
QMAILQUEUEenvironment variable. If you want to use
qmail-spamcbut it's not setup on your system, you may like to see if it is available as a package, alternatively you can compile it from source - see
spamc/README.qmailin SpamAssassin's source files.
- I'd appreciate your report on whether you could compile qmail successfully with this patch so that I can update the Compatibility section below - please email firstname.lastname@example.org with details of your system (esp. OS & CPU) - just
cat systypefrom within your qmail source directory is enough if you're in a hurry.
Setup / Configuration
Enable spam refusal with the
SPAMREFUSE environment variable. This specifies the threshold score above which messages should be refused. This may be the different from your SpamAssassin
required_hits setting if desired (for example you might reject very spammy messages and quarantine moderately spammy messages). Set this variable in the source for your cdb file (if using
tcpserver -x), remembering to update your cdb afterwards (
qmailctl cdb if you have a LWQ setup). For example,
Alternatively you can set
SPAMREFUSE in the environment supplied to
tcpserver, in the startup script for
qmail-smtpd, for example (based on LWQ section 188.8.131.52),
exec env SPAMREFUSE="5.5" \
/usr/local/bin/softlimit -m 2000000 \
postmaster for all domains is exempt (no mail is refused). See the man pages if you wish to alter this.
Please let me know if you successfully install Spamrefuse on systems not listed below (see the end of the installation section on this page).
Compatibility with qmail, netqmail: The patch should apply cleanly to the following:
- netqmail 1.05 patched with qmail-logmsg version 1.1, 1.2 or 1.3.
- netqmail 1.06 patched with qmail-logmsg version 1.1, 1.2 or 1.3.
Compatibility with Unix / Linux: Successful compilations have been reported on the following:
- Centos 5.3 / i386 (Systype: linux-2.6.18-128.1.10.el5pae-:i386-:-:ppro-:-)
- Fedora 8 / i386 (Systype: linux-184.108.40.206-57.fc8-:i386-:-:ppro-:-)
- Ubuntu 9.04 / i386 (systype: linux-2.6.28-15-generic-:i386-:-:ppro-:-)
- OpenBSD 4.0 / Sparc64 (Systype: openbsd-4.0-custom#1-:openbsd.sparc64-:-:sparc64-:-)
I've tried to ensure that the changes to netqmail are minimal. In
qmail-smtpd I've taken my cue from the existing
badmailfrom code to provide the code for
nospamrefuse. By definition the scanned message is not available to
qmail-smtpd, therefore it is in
SPAMREFUSE is checked against the message's SpamAssassin score in the
Rather than add floating-point logic for comparing
SPAMREFUSE (which can have a fractional part) I multiply it and the SpamAssassin score by 100 before comparing them.
Spamrefuse could be enhanced:
- Currently exceptions are in
control/nospamrefuseto "opt out" of Spamrefuse. This file could be extended to (optionally) specify different
SPAMREFUSEscores from the global setting. This could be achieved by making more use of the existing
constmapmechanism or by using a cdb file for the exceptions. In this case
control/nospamrefusewould perhaps be better named
control/spamrefuse(also see below on this subject).
qmail-queue.cis perhaps better separated into its own module so it can be used elsewhere - in particular if the above enhancement of specifying different
SPAMREFUSEscores were implemented, these would probably be parsed in
SPAMREFUSEis set but no
X-Spam-Status:header is found it would be good to log an error message, but this may be complex given that
qmail-queuegenerally communicates via exit codes with the other components of qmail.
- Please also see my notes in Spamrefuse's source code.
- This patch has evolved from an early prototype in a way that it's not elegant: I feel it is confusing to have both
control/nospamrefuse. It would be better to have
control/spamrefusewhich would include a default score specified as
:6.0for example, optionally also specifying addresses like
postmasterfor which SpamRefuse should be omitted.
At present I do not have plans to implement any of the above enhancements, given that the current behaviour is sufficiently straightforward, particularly for a fairly small netqmail system - and that I'm not being paid for it. I have written SpamRefuse because I feel it's an important tool to reduce the impact of spam and it's a feature I want to offer to my clients.
There are no earlier public releases.
This page last updated: AR, 1st July 2013.