qmail-spp adds plugin support to qmail`s SMTP daemon (qmail-smtpd). It`s written entirely in C using native qmail libraries, so it does not create any dependencies.
Why should I use it?
qmail-spp has been written because currently there is no common way of enhancing qmail-smtpd`s functionality apart of patches which usually are not compatible one with other and require recompilation. In addition, qmail-spp gives you possibility of enhancing your mail server in any language, so you can easily integrate it with anything you want.
How does it work?
Plugins are external programs which are executed after processing SMTP command, but just before accepting it by qmail - this lets you to add extra checks on commands` arguments before accepting it - for instance you can check envelope recipient address against your "black list".
Plugins can be written in any language, because they are independent programs. They:
- should not read anything from standard input,
- can print commands on standard output,
- should print all errors to standard error (they are logged),
- should not exit with error code 120.
All required data (as HELO host, last RCPT address, etc.) can be retrieved from environmental variables.
Which SMTP commands can be enhanced this way?
HELO/EHLO, MAIL, RCPT, DATA and (if supported) AUTH. There is also one pseudo-event triggered just after client connection.
Regarding DATA: you can't run plugins which filter message content, you can only do something else than standard 354 go ahead - this may be useful for e.g. greylisting.
What environmental variables are set by qmail-spp?
|SMTPHELOHOST||argument of 'HELO/EHLO' command|
|SMTPMAILFROM||argument of 'MAIL' command|
|SMTPRCPTTO||argument of last 'RCPT' command|
|SMTPRCPTCOUNT||how many times has 'RCPT' command been accepted|
|SMTPRCPTCOUNTALL||as above, but counts all issued 'RCPT' commands|
|SMTPRCPTHOSTSOK||rcpthosts check was successful (1) or not (0)|
Remark for SMTPRCPTCOUNT* variables: SMTPRCPTCOUNT is incremented after accepting the recipient by your plugin, and SMTPRCPTCOUNTALL is incremented before asking the plugin if the recipient should be accepted. This means that usually you will observe SMTPRCPTCOUNT=0 and SMTPRCPTCOUNTALL=1 in your plugin after first RCPT command.
And if SMTP AUTH is supported:
|SMTPAUTHUSER||user name of authorized SMTP client|
|SMTPAUTHMETHOD||used SMTP authorization method|
You should probably also take a look at http://cr.yp.to/ucspi-tcp/environment.html if you use tcpserver (from ucspi-tcp package).
What environmental variables can I use to control qmail-spp?
|NOSPP||if set, qmail-spp won't run in this session|
|SPPCONFFILE||if set, specifies alternative configuration file (instead of standard "control/smtpplugins")|
What plugin commands are supported and how to use them?
|A||accept mail - turn off qmail-spp in this session|
|N||next - accept current SMTP command (do not execute remaining plugins for this command)|
|O||ok - like N, but omits qmail checks in MAIL and RCPT|
|Emsg||error - do not accept this SMTP command and immediately send msg to the client|
|LMmsg||later, mail - like E, but shows error after MAIL command|
|LRmsg||later, rcpt - like E, but shows error after RCPT command|
|LDmsg||later, data - like E, but shows error after DATA command|
|Rmsg||reject mail - send msg to the client and drop connection|
|D||drop connection immediately, without printing anything|
|Svar=value||set environmental variable var to value|
|Uvar||unset var variable|
|Hcontent||header - add header content (eg. X-Spam-Flag: YES)|
|Cfoo@bar.com||change last address provided by the client to firstname.lastname@example.org (MAIL FROM or RCPT TO address)|
|Pmsg||print - send msg to the client|
Plugins should simply print commands on standard output, one per line, eg. RCPT plugin which prints:
to standard output:
to standard error:
redirected spam from <$SMTPMAILFROM>
- change last RCPT TO address (redirect) to email@example.com
- add X-Spam-Flag: YES header
- set $spam to "1"
- accept mail (turn off qmail-spp for this session)
- log 'redirected spam from <firstname.lastname@example.org>' message (where <email@example.com> is envelope sender address)
- each plugin command must end with a new line
- valid SMTP response codes are not added automatically to messages generated by plugins
- A, N, O, E, R and D should be used as the last command
Simply cd into the qmail source dir, patch it and install in usual way.
Following patches are bundled with qmail-spp:
- qmail-spp.diff - patch against stock qmail 1.03
- qmail-spp-smtpauth.diff - patch against qmail patched with Krzysztof Dabrowski's SMTP AUTH patch
- qmail-spp-smtpauth-eh.diff - patch against qmail patched with Erwin Hoffman's SMTP AUTH patch v. 0.4.3
- netqmail-spp.diff - patch against netqmail 1.05
- qmail-spp-smtpauth-tls-20060105.diff - patch against netqmail 1.05 patched with Bill Shupp's SMTP-AUTH/TLS composite patch, version 20060105
Remember to create configuration file (see below) - you can also use sample smtpplugins file bundled in samples/ directory.
The main default configuration file of qmail-spp is
file (assuming that /var/qmail is your qmail home dir).
It consist of few sections, one for each command:
- connection - for plugins run just after client connection
- helo - for HELO/EHLO
- mail - for MAIL
- rcpt - for RCPT
- data - for DATA
- auth - for AUTH (if supported)
Section names are marked using square brackets ('[' and ']'). After section name there are plugins to execute for this command - one per line.
# smtpplugins sample file
:plugins/rbl -r relays.ordb.org
:plugins/badhelo example.com spammers.com
Paths are relative to the qmail home dir (usually /var/qmail).
Note: If you want your plugin to be executed by system shell (/bin/sh -c), add a colon (':') before the plugin path. This might be useful for debugging or passing arguments to your program, but note that this is slightly slower than normal mode.
Copyright © 2004-2008 Paweł Foremski
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license can be found here.