Fetching contributors…
Cannot retrieve contributors at this time
539 lines (411 sloc) 16.4 KB


spamassassin - SpamAssassin integration for qpsmtpd


Plugin that checks if the mail is spam by using the "spamd" daemon from the SpamAssassin package.

SpamAssassin 2.6 or newer is required.

Stores the results in a note named spamassassin (for other plugins). The note is a hashref with whatever fields are defined in your spamassassin config. These are the common ones: score,required,autolearn,tests,version


Configured in the plugins file without any parameters, the spamassassin plugin will add relevant headers from spamd (X-Spam-Status etc).

The format goes like

spamassassin  option value  [option value]

Options being those listed below and the values being parameters to the options. Confused yet? :-) It looks like this in practice:

spamassassin reject 7 leave_old_headers keep
reject [threshold|userprefs]

Set the threshold where the plugin will reject the mail. Some mail servers are so useless that they ignore 55x responses not coming after RCPT TO, so they might just keep retrying and retrying and retrying until the mail expires from their queue.

Depending on your spamassassin configuration a reasonable setting is typically somewhere between 12 to 20.

By setting reject = userprefs, the required threshold will be taken from spamassassin userprefs. Usually used in conjunction with spamd_user = vpopmail.

The default is to never reject mail based on the SpamAssassin score.

munge_subject_threshold [threshold]

Set the threshold where the plugin will prefix the subject with the value of subject_prefix. A modified subject is easier to filter on than the other headers for many people with not so clever mail clients. You might want to make another plugin that does this on a per user basis.

The default is to never munge the subject based on the SpamAssassin score.

subject_prefix [prefix]

What to prefix the subject with if the message is detected as spam (i.e. if score is greater than munge_subject_threshold. Defaults to *** SPAM ***

spamd_socket [/path/to/socket|]

Beginning with Mail::SpamAssassin 2.60, it is possible to use Unix domain sockets for spamd. This is faster and more secure than using a TCP connection, but if you run spamd on a remote machine, you need to use a TCP connection.

headers [none]

By default, spamassasin headers are added to messages. To suppress header insertion, use 'headers none'.

leave_old_headers [drop|rename|keep]

Another mail server before might have checked this mail already and may have added X-Spam-Status, X-Spam-Flag and X-Spam-Check-By lines. Normally you can not trust such headers and should either rename them to X-Old-... (default, parameter 'rename') or have them removed (parameter 'drop'). If you know what you are doing, you can also leave them intact (parameter 'keep').

spamd_user [username]

The username to pass to spamd, if different from the user qpsmtpd runs as.

relayclient skip

What special treatment is offered to connection with relay permission? Relay permissions are granted when the connecting IP is listed in the relayclients file and/or when the user has authenticated. The only valid option at present is 'skip', which skips SA scoring.

If SpamAssasin has certain network tests enabled, users may get elevated spam scores because their dynamic IP space is properly listed on DUL blocking lists. If the user is authenticated or coming from a trusted IP, odds are we don't want to be reject their messages. Especially when running qpsmtpd on port 587.

size_limit [limit]

Set the maximum email size in bytes to scan. Above this limit, no scan will be done by spamd. The default value is 500_000

With both of the first options the configuration line will look like the following

spamasssasin  reject 18  munge_subject_threshold 8


This plugin supports per-user SpamAssassin preferences. When per-user SA prefs are enabled (by setting spamd_user = vpopmail), the message recipient is used as the spamd username. If SpamAssassin has per-user preferences enabled, it will consult the users spam preferences when scoring the message.

When a message has multiple recipients, we do not change the spamd username. The message is still scored by SA, but per-user preferences are not consulted. To aid in debugging, messages with multiple recipents will have an X-Spam-User header inserted. Admins and savvy users can look for that header to confirm the reason their personal prefs were not consulted.

To get per-user SA prefs to work for messages with multiple recipients, the LDA should be configured to check for the presence of the X-Spam-User header. If the X-Spam-User header is present, the LDA should submit the message to spamd for re-processing with the recipients address.


2012.04.02 - Matt Simerson

* refactored for ease of maintenance
* added support for per-user SpamAssassin preferences
* updated get_spam_results so that score=N.N works (as well as hits=N.N)
* rewrote the X-Spam-* header additions so that SA generated headers are
  preserved. Admins can alter SA headers with add_header in their SA
  config. Subverting their changes there is unexpected. Making them read
  code to figure out why is an unnecessary hurdle.
* added assemble_message, so we can calc content size which spamd wants