Exim and Mailman: Reject non-subscribers at the SMTP level

Prerequisites

The recipe below has been tested with the following configuration. Reasonably close software versions should work as well.

Installing the scripts

Two scripts are needed: A Python script called is-list-member which performs the actual list membership test, and a SGID Perl script, is-list-member-sgid, which performs the transition from the Exim user to the Mailman user.

The following steps are recommended to install these scripts:

As a result, any local user can invoke the is-list-member-sgid script to probe mail addresses for list membership. If this is a problem, place the script into a directory which can only be accessed by the Exim user (or use file system ACLs if available).

Modifying the Exim configuration

Add the following ACL entry before accepting mail to the Exim 4 configuration (in the acl_smtp_rcpt ACL):

  deny domains = +mailman_domains
    # Check if the local part is a Mailman list.
    condition = \
      ${if exists{MAILMAN_HOME/lists/$local_part/config.pck} \
      {yes}{no}}

    # Check blacklists (optional).
    # Mail from non-subscribers will still go through.
    # condition = some blacklist check

    # Check for list membership.  The if condition ensures
    # that the script (which runs under the Mailman group)
    # cannot inject code to be executed by the Exim user.
    !condition = ${if match{${run \
      {/etc/exim4/scripts/is-list-member-sgid \
       $local_part $sender_address}{$value}{fail}}}\
      {^([a-z]+)}{$1}{fail}}

    # Document the cause for rejection in the error message.
    message = Please subscribe the address <$sender_address> \
      to this mailing list before posting.

If necessary, adjust the path to the Mailman installation (MAILMAN_HOME) and to the is-list-member script.


Florian Weimer
Home Blog (DE) Blog (EN) Impressum RSS Feeds