The SMTP protocol (unlike LMTP) allows only a single result code to the DATA command. However, often a mail to multiple recipients should be accepted for some recipients but rejected for others (As an example, consider the case where each recipient uses a bayesian filter to categorize mails into spam and ham). A simple solution would be to accept only one recipient per transaction and temporarily reject all others. However, for mails with many recipients this will lead to unacceptable delays. Another method would be to identify recipients with the same configuration and accept or temporarily reject mails to them as a group. However, if there are many possible configurations (e.g., for the bayesian filter example mentioned above), it is unlikely that any two recipients have the same configuration, so this will also lead to unacceptable delays.

This plugin uses the results of transactions to categorize sender/recipient pairs into sets. These sets are then used to accept or temporarily reject the recipients, so that when a DATA command is processed there are only recipients in the same set which will hopefully either all accept or all reject the mail. If the result for the DATA command is not unanimous, a temporary failure will be generated and the set will be split into two subsets. (In the worst case, this will result in a lot of sets with one member - however, it is to be expected that for a given sender, the sets of accepting and rejecting recipients will be relatively stable).


The following parameters can be passed to cf_wrapper:

dbi_credentials <filename>
Name of the file which contains the datasource, username and password for the database. The file should only be readable for the qpsmtpd user.

Default: none. This parameter must be specified!


This plugin makes use of the following transaction notes:

The currently accepted set. Set the first time the rcpt hook is called, and queried for subsequent recipients.

The recipient for which cf_wrapper_accept_set was set. This is only used in 4xx responses to RCPT commands.

A hashref indexed by recipient addresses with the per-recipient results. This must be filled in by the content filter plugins and is used by this plugin decide whether to accept, reject or temporarily reject the message and to categorize sender/recipient-pairs.


The content filters can only store numeric results, not error messages, so messages are always rejected with a non-informative message ``Message denied''.


Written by Peter J. Holzer <>.