Mailing-list administrator tips and tricks

This page lists some tips and tricks for people running mailing lists on CSAIL’s mailing-list server. (Many of these will also apply to mailing lists at other sites also using the GNU Mailman list-management software.)

See also

The listadmin command for command-line moderation

There’s a listadmin command (in the package of the same name on Ubuntu and Debian, so sudo apt-get install listadmin) which allows for command-line mailing list moderation. You give it a config file that lists the lists you manage and points at the web URL for them, and it will go through the moderator queues for the various lists and allow you to accept, discard, reject, or defer all the held posts (and/or subscription requests).

By default it asks you for the password for each list which will be echoed to the screen, but if you have a safe place to store the config file you can put the list passwords in it. This saves you not only the need to paste each mailing-list moderation URL into a browser, but also the need to type a password for each list. I strongly recommend you only put passwords in a listadmin config file on a single-user machine with your home directory on local disk, like a laptop.

Here’s an example ~/.listadmin.ini customized for CSAIL:

default skip
log ~/.listadmin.log

adminurl https://lists.csail.mit.edu/mailman/admindb/{list}

# no "password" directive yet, so this first list will prompt:
my-secure-list@lists.csail.mit.edu

# this password will be used for the following two lists:
password "Ieghio9Maith"
mycourse@lists.csail.mit.edu
mycourse-staff@lists.csail.mit.edu

# and this password will be used for the last list in this file:
password "gooZ2wiv9jah"
mycommittee@lists.csail.mit.edu

# You can even have lists on multiple servers:
adminurl https://mypersonaldomain.example.org/mailman/admindb/{list}
password "ed0aeGh8ieP7"
myfriends@mypersonaldomain.example.org

The man page is pretty clear, and there’s a page about it at Ubuntu Geek.

You can also manually add or remove subscribers (individually or in bulk from a file of addresses).

If you put passwords in your ~/.listadmin.ini make sure your home directory and the permissions on the file (or ACLs on your AFS home directory) are secure. I would encourage you to use this on a single-user laptop or on a machine where your home directory is not on shared storage rather than storing your config file in AFS. Do not put files with passwords on NFS, because NFS is not at all secure; anyone on the CSAIL network can read your data.

Limiting who can subscribe to a list

There’s a ban_list option which specifies addresses (or patterns to match for addresses) that are prohibited from subscribing to a list. To find it, go to your mailing list’s administration page (at https://lists.csail.mit.edu/mailman/admin/YOURLISTNAMEHERE), and choose “Privacy options…” and “Subscription rules” underneath that, and scroll down to “List of addresses which are banned from membership in this mailing list. (Details for ban_list)".

The simplest way to use that is to add individual, complete email addresses, one per line. For instance, if annoying@example.com keeps trying to subscribe to your list even after having been rejected several times, you could put annoying@example.com in that field, and click “Submit Your Changes”.

But that doesn’t help if you get mail from lots of different addresses, say, annoying1@example.com, annoying9@example.com, and so on.
Fortunately, GNU Mailman lets you specify a pattern to match by putting a caret (^) at the front of the line. (That pattern is a regular expression, specifically a Perl-compatible regular expression as implemented by Python, and technically the caret at the front is part of the regular expression, but it is also used as a signal to treat that line as a regular expression and not just a static email address to match.)

Regular expressions have whole books written about them, but if you just want to block subscriptions by email addresses that have a particular string of letters and/or numbers (and/or underscores, at signs, and hyphens) in them, it’s pretty simple:

^.*@yahoo
^.*noreply
^.*no-reply
^.*no_reply
^.*@hotmail

Those expressions will match any email addresses with noreply, no-reply, or no_reply anywhere in them, as well as addresses at domains starting with yahoo or hotmail (so that would match foo@yahoo.com but also bar@yahoo.co.uk and baz@yahoo.fr).

You want to be careful not to block more than you intend! For instance, if you get lots of bogus subscription requests for addresses like info@random.dom.ain, info@another.hosting.provider, info1@else.where, you might be tempted to try

 `^.*info` ← *you probably don't want this*

but that matches anywhere in the address, so it would also prevent wang-ck@informatique.uni.fr and infosec-officer@bigcompany.com from subscribing. You could be more specific with something like

^info[0-9]*@

which matches info only at the start of an email address, followed by zero or more digits before the @ sign. So that would match info@anything or info930@anything, but not jane@useful.info or security-information@example.com.

It might be particularly convenient to block all email addresses ending with a particular string. For instance, if you’re getting a rash of bogus subscription requests from various com.mx (Mexican commercial) domains, you could block them all with

^.*com\.mx$

where the $ means only to match at the end. (And we use \. here because just . matches any single character, while \. will match an actual period character.)

Only allowing MIT addresses to subscribe

And finally, you may only want to allow MIT addresses to subscribe to your list (or maybe just CSAIL addresses, or addresses at any .edu email address). Using some of the fancy features of Mailman’s Perl-compatible regular-expression language, that’s possible. This pattern:

^(?!.*mit\.edu$)

will match any email address that does not end in mit.edu. (So using this would allow address1@mit.edu, address2@csail.mit.edu, address3@media.mit.edu, and for that matter address4@summit.edu, but not address5@harvard.edu or address6@gmail.com. You can get a little fancier with the regular expression if you want to allow MIT and subdomains, but not @summit.edu addresses.)

Similarly, to allow people to subscribe only from @csail.mit.edu addresses you could use

^(?!.*@csail\.mit\.edu$)

and to allow anyone from any .edu address to subscribe, you could use just

^(?!.*\.edu$)

Since this is a way of expressing “block anything except…” rather than “don’t block…", it only makes sense to have one expression in your ban_list field if you use one of these “anything except” expressions If you had

# THIS WON'T WORK
^(?!.*mit\.edu$)
^(?!.*harvard\.edu$)

in the field, the first line would match (and prevent subscriptions by) any address that didn’t end in mit.edu (including all harvard.edu addresses, and the second line would match (and prevent subscriptions by) any address that didn’t end in harvard.edu (including all mit.edu addresses), so nobody could subscribe.

Preventing ANY new subscriptions

Blocking new subscriptions like this doesn’t affect any addresses that are already subscribed, but it does prevent you as list administrator from manually subscribing addresses that match via the “Membership Management…” > “Mass Subscription” form.

Given that fact, if you run a mailing list that already has everybody on it who should ever be able to subscribe (or if additions are rare and you’ll always be doing them yourself), you could prevent any new subscriptions by putting the expression

^.

in the ban_list field. That is a regular expression that will match any email address that starts with at least one character, any character, so it will match all email addresses and prevent any new subscriptions. (If you do eventually need to subscribe somebody to the list, you can take that line out of ban_list, save your change, add the new address, and put the ^. line back in. The mass-subscription form will give you an informative error up at the top if you try to add an email address that matches a ban_list pattern, but the error is easy to miss.)