When we were moving from mailman to sympa to be able to have true multi-domain support, I was shocked how difficult (and poorly documented) it is to get sympa properly integrated with postfix. I wanted a system where:

  • mails to unknown recipients are rejected
  • lists can be created and deleted by users (no manual editing of aliases)
  • no patches to sympa or postfix are necessary.

For mailman, Debian ships with a setup that just works. For sympa, read on.

This post was last updated on 2018-06-01 for Sympa 6.2.16

The problem

When you follow the sympa docs on postfix integration, you end up with a system that will accept all mails on the domain(s) sympa is expecting mails to arrive on. This makes it very difficult to have lists on the same domain as regular mailboxes, is a terrible practice because it leads to a lot of bounce-spam and may bring your server down if a spammer is guessing random emails from your domain.

The sympa FAQ contains an entry about this very problem, but the page is a mess and mostly outdated so it's unfortunately not helpful. The following will rougly follow the howto from Folly Consulting, which you should read if you're interested in an in-depth explanation of the problem and how postfix transports work. The code they use is not up-to-date however, redundant (they call postmap even though it's unneccessary) and they patch files from sympa, which I wanted to avoid to make upgrades less painful.


My servers run Debian, so if you use sympa on a system that is not Debian-based you may have to change some paths. The following was confirmed to work on Debian 6 (squeeze) and Debian 7 (wheezy) and should work without modification for recent versions of Ubuntu and Mint (at least).

The setup

We will setup virtual transports for each of the six commands sympa uses and let them handle mail for corresponding virtual domains (sympalist, symparequest and so on). A modified alias_manager.pl is provided that is able to create a regexp-type alias file for postfix which maps incoming mail to those virtual domains. This setup means we do not need to call a binary after changes (such as the suid-root aliaswrapper provided by sympa or even postmap) as regexp files are re-read everytime smtpd starts. See the notes at the end for what this means for low-traffic mailservers.

Let's get started!

The alias manager

Get the modified version of alias_manager.pl from Github and make it executable. Download list_aliases.ttf and place it in /etc/sympa. Or simply run:

cd /opt
git clone https://github.com/tribut/sympa-postfix-virtual.git
cd sympa-postfix-virtual && sh make_public.sh
cd /etc/sympa && ln -s /opt/sympa-postfix-virtual/templates/list_aliases.tt2 .

The version of alias_manager.pl in the master branch is based on sympa 6.2.16 and works with sympa 6.2. An older version from sympa 6.12 that works with sympa versions 6.0 and 6.1 is available in the sympa-6.1 branch. If you use a different version and encounter problems, it's easy to review my changes.


Add the following options to your sympa.conf:

# use modified alias_manager with support for virtual aliases
alias_manager /opt/sympa-postfix-virtual/scripts/alias_manager.pl
# name of the alias file MUST end in "virtual"
sendmail_aliases /etc/sympa/sympa-alias.virtual

And create the alias file with the correct permissions:

umask 077
touch /etc/sympa/sympa-alias.virtual
chown sympa:sympa !!$

Finally, open sympa-alias.virtual in your favorite editor and add the following, replacing my.domain.tld and my\.domain\.tld with your domain name and the escaped version of your domain name, respectively.

# add a line like this for all domains sympa should receive mails on
# the right-hand content ("xxx") is ignored but necessary
/^my\.domain\.tld$/  xxx
# default contact emails
/^(postmaster|sympa-request|sympa-owner)\@.*$/  listmaster@my.domain.tld.
# sympa user interaction and VERP management
/^(sympa|listmaster)\@my\.domain\.tld$/         $1+my.domain.tld@sympalist.
/^(bounce\+.*|abuse-feedback-report)\@my\.domain\.tld$/ sympa+my.domain.tld@sympabounce.

Pay attention to the dots at the end of the lines, marking the destination domains fully-qualified.


For the postfix configuration, first create the virtual transports by adding this to master.cf:

sympalist        unix  -       n       n       -       -       pipe
  flags=RF user=sympa argv=/usr/lib/sympa/bin/queue ${user}@${extension}
symparequest     unix  -       n       n       -       -       pipe
  flags=RF user=sympa argv=/usr/lib/sympa/bin/queue ${user}-request@${extension}
sympaeditor      unix  -       n       n       -       -       pipe
  flags=RF user=sympa argv=/usr/lib/sympa/bin/queue ${user}-editor@${extension}
sympasubscribe   unix  -       n       n       -       -       pipe
  flags=RF user=sympa argv=/usr/lib/sympa/bin/queue ${user}-subscribe@${extension}
sympaunsubscribe unix  -       n       n       -       -       pipe
  flags=RF user=sympa argv=/usr/lib/sympa/bin/queue ${user}-unsubscribe@${extension}
sympabounce      unix  -       n       n       -       -       pipe
  flags=RF user=sympa argv=/usr/lib/sympa/bin/bouncequeue ${user}@${extension}

Now, create transport_regexp with the following contents:

/^.*\@sympalist$/         sympalist:
/^.*\@symparequest$/      symparequest:
/^.*\@sympaeditor$/       sympaeditor:
/^.*\@sympasubscribe$/    sympasubscribe:
/^.*\@sympaunsubscribe$/  sympaunsubscribe:
/^.*\@sympaowner$/        sympabounce:

This file will tell postfix to actually use the transports for mail that is aliased to our virtual domains. Lastly, modify main.cf and declare the two files we have created:

virtual_alias_maps = regexp:/etc/sympa/sympa-alias.virtual
transport_maps     = regexp:/etc/postfix/transport_regexp
sympalist_destination_recipient_limit        = 1
symparequest_destination_recipient_limit     = 1
sympaeditor_destination_recipient_limit      = 1
sympasubscribe_destination_recipient_limit   = 1
sympaunsubscribe_destination_recipient_limit = 1
sympabounce_destination_recipient_limit      = 1

If you already have virtual_alias_maps or transport_maps in your config, you can list several values seperated by commas. Pay attention to the order of the maps though: First match wins.

Now, restart your services.

service sympa reload
service postfix reload

To test if everything worked, create a mailing list and then run /usr/sbin/sendmail -bv mylist@my.domain.tld. This will send a delivery report to the user account running the command (but not generate any real mail to the list). Ideally you should see something like this:

<mylist+my.domain.tld@sympalist> (expanded from
    <mylist@my.domain.tld>): delivery via sympalist: delivers to
    command: /usr/lib/sympa/bin/queue

Additional tweaking

A drawback of regexp-type maps is that they will be kept in memory for the lifetime of an smtpd process, so changes won't be picked up immediately. If your mailserver is not very busy, it may take close to 3 hours (100*100s in the default configuration) before postfix notices a new list. So if you run a server that is idle a lot, you could consider adding some options to the smtp process in master.cf:

smtp      inet  n       -       -       -       -       smtpd
   -o max_idle=30s
   -o max_use=20

With those values it will take at most 10 minutes before your maps are re-read.

Previous Post Next Post