src | ||
tests | ||
.gitignore | ||
Cargo.lock | ||
Cargo.toml | ||
CHANGELOG.md | ||
LICENSE | ||
milter.pc | ||
README.md | ||
spamassassin-milter.8 | ||
spamassassin-milter.service |
SpamAssassin Milter
SpamAssassin Milter is a milter application that filters email through
SpamAssassin server using the spamc
client. It is a light-weight component
that serves to integrate Apache SpamAssassin with a milter-capable MTA (mail
server) such as Postfix. Its task is thus helping combat spam on email sites.
SpamAssassin Milter operates as a milter hooked into the MTA’s SMTP protocol handler. It passes incoming messages to SpamAssassin for analysis, and then interprets the response from SpamAssassin and applies suggested changes to the message.
By default, the following modifications are made:
- Always: Add SpamAssassin headers to the message (headers starting with
X-Spam-
) - Spam only: Rewrite headers
Subject
From
To
, if requested - Spam only: Replace message body (and rewrite related headers
MIME-Version
Content-Type
, if requested)
Alternatively, messages flagged as spam may be rejected at the SMTP level with an SMTP error reply code.
Both SpamAssassin and SpamAssassin Milter provide various configuration options to alter the default behaviour. See below for a discussion of several configuration and integration approaches.
This application can be used as a replacement for spamass-milt; it has a reduced feature set, but it should be satisfactory for a personal mail server setup. SpamAssassin Milter has been used in such a setup together with Postfix, SpamAssassin, and for delivery Dovecot with LMTP and the Sieve plugin.
Building
This project is a Rust package. Build it with Cargo as usual.
As a milter, this package requires the libmilter C library to be available. Be sure to install the libmilter shared library and header files.
If your distribution does not install a pkg-config metadata file for libmilter,
you can use the provided milter.pc
file. Put it on the pkg-config path as
follows:
PKG_CONFIG_PATH=. cargo build
The integration tests rely on the miltertest
utility. Make sure miltertest
is available and can be executed when running the integration tests.
Note that until recently miltertest
had a bad bug that prevents most
integration tests in this package from completing. Make sure you use an
up-to-date version of miltertest
.
Usage
Once installed, SpamAssassin Milter can be by invoked as spamassassin-milter
.
spamassassin-milter
takes one mandatory argument, namely the listening socket
of the milter (the socket to which the MTA will connect). The socket spec can be
in one of the formats inet:port@host
or
inet6:port@host
(IPv6), or
unix:path
, for a TCP or UNIX domain socket, respectively.
For example, the following invocation starts SpamAssassin Milter on port 3000:
spamassassin-milter inet:3000@localhost
The available options and flags can be glimpsed by passing the -h
flag:
spamassassin-milter -h
More detailed information can be found in the provided man page spamassassin-milter(8).
Setting up SpamAssassin Milter as a system service is easiest by using the
provided systemd service file: Edit spamassassin-milter.service
with the
desired port, install it in /etc/systemd/system
, then enable and start the
service.
Configuration
SpamAssassin Milter is designed as a light-weight ‘glue’ application with just a few configuration options; this is intentional, as the SpamAssassin components are themselves already highly configurable.
SpamAssassin Milter is configured by setting command-line options. All options
have reasonable defaults that work well with a stock installation of
SpamAssassin server (spamd
) and client (spamc
). You can get started with
just picking a socket and things should just work. Some integration options are
discussed in subsequent sections.
First-time users may wish to run SpamAssassin Milter with the --dry-run
option
before ‘going live’. Combined with the --verbose
option, this gives accurate
insight into the changes that SpamAssassin Milter would apply.
spamassassin-milter --dry-run --verbose inet:3000@localhost
Integration with SpamAssassin
SpamAssassin Milter must be integrated with two SpamAssassin components: the
SpamAssassin server itself, called spamd
, which does the actual work, and the
SpamAssassin client spamc
, which serves as an intermediary between the milter
and the server.
SpamAssassin configuration
The main SpamAssassin configuration file is /etc/spamassassin/local.conf
. See
perldoc Mail::SpamAssassin::Conf
for detailed information.
By default, SpamAssassin creates ‘reports’ for messages it recognises as spam. These reports replace the message body, that is, the message body is rewritten to present a report instead of the original message, and the original message is relegated to a MIME attachment. SpamAssassin Milter by default applies reports.
Reports are controlled with the report_safe
configuration parameter. Disable
reports as follows:
report_safe 0
In addition, body rewriting can also be suppressed on the SpamAssassin Milter
side with the --preserve-body
flag.
SpamAssassin may also rewrite the Subject and other headers, for example, adding a prefix ‘***Spam***’. This is not done by default, but may be enabled with a setting like the following:
rewrite_header Subject ***SPAM***
SpamAssassin Milter by default applies header rewriting. Header rewriting can be
suppressed on the SpamAssassin Milter side with the --preserve-headers
flag.
spamc
configuration
spamc
can be configured by passing it command-line options, or preferably, by
setting the command-line options in the configuration file
/etc/spamassassin/spamc.conf
.
By default, spamc
will try to reach SpamAssassin server on the dedicated port
783, so that a stock installation of SpamAssassin should work with SpamAssassin
Milter without further configuration.
If SpamAssassin server listens on a different port or on a UNIX domain socket
instead, set the --socket
option as appropriate in spamc.conf
:
--socket=/run/spamassassin/spamd.sock
When reports are disabled, it is recommended to use the --headers
option.
--headers
This option is just a shortcut that causes spamd
not to transmit the message
body back to spamc
. (This option obviously only makes sense and should only be
used when SpamAssassin reports are disabled.)
Finally, a pitfall of spamc
deserves highlighting: spamc
by default tries to
resist failure to an extent that it will not indicate failure even if it cannot
connect to SpamAssassin server at all (apart from warnings logged to syslog)! If
it cannot connect to the server, it simply echoes what it received, and so masks
the error condition. This mechanism is labelled ‘safe fallback’ and should be
disabled once the system is set up and working well. Set the following flag:
--no-safe-fallback
Integration with Postfix
To integrate with Postfix, ensure the SpamAssassin Milter service is up and
running, and then configure its listening socket in /etc/postfix/main.cf
as
follows:
smtpd_milters = inet:localhost:3000
non_smtpd_milters = $smtpd_milters
After reloading the Postfix configuration, mail will be processed by SpamAssassin Milter.
By default, SpamAssassin Milter will accept, that is, won’t check messages coming from local connections (for example, mail sent locally from the command-line), and messages from authenticated senders (for example, mail submitted via a SASL-authenticated channel).
Integration with mail delivery
A further component that can be useful with SpamAssassin Milter is a
Sieve-capable mail delivery agent. A Sieve script can for example look at the
X-Spam-
SpamAssassin headers of the incoming message, and take action based on
those.
As an example, in case Dovecot does mail delivery with LMTP, enable the Sieve plugin for the LMTP protocol, then setup a global Sieve script that files messages flagged as spam into the ‘Junk’ folder:
require "fileinto";
if header :contains "X-Spam-Flag" "YES" {
fileinto "Junk";
stop;
}
Licence
Copyright © 2020 David Bürgin
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.