Kroon Information Systems
       
    
Howto: qmail and mailman

Last updated 9 August 2023

Background

I'm one of those people who like the qmail way of doing things. I'm also on of those people who like mailman. Both is simple, clearly defined and is understandable. I had a few issues with getting them to play nice together though.

The setup I'll be assuming in this howto is that used by Gentoo, specifically net-mail/mailman-2.1.5 where installation is into /usr/local/mailman. The contrib binaries are also installed into the bin directory. Other than that it is a standard install as far as I know.

I found it relatively problematic to get all the correct mails delivered to mailman the way it was described in the sparse documentation that I did find. In this document I'm hoping to clear up some things and help administrators to quickly, and effectively set up their qmail and mailman installations.

Users involved

We will only be affected by a few users, those of qmail (clearly described in Life With QMail) and then the mailman user, which in my case has uid and gid 280, and is also part of the cron group (in order to be able to run cron jobs). The following should describe the users involved:

uid=280(mailman) gid=280(mailman) groups=280(mailman),16(cron)
uid=200(alias) gid=200(nofiles) groups=200(nofiles)

The basic qmail setup

qmail is set up to deliver to ./.maildir/ by default, smtp for localhost, qmail-send delivers local mail and forwards all other mail via belrog.lan. locals and rcpthosts only contains pug.lan. This works absolutely fabiously.

qmail is a breeze to set up, I recommend a document Life With QMail. Everything about qmail is explained clearly and should allow you to get your mail system up to scratch in about half an hour. I should make an ammendment here: It's a breeze to set up if you are using a proper distro like Debian or Gentoo, on distro's like SuSE it's a bitch to get everything to work. There are also various patches that the debian and gentoo packages takes care off (whilst most of these are not required I highly recommend some of them - like the QMAILQUEUE patch). You may want to consider netqmail which is qmail with a few patches added.

I can also recommend courier-imap for pop3/imap. It's setup is easy and effective.

Adding mailman to the picture

Configuring mailman in itself was a pain in the backside. Here is a quick list of commands to run:

  1. # su - mailman
  2. $ cd cron
  3. $ crontab crontab.in
  4. $ cd ..
  5. $ bin/mmsitepass
  6. $ bin/newlist mailman
  7. $ exit
  8. # /etc/init.d/mailman start
  9. # rc-update add mailman default

These basically install the crontab, set up the mailman password (for the web interface), create the base mailman mailing list and start the mailman daemon. Type these commands excactly as above, enter the password when prompted and enter your mail address (I used postmaster, the reasoning is that whoever postmaster goes to is probably the person in charge of the mailman setup anyway. The last line is gentoo specific and is only there to add mailman to the default runlevel.

Configuring the basic mailman aliases

By default only mail sent to mailman@pug.lan will get delivered, and then qmail will attempt to deliver the mail to ~mailman/.maildir/, which is not what we want. For this reason we need to create some aliases, and we need to change the way in which mail is delivered to mailman.

When mail is delivered to mailman, we should execute ~mailman/mail/mailman with two parameters, the first is the command, which can be one of:

  • post
  • admin
  • owner
  • bounces
  • confirm
  • join
  • leave
  • subscribe
  • unsubscribe
  • request

For each of these we need to create a .qmail file in ~mailman. We also need to pass the message through preline first in order to make sure that we have a valid From: field in the message. The following script achieves what we want:

#! /bin/bash

echo "|preline /usr/local/mailman/mail/mailman post mailman" > ~mailman/.qmail

for i in admin owner bounces confirm join leave subscribe unsubscribe request
do
	echo "|preline /usr/local/mailman/mail/mailman $i mailman" > ~mailman/.qmail-$i
done

ln -s ~mailman/.qmail-bounces ~mailman/.qmail-bounces-default

This is relatively obvious, mailman@ should go to post, the remainder all need to go to their appropriate places. The symbolic link is in order for VERP to work properly if enabled.

After these you should be able to subscribe to the mailman mailing list, send mail to it and receive again. Play around.

Last touches to mailman

Only one more thing remains to be done for mailman and that is to create a .qmail-default file for all other lists. The content of this file should be:

|preline /usr/bin/python /usr/local/mailman/bin/qmail-to-mailman.py

And one needs to edit the bin/qmail-to-mailman.py file slightly in order to get things working. There is 3 config variables need the top of the file which you need to edit. Mine looks like:

# Configuration variables - Change these for your site if necessary.
MailmanHome = "/usr/local/mailman"; # Mailman home directory.
MailmanVar = "/usr/local/mailman"; # Mailman directory for mutable data.
MailmanOwner = "postmaster@pug.lan"; # Postmaster and abuse mail recepient.
# End of configuration variables.

This script will look at the to part of the mail (using the LOCAL environment variable as supplied by qmail-local). It then proceeds to execute the mailman program with the appropriate parameters. It automatically bounces any messages to invalid addresses.

It however contains a bug. It cannot handle VERP by default, it basically checks for "-bounces$". I therefor wrote a patch that fixes this problem by also adding an action for -bounces[-+].*$:

--- qmail-to-mailman.py.orig	2005-07-30 15:10:51.000000000 +0200
+++ qmail-to-mailman.py	2005-07-30 15:10:26.000000000 +0200
@@ -77,6 +77,7 @@
     type = "post"
     types = (("-admin$", "bounces"),
              ("-bounces$", "bounces"),
+             ("-bounces[-+].*$", "bounces"),
              ("-join$", "join"),
              ("-leave$", "leave"),
              ("-owner$", "owner"),

Adding mailing lists

This is achieved by doing:

  1. # su - mailman
  2. $ bin/newlist
  3. $ exit

Simply fill in the details as requested and you are done with the mailman side. This can also be done via the web interface.

In order to get qmail to play with we only need to add a single entry to the users assign file /var/qmail/users/assign. This line needs to match listname*@... and deliver it to the mailman user with the appropriate LOCAL environment variable set. A line such as:

+listname:mailman:280:280:/usr/local/mailman:-:listname:

achieves this. Your list should now be working correctly after you have run qmail-newu as root.

The web-interface

Just worked for me, I did not have any issues other than having had to restart apache after installing mailman. It basically uses /mailman/* to admin mailman and /pipermail/* for archives. All administration, including adding lists (except for the entry to be added to /var/qmail/users/assign.

VERP

VERP stands for Variable Envelope Return Path. It ensures that each message that gets sent out has a different return path (where to send bounces to). This means that the address to which a message bounces can be used to determine the address the message was sent to. To see why this is usefull, consider the situation where I subscribe jaco@pug.lan to a list testy@pug.lan, I then make jaco@pug.lan forward to fred@pug.lan. Should the message then bounce when attempting to deliver to fred it is not always possible from the bounce to determine that the message was orriginally sent out to jaco@pug.lan. It also means that we don't need to parse any email addresses since we can simply look at the address that the message bounced to and it is thus simple to find the quilty address (It means admins like me won't have to send out a few thousand individual messages when there is one user where the above holds in order to determine which address to nuke from the list). An additional advantage is that it allows us to send bounces off to mailman and the admin don't have to see a bounce in his life.

Whilst Mailman can still do VERP without help from the MTA getting the MTA to perform VERP is much more efficient. Thus I recommend following the instructions below in order to VERP every single message without (much) additional overhead.

To configure VERP to work with qmail we need a single file from https://sourceforge.net/tracker/?func=detail&atid=300103&aid=645513&group_id=103. On the page you should find a download link for Qmail.py. Store this file in ~mailman/Mailman/MTA. To actually make use of this module it is required to edit ~/mailman/Mailman/mm_cfg.py and add the following lines

DELIVERY_MODULE = 'Qmail'
QMAIL_CMD = '/var/qmail/bin/qmail-inject'
DO_QMAIL_VERP = 1
QVERP_FORMAT = None
QMAIL_LOG_SUCCESS = None
QMAIL_LOG_FAILURE = 'logs/qmail-failures'
QMAIL_LOG_EVERY_MESSAGE = None

VERP_PASSWORD_REMINDERS = Yes
VERP_PERSONALIZED_DELIVERIES = Yes
VERP_DELIVERY_INTERVAL = 1

As you can see, the lines are devided into two blocks. The upper block is required config, the bottom few is optional, but is required to actually activate VERP

  • DELIVERY_MODULE
    Informs Mailman to make use of the Qmail.py file which we have just downloaded.
  • QMAIL_CMD
    The path to your qmail-inject binary, this should always be as above due to the way distributions has to package Dan Berkenstein's software.
  • QVERP_FORMAT
    The format to use for VERP. I don't know how this works, but a seemingly decent default is set is Defaults.py and results in listname-bounces-username=domain@your.lists.server which is handled perfectly if you followed the config as described above.
  • QMAIL_LOG_SUCCESS
    Where to log successfull deliveries to. Ok, since we handle a large amount of mail we don't want all this logged, you can configure this if you want to.
  • QMAIL_LOG_FAILURE
    We should never get any, but in case we do I would like to know about it.
  • QMAIL_LOG_EVERY_MESSAGE
    I might be insance, machogistic I'm not. If you handle a small amount of email, you might want to do this.
  • VERP_PASSWORD_REMINDERS
    Should password reminders be VERPalised?
  • VERP_PERSONALIZED_DELIVERIES
    Should personalized devliveries be VERPalised?
  • VERP_DELIVERY_INTERVAL
    Most MTAs don't support VERP the way qmail does, thus mailman then sends individual email messages out to each client. This allows the system administrator to state how frequently messages should be VERPalised. Since qmail can do this the additional overhead is minimal as we still only send the message once. Qmail does a seperate delivery from there on for every destination address anyway so we don't even increase the number of outgoing deliveries from the server, we only hit a slight overhead on processing and possibly on temporary storage (not sure how big the impact is).

This concludes everything I know about integrating qmail and mailman, and making it use VERP. I hope it was usefull, if welcome any comments, suggestions and/or corrections.