Mailman – a mailing list manager

Mailman – a mailing list manager

Mailman is a mailing list manager.
This article will demonstrate how I set up Mailman and converted some mailing lists from
Majordomo. I’ll be using FreeBSD 6.0-STABLE,
Postfix 2.2.7, and MailMan 2.17 but you will probably find these instructions useful no matter that operating
system and version you are planning to use.

Mailman has a web component that can be used for subscribing, administration, and archives. I’ll be showing
how I configured Apache to work with Mailman.

With this solution, I’m making the following assumptions

  • All mail for your list goes to a specific domain. In my case, lists.freebsddiary.org. I do it
    this way so that I can easily change the mail server to another host should the need arise.
    It also simplifies the solution in that all mail for that host goes to Mailman, not to a user.
  • Postfix is your mail server, and you want to use virtual domains.
  • You will give unique names to each mailing list. You will not have announce@h1.example.org and
    announce@h2.example.org. Instead, you will have announce-h1@h1.example.org and
    example-h2@h2.example.org. Again, this simplifies the solution.

Installation

Installation is a no-brainer. But if you are using anything other than sendmail as your
mail server, you’ll need to tell Mailman about it. The make options command
shows you a lot of things you can tweak. I recommend leaving everything as the default
value except for setting the right value for MAIL_GID. Since I’m using Postfix,
I’ll use the following command for installation:

cd /usr/ports/mail/mailman
make MAIL_GID=mailman install clean

That will install mailman and clean up the working files when it is done.

16 April 2006

When it came time to upgrade Mailman at at later date, I found this worked for me:


export MAIL_GID=mailman
portupgrade mailman

NOTE: after reinstalling mailman, you need to restart it:

/usr/local/etc/rc.d/mailman.sh start

In later versions of Mailman, the command is

/usr/local/etc/rc.d/mailman start

NOTE the missing .sh

This point has stumped me more than once. I’d send a message. Nothing happened.
Starting up the mailman queue processing helps.

Configuration

This isn’t the first time I have set up Mailman. I know I played with it twice before, the latest
of which I think was in 2003. At the time, I thought the documentation wasn’t very clear in some
crucial aspects. In particular, while they may document things well, they don’t provide enough
practical examples to demonstrate how to use a particular feature.
I hope things will go smoother this time.

Be sure to read /usr/local/share/doc/mailman/FreeBSD-post-install-notes.

I started by setting up lists.freebsddiary.org. I’m not going to describe
how to set up the DNS. That is outside the scope of this article and I have several
articles about DNS. Similarly, I won’t tell you how to
set up a virtual server in Apache, but you can
read something about that. However, the virtual
host for this:

<VirtualHost *>
    ServerAdmin     dan@langille.org
    
    DocumentRoot    /path/to/www/lists.freebsddiary.org/www
        
    ServerName      lists.freebsddiary.org
            
    ScriptAlias /mailman   "/usr/local/mailman/cgi-bin"
    Alias       /pipermail "/usr/local/mailman/archives/public"
    
    ErrorLog        /path/to/www/log/lists.freebsddiary.org-error.log
    CustomLog       /path/to/www/log/lists.freebsddiary.org-access.log combined
                            
</VirtualHost>

I think the most important document to read is /usr/local/share/doc/mailman/mailman-install.txt.
You can also read that document online in HTML form.
From that document, I performed these steps.

  1. From Step 4, I ran bin/check_perms. It found nothing wrong.
  2. I’m using Postfix, so I followed “6.1 Using the Postfix mail server” closely.
    Specifically, I made sure these items were in /usr/local/etc/postfix/main.cf:

    recipient_delimiter = +
    unknown_local_recipient_reject_code = 550
    transport_maps = hash:/usr/local/etc/postfix-config/transport
    mailman_destination_recipient_limit = 1

    Combined with the above, I added the following to
    /usr/local/etc/postfix-config/transport (NOTE: you can use any
    file name you want; just be consistent with it.):

    lists.freebsddiary.org mailman:

    Remember to process that file first:

    postmap /usr/local/etc/postfix-config/transport

    That will create the database file Postfix will use.

    I also let Postfix know that it should accept mail for lists.freebsddiary.org
    by adding this entry to /usr/local/etc/postfix/main.cf:

    relay_domains = lists.freebsddiary.org
    

    If you already have a relay_domains entry, add to it. Do not replace.

    And I added this to /usr/local/etc/postfix/master.cf:

    mailman unix  -       n       n       -       -       pipe
          flags=FR user=mailman:mailman
          argv=/usr/local/mailman/postfix-to-mailman-2.1.py ${nexthop} ${user}
    

    You’ll see a reference to postfix-to-mailman.py above. You need to download that
    manually and install it to the indicated directory. You can get that from
    http://www.gurulabs.com/goodies/downloads.php.
    I grabbed the one for Mailman 2.1 version and renamed the file accordingly.
    I changed some items within the file:

    #! /usr/local/bin/python
    
    # Configuration variables - Change these for your site if necessary.
    MailmanHome = "/usr/local/mailman"; # Mailman home directory.
    MailmanOwner = "postmaster@havoc.example.org";
    # End of configuration variables.

    The items I changed are in bold.

  3. And to integrate Postfix and Mailman, I followed “6.1.1 Integrating Postfix and Mailman”.
    • I added this to /usr/local/mailman/Mailman/mm_cfg.py:
      MTA = 'Postfix'

      I found I didn’t need the following entries at all:

      POSTFIX_STYLE_VIRTUAL_DOMAINS = ['lists.freebsddiary.org']
      
      add_virtualhost(DEFAULT_URL_HOST, DEFAULT_EMAIL_HOST)
      add_virtualhost('lists.freebsddiary.org','lists.freebsddiary.org')

      Those last two entries deal with virtual hosts.
      But given the script I’m using (postfix-to-mailman.py), perhaps those
      items are no longer required.

    • I checked the values of POSTFIX_ALIAS_CMD and
      POSTFIX_MAP_CMD in /usr/local/mailman/Mailman/Defaults.py.
    • As root, I issued these commands to generate the aliases:
      cd /usr/local/mailman
      bin/genaliases
    • Followed by these commands to make sure the files are owned by mailman:
      cd /usr/local/mailman/data
      chown mailman aliases aliases.db
      chmod g+w aliases aliases.db
    • I told Postfix about the aliases by adding this to
      /usr/local/etc/postfix/main.cf:

      hash:/usr/local/mailman/data/aliases

      You should add the above directive to any existing alias_maps =
      directive.

  4. You’ll need to restart Postfix and Apache. Check for errors
  5. Create a site-wide mailing list. Following step 8 of the
    mailman-install.txt, I did this (see later in this step
    for a better method):

    bin/newlist mailman
    bin/config_list -i data/sitelist.cfg mailman

    The list creation email that you receive will have the wrong hostname in the
    URLs. Ignore that point. In a latter step, we’ll fix that URL.

    You can avoid the fixing step if you specify the email host and web host on the
    command line:

    bin/newlist --urlhost=lists.freebsddiary.org \
        --emailhost=lists.freebsddiary.org freebsddiary-announce
    

    NOTE: I’ve split the above into two lines.

  6. Set up the cronjob for mailman:
    cd /usr/local/mailman/cron
    crontab -u mailman crontab.in
  7. Start the queue processing:
    cd /usr/local/mailman
    bin/mailmanctl start
  8. If we didn’t specify the mail host and web host on the command line,
    we need to fix the URL for this list:

    bin/withlist -l -r fix_url freebsddiary-announce --urlhost=lists.freebsddiary.org
    

    With the above we change the URL for the list freebsddiary-announce by setting
    it to lists.freebsddiary.org.

    Ignore the incorrect URL in the list correction email. The above command fixes
    that.

Now you should be able to browse to your mailman interface. Like I can:

http://lists.freebsddiary.org/mailman/listinfo

Creating the first list

I will now create the freebsddiary-announce mailing list:

cd /usr/local/mailman
bin/newlist freebsddiary-announce

Shortly thereafter, you should get an email with a list of all the things you need to know.

Problems I encountered

This section outlines some of the problems I encountered and the solution.

relay access denied

Symptoms: messages to the list bounce with:


<freebsddiary-announce@lists.example.org>: host
lists.freebsddiary.org[66.154.98.130] said: 554
<freebsddiary-announce@lists.example.org>: Relay access denied (in
reply to RCPT TO command)

I was missing an entry from relay_domains in main.cf.

no such file or directory

Symptoms: messages to the list bounce with:

<freebsddiary-announce@lists.example.org>: Command died with status 127:
"/usr/local/mailman/postfix-to-mailman.py". Command output: env: python: No
such file or directory

The first line of the postfix-to-mailman.py script was wrong. See above for my
changes to this file.

command died with status 1

Symptoms: messages to the list bounce with:

<freebsddiary-announce@lists.example.org>: Command died with status 1:
"/usr/local/mailman/postfix-to-mailman.py"

Solution: chmod +x /usr/local/mailman/postfix-to-mailman.py

Command died with status 1

Symptoms: messages to the list bounce with:


<freebsddiary-anounce@lists.example.org>: Command died with status 1:
"/usr/local/mailman/postfix-to-mailman.py". Command output: TO ACCESS THE
MAILING LIST SYSTEM: Start your web browser on http://lists.example.org/
That web page will help you subscribe or unsubscribe, and will give you
directions on how to post to each mailing list.

Solution: Your list does not exist. Spell it correctly. In this case,
I’m missing a n from announce.

command died with status 2

Symptoms: messages to the list bounce with:


<freebsddiary-announce@lists.example.org>: Command died with status 2:
"/usr/local/mailman/postfix-to-mailman.py". Command output: Group mismatch
error. Mailman expected the mail wrapper script to be executed as group
"mail", but the system's mail server executed the mail script as group
"mailman". Try tweaking the mail server to run the script as group "mail",
or re-run configure, providing the command line option
--with-mail-gid=mailman'.

Solution: reinstall mailman using the instruction shown at the start of this
article. Key point: MAIL_GID setting is incorrect.

Problem with mailman archives

I encountered one problem with mailman archives. It was reported by Mark Linimon who was unable to view the archives
for the BSDCan Announce mailing list. If you
clicked on bsdcan-announce Archives you would be presented
with:


Forbidden
You don't have permission to access /pipermail/bsdcan-announce/ on this server.

Apache/1.3.34 Server at lists.bsdcan.org Port 80

Looking at the server logs for that website, I saw:

(13)Permission denied: access to /pipermail/bsdcan-announce/ failed because search permissions are missing on a component of the path

Googling led me to suspect symlinks were the cause of the problem. Looking at the mailman directory structure supported this theory.
I was to be proven wrong. The cause of the problem was directory permissions. I show you what I did wrong just to document
what I did wrong. 🙂 I show you the correct solution at the end of this section.

Here is what I found in that directory:


$ ls -l
total 0
lrwxr-xr-x 1 root mailman 51 Mar 1 07:17 bsdcan-announce -> /usr/local/mailman/archives/private/bsdcan-announce

I added one set of symlinks:


<Location /pipermail>
    Options     Indexes FollowSymLinks
</Location>

And I restarted tested the configuration and restarted Apache:


$ sudo apachectl configtest
Syntax OK
$ sudo apachectl graceful
/usr/local/sbin/apachectl graceful: httpd gracefully restarted

The problem persisted. OK, what about another symlink?


<Location /pipermail/bsdcan-announce>
    Options     Indexes FollowSymLinks
</Location>

The correct solution

Another configtest and graceful indicated I was wrong. It was then that I started to look at the symlink destination:
/usr/local/mailman/archives/private/:


[dan@havoc:/usr/local/mailman/archives] $ ls -l
total 4
drwxrws---  30 root  mailman  1024 Apr 14 12:05 private
drwxrwsr-x   2 root  mailman   512 Apr 14 12:05 public

Ahhh! There’s the problem. Apache, running as user www, cannot access the archives that
are found in private. A quick chmod to test the theory:

chmod o=rx private

Success! Now I can view the BSDCan announce list archives properly.

I went back and removed the <Location…> directives from the virtual host, retested the configuration, and did a graceful on Apache.
I browsed to the URL again to confirm the FollowSymLinks directive was not required. All as well.

Adding more domains

The above uses only one domain (lists.freebsddiary.org). I hope to add others later.
That will be in another article. Enjoy.

A word about backups

I’m now backing up /usr/local/mailman. The empty files are about 30MB. No
sense not backing up everything! And, of course, I’m using Bacula.

1 thought on “Mailman – a mailing list manager”

Leave a Comment

Scroll to Top