Installation and Configuration

An installation and configuration guide to mlmmj. This guide includes howtos for the tunables, and also information on how to make mlmmj play nice with different mail servers.

Installing mlmmj

Installing mlmmj is trivial. Simply compile it if you're not using a binary package such as dpkg, rpm or a ports collection from a BSD or Gentoo. To compile, untar the tar-ball and do:

$ ./configure && make && make install

That is it. Now on to making a new list.

Creating a new list

To create a new list follow steps 1-5 and optionally you can also do steps 6-10.

  1. Configure a recipient delimiter. The default is to use '+', and in Postfix it's done by adding
    recipient_delimiter = +
    

    to /etc/postfix/main.cf. In Exim it can be done by adding

    local_part_suffix = +*
    local_part_suffix_optional
    

    to the "userforward:" and the "localuser:" router in /etc/exim/exim.conf, and also add "local_part_suffix = +*" to the system_aliases function. Also make sure that exim will add the envelope from in the Return-Path: header.

    There is a nice FAQ explaining recipient delimiter configuration here

    The "delimiter" tunable configures this on a per list basis

  2. Create the mailinglist. There's a script, mlmmj-make-ml.sh, that will make a mailinglist for mlmmj. It is highly recommended to use this script to make the lists! What is does is described here:

    In the case of a list called mlmmj-test below /var/spool/mlmmj it makes the
    following directories:

     /var/spool/mlmmj/mlmmj-test/incoming
     /var/spool/mlmmj/mlmmj-test/queue
     /var/spool/mlmmj/mlmmj-test/queue/discarded
     /var/spool/mlmmj/mlmmj-test/archive
     /var/spool/mlmmj/mlmmj-test/text
     /var/spool/mlmmj/mlmmj-test/subconf
     /var/spool/mlmmj/mlmmj-test/unsubconf
     /var/spool/mlmmj/mlmmj-test/bounce
     /var/spool/mlmmj/mlmmj-test/control
     /var/spool/mlmmj/mlmmj-test/moderation
     /var/spool/mlmmj/mlmmj-test/subscribers.d
     /var/spool/mlmmj/mlmmj-test/digesters.d
     /var/spool/mlmmj/mlmmj-test/nomailsubs.d
     /var/spool/mlmmj/mlmmj-test/requeue
    

    NOTE: The mailinglist directory (/var/spool/mlmmj/mlmmj-test in our example) have to be owned by the user the mailserver writes as. On some Postfix installations Postfix is run by the user postfix, but still writes files as nobody:nogroup or nobody:nobody

  3. Make the changes to your mailserver aliases that came as output from mlmmj-make-ml.sh. Following the example above they will look like this:
    mlmmj-test:     "|/usr/bin/mlmmj-recieve -L /var/spool/mlmmj/mlmmj-test"
    

    NOTE: Don't forget newaliases.

  4. Start mlmmj-maintd (remember full path when starting it!) or add it to crontab with -F switch. The recommended way for now is to run it via cron:
     "0 */2 * * *  /usr/bin/mlmmj-maintd -F -L /var/spool/mlmmj/mlmmj-test"
    

    It should be started as root, as mlmmj-maintd will become the user owning the listdir (/var/spool/mlmmj/mlmmj-test), and log it's last maintenance run to listdir/mlmmj-maintd.lastrun.log.

    If you have several lists below /var/spool/mlmmj you can use -d:

     /usr/bin/mlmmj-maintd -F -d /var/spool/mlmmj
    
  5. If you want to you can pre-subscribe some people
    /usr/bin/mlmmj-sub -L /var/spool/mlmmj/mlmmj-test/ -a joe@domain.tld
    
  6. If you want custom headers like X-Mailinglist, Reply-To: etc. just add a file called 'customheaders' in the list control/ directory like this:
        $ cat /var/spool/mlmmj/mlmmj-test/control/customheaders
        X-Mailinglist: mlmmj-test
        Reply-To: mlmmj-test@domain.tld
    
  7. If you want every mail to have something like:
    -- 
    To unsubscribe send a mail to coollist+unsubscribe@lists.domain.net
    

    Just add what you want to a file named "footer" in the same dir as "customheader" (listdir/control/).

  8. If you want a prefix on the subject, to make it look like this:
    Subject: [mlmmj-test] how are we doing?
    

    Simply do

    echo "[mlmmj-test]" > control/prefix
  9. For having a moderated list, simply create a file called 'moderated' in the control/ directory. Moderators are added to a file called 'moderators' in the control/ dir as well.
  10. Have a look at the file TUNABLES for runtime configurable things.

Tunables

The following files can be used for changing the behaviour of a list. The filename is supposed to be below listdir/control. In the case it's a "boolean", the contents of a file does not matter, the mere presence of it, will set the variable to "true". If it's a "normal" file, the first line will be used as value, leaving line 2 and forward ready for commentary etc. If it's possible to specify several entries (one per line), it's marked "list".

access (list)

If this file exists, all headers of a post to the list is matched against the rules. The first rule to match wins. See access rules for syntax and examples.

addtohdr (boolean)

When this file is present, a To: header including the recipients emailaddress will be added to outgoing mail. Recommended usage is to remove existing To: headers with delheaders (see above) first.

bouncelife (normal)

Here is specified for how long time in seconds an address can bounce before it's unsubscribed. Defaults to 432000 seconds, which is 5 days.

closedlist (boolean)

Is the list is open or closed. If it's closed subscription and unsubscription via mail is disabled.

closedlistsub (boolean)

This works like closedlist, except it allows unsubscription by normal means.

customheaders (list)

These headers are added to every mail coming through. This is the place you want to add Reply-To:, List-Info:, etc headers in case you want such.

delheaders (list)

In this file is specified *ONE* headertoken to match per line. If the file
consists of:

Received:
Message-ID:

Then all occurences of these headers in incoming list mail will be deleted. "From " and "Return-Path:" are deleted no matter what.

delimiter (normal)

This specifies what to use as recipient delimiter for the list. Default is "+".

digestinterval (normal)

This file specifies how many seconds will pass before the next digest is sent. Defaults to 604800 seconds, which is 7 days.

digestmaxmails (normal)

This file specifies how many mails can accumulate before digest sending is triggered. Defaults to 50 mails, meaning that if 50 mails arrive to the list before digestinterval have passed, the digest is delivered.

listaddress (list)

This file contains all addresses which mlmmj sees as listaddresses (see tocc below). The first one is the one used as the primary one, when mlmmj sends out mail.

mlmmj - maling list management made joyful


The functionality

  1. Archive
  2. Custom headers / foote
  3. Fully automated bouncehandling (similar to ezmlm)
  4. Complete requeueing functionality
  5. Moderation functionality
  6. Subject prefix
  7. Subscribers only posting
  8. Regular expression access control
  9. Functionality to retrieve old posts
  10. Web-interface
  11. Digests
  12. No mail delivery subscription
  13. VERP support
  14. Delivery Status Notification (RFC1891) support

There's a mailing list, , for discussions of any kind with regards to mlmmj. Archive.
Feel free to join in by sending a mail to .

On to the project page

maxmailsize (normal)

With this option the maximal allowed size of incoming mails can be specified.

maxverprecips (normal)

How many recipients per mail delivered to the smtp server. Defaults to 100.

memorymailsize (normal)

Here is specified in bytes how big a mail can be and still be prepared for sending in memory. It's greatly reducing the amount of write system calls to prepare it in memory before sending it, but can also lead to denial of service attacks. Default is 16k (16384 bytes).

moderated (boolean)

If this file is present, the emailaddresses in the file listdir/control/moderators will act as moderators for the list.

modnonsubposts (boolean)

When this file is present and subonlypost is enabled, all postings from people who are not subscribed to the list will be moderated.

noaccessdenymails (boolean)

This switch turns off whether mlmmj sends out notification about postings being denied when it was rejected due to an access rule (see 'access').

noarchive (boolean)

If this file exists, the mail won't be saved in the archive but simply deleted.

nodigestsub (boolean)

If this file exists, subscription to the digest version of the mailinglist will be denied. (Useful if you don't want to allow digests and notify users about it).

nodigesttext (boolean)

If this file exists, digest mails won't have a text part with a thread summary.

noget (boolean)

If this file exists, then retrieving old posts with +get-N is disabled.

nomaxmailsizedenymails (boolean)

If this is set, no reject notifications caused by violation of maxmailsize will be sent.

nonomailsub (boolean)

If this file exists, subscription to the nomail version of the mailinglist will be denied. (Useful if you don't want to allow nomail and notify users about it).

nosubconfirm (boolean)

If this file exists, no mail confirmation is needed to subscribe to the list. This should in principle never ever be used, but there is times on local lists etc. where this is useful.
HANDLE WITH CARE!

nosubonlydenymails (boolean)

This switch turns off whether mlmmj sends out notification about postings being denied due to it's a subscribers only posting list (see 'subonlypost').

notifysub (boolean)

If this file is present, the owner(s) will get a mail with the address of someone sub/unsubscribing to a mailinglist.

notoccdenymails (boolean)

This switch turns off whether mlmmj sends out notification about postings being denied due to the listaddress not being in To: or Cc: (see 'tocc').

owner (list)

The emailaddresses in this file (1 per line) will get mails to listname+owner@listdomain.tld

prefix (normal)

The prefix for the Subject: line of mails to the list. This will alter the Subject: line, and add a prefix if it's not present elsewhere.

relayhost (normal)

The host specified (IP address or hostname, both works) in this file will be used for relaying the mail sent to the list. Defaults to 127.0.0.1.

smtpport (normal)

In this file a port other than port 25 for connecting to the relayhost can be specified.

submod (list)

If this file is present, subscription will be moderated by owner(s). If there are emailaddresses in this file, then these will be used instead of owner.

subonlyget (boolean)

If this file exists, then retrieving old posts with +get-N is only possible for subscribers. The tunable 'noget' has precedence.

subonlypost (boolean)

When this file is present, only people who are subscribed to the list, are allowed to post to it. The check is made against the "From:" header.

tocc (boolean)

If this file is present, the list address does not have to be in the To: or Cc: header of the email to the list.

verp (normal)

Enable VERP support. Anything added in this variable will be appended the MAIL FROM: line. If "postfix" is put in the file, it'll make postfix use VERP by adding XVERP=-= to the MAIL FROM: line.

Access rules

If the file listdir/control/access is present, access control is enabled.

NOTE: the default action is to deny access (reject the mail), so an empty access control file will cause mlmmj to reject all posts, whereas a non-existant file will change nothing, and mlmmj will behave as usual.

Each header in the mail is tested against each rule, rule by rule. That is, all headers are first tested against the first rule, then all headers are tested against the second rule, and so on.

The first rule to match a header decides which action to take - allow, deny or moderate the post.

The syntax is quite simple:

action[ [!]regexp]

IMPORTANT: if "moderate" is used then don't forget to add people who should function as moderators in listdir/control/moderators

First a simple example. This rule set will reject any mail that is NOT plain text, or has a subject that contains "BayStar", and allow anything else:

 deny !^Content-Type: text/plain
 deny ^Subject:.*BayStar
 allow

To allow only text mails, but have the moderators moderate every html mail one would use this:

 allow ^Content-Type: text/plain
 moderate ^Content-Type: text/html
 deny

Now on to a more advanced example. Morten can post anything, Mads Martin can post if the subject does not contain "SCO". Everything else is denied:

 allow ^From: Morten
 deny ^Subject:.*SCO
 allow ^From: Mads Martin
 deny

The last rule (deny) can be left out, as deny is the default action.

A third example. Deny any mails with "discount", "weightloss", or "bonus" in the subject. Allow PGP signed and plain text mails. Anything else is denied:

 deny ^Subject:.*discount
 deny ^Subject:.*weightloss
 deny ^Subject:.*bonus
 allow ^Content-Type: multipart/signed
 allow ^Content-Type: text/plain

Exim4 configuration

This is a step-by-step guide to run mlmmj with Exim4. The most current version
of this can be found on http://plonk.de/sw/mlmmj/README.exim4.

Notes:

  1. In the main configuration section:
    MLMMJ_HOME=/var/spool/mlmmj
    domainlist mlmmj_domains = list.example.net
    
  2. Add +mlmmj_domains to relay_to_domains:
    domainlist relay_to_domains = other.domain : +mlmmj_domains
    
  3. mlmmj is barely interested in delay warnings, so add this in the main
    configuration:

    delay_warning_condition = ${if match_domain{$domain}{+mlmmj_domains}{no}{yes}}
    
  4. In the routers section (before the dnslookup router, preferably at the
    beginning):

    mlmmj_router:
      driver = accept
      domains = +mlmmj_domains
      require_files = MLMMJ_HOME/${lc::$local_part}
      # Use this instead, if you don't want to give Exim rx rights to mlmmj spool.
      # Exim will then spawn a new process running under the UID of "mlmmj".
      #require_files = mlmmj:MLMMJ_HOME/${lc::$local_part}
      local_part_suffix = +*
      local_part_suffix_optional
      headers_remove = Delivered-To
      headers_add = Delivered-To: $local_part$local_part_suffix@$domain
      transport = mlmmj_transport
    

    If you want VERP to be done by your MTA, also add this:

    verp_router:
      driver = dnslookup
      domains = !+mlmmj_domains
      # we only consider messages sent in through loopback
      condition = ${if eq{$sender_host_address}{127.0.0.1}{yes}{no}}
      ignore_target_hosts = <; 0.0.0.0; 127.0.0.0/8; ::1/128; fe80::/10; ff00::/8
      # only the un-VERPed bounce addresses are handled
      senders = \N^.+\+bounces-\d+@.+\N
      transport = verp_smtp
    

    To prevent temporary errors for not-existing lists, add !+mlmmj_domains to the
    domains condition of the dnslookup router:

    dnslookup:
      driver = dnslookup
      domains = !+mlmmj_domains : !+local_domains
    [...]
    
  5. Somewhere in the transports section. (Change the path of mlmmj-recieve if you
    don't use the default location!):

    mlmmj_transport:
      driver = pipe
      return_path_add
      user = mlmmj
      group = mlmmj
      home_directory = MLMMJ_HOME
      current_directory = MLMMJ_HOME
      command = /usr/local/bin/mlmmj-recieve -F -L MLMMJ_HOME/${lc:$local_part}
    

    If you want VERP to be done by your MTA, also add this:

    verp_smtp:
      driver = smtp
      # put recipient address into return_path
      return_path = ${quote_local_part:${local_part:$return_path}}-\
                    ${original_local_part}=${original_domain}@\
                    ${domain:$return_path}
      # must restrict to one recipient at a time
      max_rcpt = 1
      # Errors-To: may carry old return_path
      headers_remove = Errors-To
      headers_add = Errors-To: $return_path
    
  6. Test your setup with
    $ exim -bt mlmmj-test@your.list.domain
    mlmmj-test@your.list.domain
      router = mlmmj_router, transport = mlmmj_transport
    

    If you get different output, run it with -d to see what's going wrong.
    If not, you're done!

    Jakob Hirsch (jh at plonk dot de)

qmail configuration

Using mlmmj with qmail (and vpopmail)
by Fabio Busatto

This mini-HOWTO is a step-by-step guide for using mlmmj with qmail MTA
(http://www.qmail.org/), and it has been successfully tested also with vpopmail
virtual domains (http://www.inter7.com/vpopmail/).

Prerequisites:

Conventions:

Configuration:

WARNING: REMEMBER that the delimiter is -, so do not use + when composing mail
addresses for extensions!!!

WARNING: DO NOT USE 'preline' command in dot-qmail files, it will result in
mlmmj to not work properly!!!

Example:
Configuring mlmmj to handle ml@programmazione.it mailing list using qmail as MTA and vpopmail for virtual domain support:

# mlmmj-make-ml.sh -c vpopmail:vchkpw -L ml
Creating Directorys below /var/spool/mlmmj. Use '-s spooldir' to change
The Domain for the List? [] : programmazione.it
The emailaddress of the list owner? [postmaster] : postmaster@programmazione.it
The path to texts for the list? [/usr/local/share/mlmmj/text.skel] :
chown -R vpopmail:vchkpw /var/spool/mlmmj/ml? [y/n]: y

# cd /var/spool/mlmmj/ml/control/
# echo '-' > delimiter
# chown vpopmail:vchkpw delimiter
# cd /home/vpopmail/domains/programmazione.it/
# echo -e "|/usr/local/bin/mlmmj-recieve -L /var/spool/mlmmj/ml/" > .qmail-ml
# cp -a .qmail-ml .qmail-ml-default
# cat *-default
# chown vpopmail:vchkpw .qmail-ml .qmail-ml-default
# chmod 600 .qmail-ml .qmail-ml-default

Sendmail configuration

The following configuration enables VERP (http://cr.yp.to/proto/verp.txt) which is useful for mailing list managers that are able to take advantage of that feature.

This configuration is currently used for using the mlmmj manager with VERP enabled + sendmail.

The hack consists in hooking VERP rewriting in a replacement ruleset for the existing EnvFromSMTP one (called VerpEnvFromSMTP). This is going to work *only* if we are splitting messages with multiple recipients in separate queue files since the macro we are using for the rewriting ($u) is not set when multiple rcpt are present.

The first step consists in forcing envelope splitting, this is done using the QUEUE_GROUP feature, here we are definining r=1 (max 1 rcpt per message) for the default queue group:

QUEUE_GROUP(`mqueue', `P=/var/spool/mqueue, F=f, I=1m,  R=2, r=1')

Since we are going to split a lot it's advisable to use the FAST_SPLIT option, additionally we need to enforce return-path inclusion in the local mailer:

define(`confFAST_SPLIT', `100')dnl
define(`LOCAL_SHELL_FLAGS', `eu9P')dnl

Then we define a regex map for matching the addresses that we are going to rewrite, in our example we'll rewrite addresses like

<listname+bounces-123@domain.net>

with

%lt;listname+bounces-123-user=foo.net@domain.net>

where user@foo.net is the recipient address of the message. So we need to apply
our verp ruleset *only* to those addresses. Additionally we are also adding the
Delivered-To header:

LOCAL_CONFIG
Kmatch_verp regex -m -a@VERP (listname\+bounces\-[0-9]+<@domain\.net\.?>)
H?l?Delivered-To: $u

Here's the ruleset, the first half of the ruleset is the existing EnvFromSMTP ruleset present in default sendmail.cf, the seconf half is the VERP stuff:

SVerpEnvFromSMTP
R$+                     $: $>PseudoToReal $1            sender/recipient common
R$* :; <@>              $@                              list:; special case
R$*                     $: $>MasqSMTP $1                qualify unqual'ed names
R$+                     $: $>MasqEnv $1                 do masquerading

R $*                                    $: $(match_verp $1 $)                            match the address
R $* + $* < @ $* . > $* @VERP           $: $1 + $2 - $&u < @ $3 . > $4 VERP              rewrite it using $u macro and add VERP string for failsafe
R $* - < @ $* . > $* VERP               $: $1 < @ $2 . > $3                              if $u wasn't defined rewrite the address back
R $* - < $+ @ $+ > < @ $* . > $* VERP   $: $(dequote $1 "-" $2 "=" $3 $) < @ $4 . > $5   replace the "@" in rcpt address with "="
R $* - $+ @ $+ < @ $* . > $* VERP       $: $(dequote $1 "-" $2 "=" $3 $) < @ $4 . > $5   replace the "@" in rcpt address with "="

Finally we need to rewrite the mailer definition for the used mailer (typically esmtp) specifying VerpEnvFromSMTP as the sender rewrite ruleset:

MAILER_DEFINITIONS
Mesmtp,         P=[IPC], F=mDFMuXa, S=VerpEnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990,
                T=DNS/RFC822/SMTP,
                A=TCP $h

NOTE: for mailing list servers it's also a good idea keeping existing Delivered-To headers, sendmail needs the following patch for doing this

Installation and Configuration

An installation and configuration guide to mlmmj. This guide includes howtos for the tunables, and also information on how to make mlmmj play nice with different mail servers.

Installing mlmmj

Installing mlmmj is trivial. Simply compile it if you're not using a binary package such as dpkg, rpm or a ports collection from a BSD or Gentoo. To compile, untar the tar-ball and do:

$ ./configure && make && make install

That is it. Now on to making a new list.

Creating a new list

To create a new list follow steps 1-5 and optionally you can also do steps 6-10.

  1. Configure a recipient delimiter. The default is to use '+', and in Postfix it's done by adding
    recipient_delimiter = +
    

    to /etc/postfix/main.cf. In Exim it can be done by adding

    local_part_suffix = +*
    local_part_suffix_optional
    

    to the "userforward:" and the "localuser:" router in /etc/exim/exim.conf, and also add "local_part_suffix = +*" to the system_aliases function. Also make sure that exim will add the envelope from in the Return-Path: header.

    There is a nice FAQ explaining recipient delimiter configuration here

    The "delimiter" tunable configures this on a per list basis

  2. Create the mailinglist. There's a script, mlmmj-make-ml.sh, that will make a mailinglist for mlmmj. It is highly recommended to use this script to make the lists! What is does is described here:

    In the case of a list called mlmmj-test below /var/spool/mlmmj it makes the
    following directories:

     /var/spool/mlmmj/mlmmj-test/incoming
     /var/spool/mlmmj/mlmmj-test/queue
     /var/spool/mlmmj/mlmmj-test/queue/discarded
     /var/spool/mlmmj/mlmmj-test/archive
     /var/spool/mlmmj/mlmmj-test/text
     /var/spool/mlmmj/mlmmj-test/subconf
     /var/spool/mlmmj/mlmmj-test/unsubconf
     /var/spool/mlmmj/mlmmj-test/bounce
     /var/spool/mlmmj/mlmmj-test/control
     /var/spool/mlmmj/mlmmj-test/moderation
     /var/spool/mlmmj/mlmmj-test/subscribers.d
     /var/spool/mlmmj/mlmmj-test/digesters.d
     /var/spool/mlmmj/mlmmj-test/nomailsubs.d
     /var/spool/mlmmj/mlmmj-test/requeue
    

    NOTE: The mailinglist directory (/var/spool/mlmmj/mlmmj-test in our example) have to be owned by the user the mailserver writes as. On some Postfix installations Postfix is run by the user postfix, but still writes files as nobody:nogroup or nobody:nobody

  3. Make the changes to your mailserver aliases that came as output from mlmmj-make-ml.sh. Following the example above they will look like this:
    mlmmj-test:     "|/usr/bin/mlmmj-recieve -L /var/spool/mlmmj/mlmmj-test"
    

    NOTE: Don't forget newaliases.

  4. Start mlmmj-maintd (remember full path when starting it!) or add it to crontab with -F switch. The recommended way for now is to run it via cron:
     "0 */2 * * *  /usr/bin/mlmmj-maintd -F -L /var/spool/mlmmj/mlmmj-test"
    

    It should be started as root, as mlmmj-maintd will become the user owning the listdir (/var/spool/mlmmj/mlmmj-test), and log it's last maintenance run to listdir/mlmmj-maintd.lastrun.log.

    If you have several lists below /var/spool/mlmmj you can use -d:

     /usr/bin/mlmmj-maintd -F -d /var/spool/mlmmj
    
  5. If you want to you can pre-subscribe some people
    /usr/bin/mlmmj-sub -L /var/spool/mlmmj/mlmmj-test/ -a joe@domain.tld
    
  6. If you want custom headers like X-Mailinglist, Reply-To: etc. just add a file called 'customheaders' in the list control/ directory like this:
        $ cat /var/spool/mlmmj/mlmmj-test/control/customheaders
        X-Mailinglist: mlmmj-test
        Reply-To: mlmmj-test@domain.tld
    
  7. If you want every mail to have something like:
    -- 
    To unsubscribe send a mail to coollist+unsubscribe@lists.domain.net
    

    Just add what you want to a file named "footer" in the same dir as "customheader" (listdir/control/).

  8. If you want a prefix on the subject, to make it look like this:
    Subject: [mlmmj-test] how are we doing?
    

    Simply do

    echo "[mlmmj-test]" > control/prefix
  9. For having a moderated list, simply create a file called 'moderated' in the control/ directory. Moderators are added to a file called 'moderators' in the control/ dir as well.
  10. Have a look at the file TUNABLES for runtime configurable things.

Tunables

The following files can be used for changing the behaviour of a list. The filename is supposed to be below listdir/control. In the case it's a "boolean", the contents of a file does not matter, the mere presence of it, will set the variable to "true". If it's a "normal" file, the first line will be used as value, leaving line 2 and forward ready for commentary etc. If it's possible to specify several entries (one per line), it's marked "list".

access (list)

If this file exists, all headers of a post to the list is matched against the rules. The first rule to match wins. See access rules for syntax and examples.

addtohdr (boolean)

When this file is present, a To: header including the recipients emailaddress will be added to outgoing mail. Recommended usage is to remove existing To: headers with delheaders (see above) first.

bouncelife (normal)

Here is specified for how long time in seconds an address can bounce before it's unsubscribed. Defaults to 432000 seconds, which is 5 days.

closedlist (boolean)

Is the list is open or closed. If it's closed subscription and unsubscription via mail is disabled.

closedlistsub (boolean)

This works like closedlist, except it allows unsubscription by normal means.

customheaders (list)

These headers are added to every mail coming through. This is the place you want to add Reply-To:, List-Info:, etc headers in case you want such.

delheaders (list)

In this file is specified *ONE* headertoken to match per line. If the file
consists of:

Received:
Message-ID:

Then all occurences of these headers in incoming list mail will be deleted. "From " and "Return-Path:" are deleted no matter what.

delimiter (normal)

This specifies what to use as recipient delimiter for the list. Default is "+".

digestinterval (normal)

This file specifies how many seconds will pass before the next digest is sent. Defaults to 604800 seconds, which is 7 days.

digestmaxmails (normal)

This file specifies how many mails can accumulate before digest sending is triggered. Defaults to 50 mails, meaning that if 50 mails arrive to the list before digestinterval have passed, the digest is delivered.

listaddress (list)

This file contains all addresses which mlmmj sees as listaddresses (see tocc below). The first one is the one used as the primary one, when mlmmj sends out mail.

mlmmj - maling list management made joyful


The functionality

  1. Archive
  2. Custom headers / foote
  3. Fully automated bouncehandling (similar to ezmlm)
  4. Complete requeueing functionality
  5. Moderation functionality
  6. Subject prefix
  7. Subscribers only posting
  8. Regular expression access control
  9. Functionality to retrieve old posts
  10. Web-interface
  11. Digests
  12. No mail delivery subscription
  13. VERP support
  14. Delivery Status Notification (RFC1891) support

There's a mailing list, , for discussions of any kind with regards to mlmmj. Archive.
Feel free to join in by sending a mail to .

On to the project page

maxmailsize (normal)

With this option the maximal allowed size of incoming mails can be specified.

maxverprecips (normal)

How many recipients per mail delivered to the smtp server. Defaults to 100.

memorymailsize (normal)

Here is specified in bytes how big a mail can be and still be prepared for sending in memory. It's greatly reducing the amount of write system calls to prepare it in memory before sending it, but can also lead to denial of service attacks. Default is 16k (16384 bytes).

moderated (boolean)

If this file is present, the emailaddresses in the file listdir/control/moderators will act as moderators for the list.

modnonsubposts (boolean)

When this file is present and subonlypost is enabled, all postings from people who are not subscribed to the list will be moderated.

noaccessdenymails (boolean)

This switch turns off whether mlmmj sends out notification about postings being denied when it was rejected due to an access rule (see 'access').

noarchive (boolean)

If this file exists, the mail won't be saved in the archive but simply deleted.

nodigestsub (boolean)

If this file exists, subscription to the digest version of the mailinglist will be denied. (Useful if you don't want to allow digests and notify users about it).

nodigesttext (boolean)

If this file exists, digest mails won't have a text part with a thread summary.

noget (boolean)

If this file exists, then retrieving old posts with +get-N is disabled.

nomaxmailsizedenymails (boolean)

If this is set, no reject notifications caused by violation of maxmailsize will be sent.

nonomailsub (boolean)

If this file exists, subscription to the nomail version of the mailinglist will be denied. (Useful if you don't want to allow nomail and notify users about it).

nosubconfirm (boolean)

If this file exists, no mail confirmation is needed to subscribe to the list. This should in principle never ever be used, but there is times on local lists etc. where this is useful.
HANDLE WITH CARE!

nosubonlydenymails (boolean)

This switch turns off whether mlmmj sends out notification about postings being denied due to it's a subscribers only posting list (see 'subonlypost').

notifysub (boolean)

If this file is present, the owner(s) will get a mail with the address of someone sub/unsubscribing to a mailinglist.

notoccdenymails (boolean)

This switch turns off whether mlmmj sends out notification about postings being denied due to the listaddress not being in To: or Cc: (see 'tocc').

owner (list)

The emailaddresses in this file (1 per line) will get mails to listname+owner@listdomain.tld

prefix (normal)

The prefix for the Subject: line of mails to the list. This will alter the Subject: line, and add a prefix if it's not present elsewhere.

relayhost (normal)

The host specified (IP address or hostname, both works) in this file will be used for relaying the mail sent to the list. Defaults to 127.0.0.1.

smtpport (normal)

In this file a port other than port 25 for connecting to the relayhost can be specified.

submod (list)

If this file is present, subscription will be moderated by owner(s). If there are emailaddresses in this file, then these will be used instead of owner.

subonlyget (boolean)

If this file exists, then retrieving old posts with +get-N is only possible for subscribers. The tunable 'noget' has precedence.

subonlypost (boolean)

When this file is present, only people who are subscribed to the list, are allowed to post to it. The check is made against the "From:" header.

tocc (boolean)

If this file is present, the list address does not have to be in the To: or Cc: header of the email to the list.

verp (normal)

Enable VERP support. Anything added in this variable will be appended the MAIL FROM: line. If "postfix" is put in the file, it'll make postfix use VERP by adding XVERP=-= to the MAIL FROM: line.

Access rules

If the file listdir/control/access is present, access control is enabled.

NOTE: the default action is to deny access (reject the mail), so an empty access control file will cause mlmmj to reject all posts, whereas a non-existant file will change nothing, and mlmmj will behave as usual.

Each header in the mail is tested against each rule, rule by rule. That is, all headers are first tested against the first rule, then all headers are tested against the second rule, and so on.

The first rule to match a header decides which action to take - allow, deny or moderate the post.

The syntax is quite simple:

action[ [!]regexp]

IMPORTANT: if "moderate" is used then don't forget to add people who should function as moderators in listdir/control/moderators

First a simple example. This rule set will reject any mail that is NOT plain text, or has a subject that contains "BayStar", and allow anything else:

 deny !^Content-Type: text/plain
 deny ^Subject:.*BayStar
 allow

To allow only text mails, but have the moderators moderate every html mail one would use this:

 allow ^Content-Type: text/plain
 moderate ^Content-Type: text/html
 deny

Now on to a more advanced example. Morten can post anything, Mads Martin can post if the subject does not contain "SCO". Everything else is denied:

 allow ^From: Morten
 deny ^Subject:.*SCO
 allow ^From: Mads Martin
 deny

The last rule (deny) can be left out, as deny is the default action.

A third example. Deny any mails with "discount", "weightloss", or "bonus" in the subject. Allow PGP signed and plain text mails. Anything else is denied:

 deny ^Subject:.*discount
 deny ^Subject:.*weightloss
 deny ^Subject:.*bonus
 allow ^Content-Type: multipart/signed
 allow ^Content-Type: text/plain

Exim4 configuration

This is a step-by-step guide to run mlmmj with Exim4. The most current version
of this can be found on http://plonk.de/sw/mlmmj/README.exim4.

Notes:

  1. In the main configuration section:
    MLMMJ_HOME=/var/spool/mlmmj
    domainlist mlmmj_domains = list.example.net
    
  2. Add +mlmmj_domains to relay_to_domains:
    domainlist relay_to_domains = other.domain : +mlmmj_domains
    
  3. mlmmj is barely interested in delay warnings, so add this in the main
    configuration:

    delay_warning_condition = ${if match_domain{$domain}{+mlmmj_domains}{no}{yes}}
    
  4. In the routers section (before the dnslookup router, preferably at the
    beginning):

    mlmmj_router:
      driver = accept
      domains = +mlmmj_domains
      require_files = MLMMJ_HOME/${lc::$local_part}
      # Use this instead, if you don't want to give Exim rx rights to mlmmj spool.
      # Exim will then spawn a new process running under the UID of "mlmmj".
      #require_files = mlmmj:MLMMJ_HOME/${lc::$local_part}
      local_part_suffix = +*
      local_part_suffix_optional
      headers_remove = Delivered-To
      headers_add = Delivered-To: $local_part$local_part_suffix@$domain
      transport = mlmmj_transport
    

    If you want VERP to be done by your MTA, also add this:

    verp_router:
      driver = dnslookup
      domains = !+mlmmj_domains
      # we only consider messages sent in through loopback
      condition = ${if eq{$sender_host_address}{127.0.0.1}{yes}{no}}
      ignore_target_hosts = <; 0.0.0.0; 127.0.0.0/8; ::1/128; fe80::/10; ff00::/8
      # only the un-VERPed bounce addresses are handled
      senders = \N^.+\+bounces-\d+@.+\N
      transport = verp_smtp
    

    To prevent temporary errors for not-existing lists, add !+mlmmj_domains to the
    domains condition of the dnslookup router:

    dnslookup:
      driver = dnslookup
      domains = !+mlmmj_domains : !+local_domains
    [...]
    
  5. Somewhere in the transports section. (Change the path of mlmmj-recieve if you
    don't use the default location!):

    mlmmj_transport:
      driver = pipe
      return_path_add
      user = mlmmj
      group = mlmmj
      home_directory = MLMMJ_HOME
      current_directory = MLMMJ_HOME
      command = /usr/local/bin/mlmmj-recieve -F -L MLMMJ_HOME/${lc:$local_part}
    

    If you want VERP to be done by your MTA, also add this:

    verp_smtp:
      driver = smtp
      # put recipient address into return_path
      return_path = ${quote_local_part:${local_part:$return_path}}-\
                    ${original_local_part}=${original_domain}@\
                    ${domain:$return_path}
      # must restrict to one recipient at a time
      max_rcpt = 1
      # Errors-To: may carry old return_path
      headers_remove = Errors-To
      headers_add = Errors-To: $return_path
    
  6. Test your setup with
    $ exim -bt mlmmj-test@your.list.domain
    mlmmj-test@your.list.domain
      router = mlmmj_router, transport = mlmmj_transport
    

    If you get different output, run it with -d to see what's going wrong.
    If not, you're done!

    Jakob Hirsch (jh at plonk dot de)

qmail configuration

Using mlmmj with qmail (and vpopmail)
by Fabio Busatto

This mini-HOWTO is a step-by-step guide for using mlmmj with qmail MTA
(http://www.qmail.org/), and it has been successfully tested also with vpopmail
virtual domains (http://www.inter7.com/vpopmail/).

Prerequisites:

Conventions:

Configuration:

WARNING: REMEMBER that the delimiter is -, so do not use + when composing mail
addresses for extensions!!!

WARNING: DO NOT USE 'preline' command in dot-qmail files, it will result in
mlmmj to not work properly!!!

Example:
Configuring mlmmj to handle ml@programmazione.it mailing list using qmail as MTA and vpopmail for virtual domain support:

# mlmmj-make-ml.sh -c vpopmail:vchkpw -L ml
Creating Directorys below /var/spool/mlmmj. Use '-s spooldir' to change
The Domain for the List? [] : programmazione.it
The emailaddress of the list owner? [postmaster] : postmaster@programmazione.it
The path to texts for the list? [/usr/local/share/mlmmj/text.skel] :
chown -R vpopmail:vchkpw /var/spool/mlmmj/ml? [y/n]: y

# cd /var/spool/mlmmj/ml/control/
# echo '-' > delimiter
# chown vpopmail:vchkpw delimiter
# cd /home/vpopmail/domains/programmazione.it/
# echo -e "|/usr/local/bin/mlmmj-recieve -L /var/spool/mlmmj/ml/" > .qmail-ml
# cp -a .qmail-ml .qmail-ml-default
# cat *-default
# chown vpopmail:vchkpw .qmail-ml .qmail-ml-default
# chmod 600 .qmail-ml .qmail-ml-default

Sendmail configuration

The following configuration enables VERP (http://cr.yp.to/proto/verp.txt) which is useful for mailing list managers that are able to take advantage of that feature.

This configuration is currently used for using the mlmmj manager with VERP enabled + sendmail.

The hack consists in hooking VERP rewriting in a replacement ruleset for the existing EnvFromSMTP one (called VerpEnvFromSMTP). This is going to work *only* if we are splitting messages with multiple recipients in separate queue files since the macro we are using for the rewriting ($u) is not set when multiple rcpt are present.

The first step consists in forcing envelope splitting, this is done using the QUEUE_GROUP feature, here we are definining r=1 (max 1 rcpt per message) for the default queue group:

QUEUE_GROUP(`mqueue', `P=/var/spool/mqueue, F=f, I=1m,  R=2, r=1')

Since we are going to split a lot it's advisable to use the FAST_SPLIT option, additionally we need to enforce return-path inclusion in the local mailer:

define(`confFAST_SPLIT', `100')dnl
define(`LOCAL_SHELL_FLAGS', `eu9P')dnl

Then we define a regex map for matching the addresses that we are going to rewrite, in our example we'll rewrite addresses like

<listname+bounces-123@domain.net>

with

%lt;listname+bounces-123-user=foo.net@domain.net>

where user@foo.net is the recipient address of the message. So we need to apply
our verp ruleset *only* to those addresses. Additionally we are also adding the
Delivered-To header:

LOCAL_CONFIG
Kmatch_verp regex -m -a@VERP (listname\+bounces\-[0-9]+<@domain\.net\.?>)
H?l?Delivered-To: $u

Here's the ruleset, the first half of the ruleset is the existing EnvFromSMTP ruleset present in default sendmail.cf, the seconf half is the VERP stuff:

SVerpEnvFromSMTP
R$+                     $: $>PseudoToReal $1            sender/recipient common
R$* :; <@>              $@                              list:; special case
R$*                     $: $>MasqSMTP $1                qualify unqual'ed names
R$+                     $: $>MasqEnv $1                 do masquerading

R $*                                    $: $(match_verp $1 $)                            match the address
R $* + $* < @ $* . > $* @VERP           $: $1 + $2 - $&u < @ $3 . > $4 VERP              rewrite it using $u macro and add VERP string for failsafe
R $* - < @ $* . > $* VERP               $: $1 < @ $2 . > $3                              if $u wasn't defined rewrite the address back
R $* - < $+ @ $+ > < @ $* . > $* VERP   $: $(dequote $1 "-" $2 "=" $3 $) < @ $4 . > $5   replace the "@" in rcpt address with "="
R $* - $+ @ $+ < @ $* . > $* VERP       $: $(dequote $1 "-" $2 "=" $3 $) < @ $4 . > $5   replace the "@" in rcpt address with "="

Finally we need to rewrite the mailer definition for the used mailer (typically esmtp) specifying VerpEnvFromSMTP as the sender rewrite ruleset:

MAILER_DEFINITIONS
Mesmtp,         P=[IPC], F=mDFMuXa, S=VerpEnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990,
                T=DNS/RFC822/SMTP,
                A=TCP $h

NOTE: for mailing list servers it's also a good idea keeping existing Delivered-To headers, sendmail needs the following patch for doing this