/ Markus Amersdorfer:home / university / about:me /
\ Say NO to Software-Patents! \

Table of Contents

Mailman & Postfix HOWTO for Debian Woody


"Mailman" is the GNU project's great and most-easy to use Mailing-List manager.

Managing mailing-lists actually boils down to distribute a mail to all the list's subscribers.
This for example does not include receiving the mails - that's the MTA's job. As the MTA, I use Postfix. Here's my mini Postfix HOWTO.

Furthermore, you should use a dedicated subdomain "lists.yourdomain.net" as is common with Mailman setups - the configuration below is also based on this.

BTW: Christopher Kolar's Mailman Documentation offers a great "Manager's Guide" explaining lots of the options available in Mailman.
Florian and me wrote the initial version of a German guide on the most important use cases for both Mailman-Admins and -Users: http://help.subnet.at/Mailman.

Install Mailman

Installation with Debian Woody is really quite easy:

  apt-get install mailman

Adapt /etc/mailman/mm_cfg.py:
  DEFAULT_HOST_NAME = 'lists.yourdomain.net'
  DEFAULT_URL       = 'http://lists.yourdomain.net/mailman/'
  IMAGE_LOGOS       = '/doc/mailman/images/'

  MAILMAN_OWNER     = 'mailman-owner@%s' % DEFAULT_HOST_NAME

  PUBLIC_ARCHIVE_URL = '/pipermail'
  PRIVATE_ARCHIVE_URL = '/cgi-bin/mailman/private'

Based on /usr/share/doc/mailman/README.Debian (which holds important (and very dense) information) proceed this way:

After reloading/restarting Apache, Mailman should be available at http://lists.yourdomain.net/mailman/listinfo.

How to integrate Mailman with Postfix

Unfortunately the Debian Woody packages of both Postfix and Mailman do not mention how to get this combination working.
I first tried the script postfix-to-mailman-2.1.py, but could not get it working correctly. (Update: See the Debian Sarge setup below ...)
Following this explanations of rezo.net the setup works now... (With this approach, you will not have to manually edit /etc/aliases each time a list is added/removed, as Postfix' regular expressions will automatically catch mailing-list mails.)

Add to /etc/aliases:
  mailman-post: "|/var/lib/mailman/mail/wrapper post $EXTENSION"
  mailman-admin: "|/var/lib/mailman/mail/wrapper mailowner $EXTENSION"
  mailman-request: "|/var/lib/mailman/mail/wrapper mailcmd $EXTENSION"
  mailman-owner: "|/var/lib/mailman/mail/wrapper mailowner $EXTENSION"
  mailman-on: "|formail -I'Subject: subscribe'|/var/lib/mailman/mail/wrapper mailcmd $EXTENSION"
  mailman-off: "|formail -I'Subject: unsubscribe f'|/var/lib/mailman/mail/wrapper mailcmd $EXTENSION"

Add to /etc/postfix/main.cf:
  virtual_maps = hash:$config_directory/virtual, regexp:/etc/postfix/virtual-regexp
  [ The following settings are Debian-Postfix-Defaults already:
      recipient_delimiter = +
      mailbox_command = /usr/bin/procmail -a "$EXTENSION"

Create /etc/postfix/virtual-regexp:
  # mandatory
  /^(postmaster|root|abuse)@lists\.yourdomain\.net$/ $1@yourdomain.net
  # commands
  /^([a-zA-Z0-9_\-]+)-(post|admin|request|owner|on|off)@lists\.yourdomain\.net$/ mailman-$2+$1
  # lists (command -post)
  /^([a-zA-Z0-9_\-]+)@lists\.yourdomain\.net$/ mailman-post+$1

Mind: In comparison to rezo.net's settings, I had to change the regexp-order from ([\-a-zA-Z0-9_]+) to ([a-zA-Z0-9_\-]+), otherwise Postfix always complained with "error in regexp: Invalid range end." in /var/log/mail.info.

If you check /etc/postfix/virtual, you'll find it mentions to execute the command "postmap /etc/postfix/virtual" (which rebuilds the corresponding database).
I did this once. Nevertheless, changing the content of virtual-regexp seems to have direct influence on Postfix - even without running this postmap-command.

DNS: The MX Record

While it's one of the easier things within this setup, this took me quite a while to find out: The "correct/existing" MX record (which, as you might/should know when dealing with a mail server, points to the machine which is responsible for receiving a domain's SMTP traffic).

Remember we are using a special subdomain "lists"?
"lists.subnet.at" is just another name for a machine which is actually called "yellow.subnet.at".
Furthermore, yellow.subnet.at is not the domain's main mail server (but it will become this some day).

The problem was, I didn't have an MX record set for lists.subnet.at in the (DNS-) zone "subnet.at" at first. This lead to other MTA's instead of sending mail to "testlist@lists.subnet.at" actually delivering it to "testlist@yellow.subnet.at". Our Postfix then, of course, could not deliver it as the regular expressions for "@lists" (see above) did not match.
(I found out about this by temporarily activating "debug_peer_list = somedomain.I.could.send.mails.from" in /etc/postfix/main.cf. /var/log/mail.log then presented some most detailed debug logs showing this (wrong) recipient.
See /usr/share/doc/postfix/DEBUG_README.gz for more information on Postfix-Debugging.)

With this setup (which is: the machine "yellow.subnet.at" hosting the Postfix MTA responsible for "lists.subnet.at" and "grey.subnet.at" hosting the DLIST MTA responsible for the overall "subnet.at" domain), the correct MX records are (taken from our subnet.at-zone-file):

  subnet.at.       MX 10  grey.subnet.at.
  lists.subnet.at  MX 10  yellow.subnet.at.

This way, all mails to "subnet.at" use the MTA at "grey", all mails to "lists..." use our new Postfix MTA at "yellow".

Allow (specific) Relaying!

Finally: In order to have our Postfix MTA accept mails which have a recipient "xyz@lists.subnet.at", we need to activate "relaying" for this domain:

Add to /etc/postfix/main.cf:
  relay_domains = lists.subnet.at

Finally, here's my main.cf for Postfix.

Managing Your List

To manage the lists, simply use the following commands and follow the instructions on the screen:

Add a new list:

Remove a list:

Configure lists via the web:

Configure lists via the command line:
  config_list -o ~/mylist.conf mylist
  [edit ~/mylist.conf]
  config_list -i ~/mylist.conf mylist

Lost Passwords

The List "mailman"

To complete the Mailman setup, add the mailing-list "mailman".
What is the purpose of the site-wide mailing list? from the The Whole Mailman FAQ.

  # newlist
  Enter the name of the list: mailman
  Enter the email of the person running the list: admin@yourdomain.net
  Initial mailman password:
  Entry for aliases file:
   ## mailman mailing list
   ## created: 14-Oct-2003 root
   mailman:                 "|/var/lib/mailman/mail/wrapper post mailman"
   mailman-admin:           "|/var/lib/mailman/mail/wrapper mailowner mailman"
   mailman-request:         "|/var/lib/mailman/mail/wrapper mailcmd mailman"
   mailman-owner:           mailman-admin
   Hit enter to continue with mailman owner notification...

List Archives

Getting the list archives to work correctly took some additional attention.

First, if they are not working at all (your browser tells you something like "You are not allowed ... *blabla* ..."), it might be that your Apache does not allow the symlinks to be followed.
Within the Virtual Host section, I added a Directory section explicitly allowing this. To make it simple - here's the whole vhost-section:

    ServerName lists.subnet.at
    DocumentRoot /data/www/lists.subnet.at

    ServerAlias www.lists.subnet.at

    ScriptAlias /mailman/ /usr/lib/mailman/cgi-bin/
    Alias /pipermail/ /var/lib/mailman/archives/public/

    <Directory /var/lib/mailman/archives/public>
      Options +FollowSymLinks

    CustomLog /var/log/apache/lists.subnet.at-access.log combined
    ErrorLog /var/log/apache/lists.subnet.at-error.log

The second thing which wanted to be fixed was that nobody could log in to a private archive.
The reason here was that Mailman thought that the corresponding URL was /cgi-bin/mailman/private, while it actually is /mailman/private. Thus, here's the solution:

  PRIVATE_ARCHIVE_URL = '/mailman/private'

Mailman hosting Lists for Virtual Domains

Mailman can handle several mailing-lists for different ("virtual") domains.
If you are using version 2.1.2 (or similar versions too, I suppose), follow the instructions on python.org for Mailman 2.1.2. To get Woody's 2.0.11 to work with virtual domains, perform the stuff below. (This is based on some info I got from N. Bronstert, many thanks again!)

How to configure Woody's Mailman 2.0.11

You should now be able to not only see your new list on http://lists.your-vdomain.net/mailman/listinfo but also use it as "newlist@lists.your-vdomain.net".
(Mind: While the list won't show up on your default domain's "listinfo", it will show up on both "admin" sites (i.e. your new virtual domain's and your default domain's admin URL)! Unless you hide it totally, of course.)

The Drawback

The drawback with Mailman and virtual domains: You cannot use the same mailing-list name for different virtual domains at the same time. (This means something like "users-list@domain1.net" and "users-list@domain2.net" is not possible!)

One idea we came up with is to use prefixes representing the virtual domain, resulting in list-names such as "vdom1_users-list" for the domain "lists.your-vdomain1.net" and similar. Incoming mail to "[everything]@lists.your-vdomain1.net" can be rewritten by Postfix using the (somewhat changed) entries in virtual-regexp to be delivered to Mailman's "vdom1_[everything]". This way, incoming mail can be delivered correctly.
The main disadvantage (that is enough to render the solution unusable, in our eyes) is that Mailman itself does not know or care about these prefixes -- to Mailman, the list-name is "vdom1_users-list". This is reflected in every mail Mailman delivers to new list-subscribers, in the URLs to the archives, etc.... Thus, Mailman constantly provides "wrong" information (though being syntactically correct, it's not what we want our mailing-lists to look like).
If you still wanted to use this approach, here are the corresponding settings in Postfix' virtual-regexp that worked for us in a small test-scenario:

/etc/postfix/virtual-regexp, using domain-prefixes:
  # This setting uses the domain-prefix "PREFIX" for your domain.
  # Though, it's probably better to wait for Mailman to natively
  # support mailing-lists with the same name on different domains ...
  # mandatory
  /^(postmaster|root|abuse)@lists\.yourdomain\.net$/ $1@yourdomain.net
  # commands
  /^PREFIX_([a-zA-Z0-9_\-]+)-(post|admin|request|owner|on|off)@lists\.yourdomain\.net$/ mailman-$2+PREFIX_$1
  /^([a-zA-Z0-9_\-]+)-(post|admin|request|owner|on|off)@lists\.yourdomain\.net$/ mailman-$2+PREFIX_$1
  # lists (command -post)
  /^PREFIX_([a-zA-Z0-9_\-]+)@lists\.yourdomain\.net$/ mailman-post+PREFIX_$1
  /^([a-zA-Z0-9_\-]+)@lists\.yourdomain\.net$/ mailman-post+PREFIX_$1

Upgrade: Mailman and Postfix for Debian Sarge

Mailman 2.1.4 vs. 2.1.5

We recently upgraded our Woody-based Mailman-host to Debian Sarge.
Unfortunately, we ran into a bug while upgrading the mailman package from 2.0.11 to Sarge's 2.1.5-3.

As a work-around, we managed to install Mailman 2.1.4 from backports.org, which perfectly fine performed the upgrade-process. (A dependency was to install Python2.2, which we did using Sarge's package.)

Postfix 2 and Mailman 2.1

/usr/share/doc/mailman/README.Debian.gz, besides other valuable information, holds the section "Upgrading from Mailman 2.x (where x < 1)" which you should read definitely!

It turned out that the new mailman also supports new aliases such as "$LISTNAME-bounce@lists.yourdomain.net", etc. In order for them to be processed correctly, one would have to adapt the /etc/aliases file accordingly. (Also see information on the necessary changes to /etc/aliases.)

BUT: The Mailman 2.1 package now also holds the file /usr/share/doc/mailman/README.POSTFIX.gz, which mentions three ways of getting Postfix and Mailman to work together:

  1. Usage of the postfix-to-mailman.py-script. (See below!)
  2. A thorough description of some steps to perform if you want "$LISTNAME@yourdomain.net" (instead of "$LISTNAME@lists.yourdomain.net").
  3. A hint on the rezo.net-approach we used and described above already when explaining the Woody-setup.


As we already decided to use "lists.yourdomain.net" for our setup, usage of the Python-script seemed to be a good idea -- and it really works great!
(Note though: Sarge's Mailman 2.1.5-3 seems to have bug concerning this script. It is fixed in Sid's 2.1.5-4 already, this version still just has to get into Sarge.)

With Mailman 2.1.4 installed, I followed the directions in the script itself /usr/lib/mailman/bin/postfix-to-mailman.py:

   relay_domains = ... lists.yourdomain.net
   transport_maps = hash:/etc/postfix/transport
   mailman_destination_recipient_limit = 1

   # [...]  
   mailman unix  -       n       n       -       -       pipe
     flags=FR user=list
     argv=/var/lib/mailman/bin/postfix-to-mailman.py ${nexthop} ${user}

   lists.yourdomain.net   mailman:

   MTA = None # No MTA alias processing required
   # alias for postmaster, abuse and mailer-daemon
   DEB_LISTMASTER = 'postmaster@yourdomain.net'

After that, I restarted the Postfix and Mailman services. Furthermore, in order for Postfix to learn about the "transport" settings, one needs to run the command "postmap /etc/postfix/transport".

I created a test-list for the domain I used and - there it was - a perfectly fine working Mailman-2.1.4-based mailing-list. :)

NOTE: If you are migrating your mailman-mailing-lists from Woody (using the above-mentioned aliases-based approach) to Sarge, you should remove the the entries in /etc/postfix/virtual-regexp for each domain you migrated to this script-based approach. Furthermore, if you're done with all domains, remove the aliases from /etc/aliases and the virtual_maps configurations in /etc/postfix/main.cf.

New Features in Mailman 2.1

Besides a considerably restructured web-interface, there are lots of changes and new functionalities in Mailman 2.1.4 - some of them are:

back to index

Valid HTML 4.01! Valid CSS! Created with Vim [Blue Ribbon Campaign icon]
© Markus Amersdorfer (markus<dott>amersdorfer<att>subnet<dott>at)
last modified: 2010-02-23 15:56:34
36467 hits