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:

  • We assume that you have a user and group called mlmmj to use with mlmmj
  • The exim user needs rx access rights to mlmmj's spool directory. (If you don't want that, see below.) The easiest way is "chmod 755 /path/to/mlmmj/spool", if it's ok that local users can see which lists there are. Note that the owner of the mlmmj spool must still be the mlmmj user (and this user must have at least x rights to the directories below).
  • Existence of mailing lists is automatically checked ($listdir) and you don't need to put anything into your aliases file
  • If you want VERP to be done by your MTA, follow the instructions below and put an empty file named verp into the control directory of your lists
  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)