view README.postfix @ 844:58d726e86650

New and improved documentation on Postfix integration.
author Ben Schmidt
date Mon, 30 Jan 2012 01:49:26 +1100
parents ddae562f7cf0
children 87599e449135
line wrap: on
line source

README.postfix                                                   Jan 28th 2012

The main challenge to setting up Mlmmj with Postfix is that Mlmmj must be
executed by root or the owner of the list directory, but by default Postfix
will execute Mlmmj as 'nobody'[1].

There are a number of possible ways around this:

- Using .forward files (impractical) [2]
- Using :include: files (possibly insecure) [3]
- Making 'nobody' own your lists (insecure) [4]
- Changing the Postfix default (possibly insecure or impractical) [5]
- Using a Postfix transport (recommended)

As you can see, the last option is recommended. Here is how to set it up using
Postfix virtual domains (so you can host multiple domains on the same server).
(It can also be done with regular non-virtual aliases[6].)

 1) Add an 'mlmmj' user to your system (e.g. using 'useradd'). It usually
    makes sense to make this a 'system' user, with no password and no shell
    (/usr/false for the shell), and for its home directory to be
    /var/spool/mlmmj (or wherever you want to put your Mlmmj spool directory).

 2) Create your Mlmmj spool directory (we'll assume it's /var/spool/mlmmj)
    and change its owner to the 'mlmmj' user.

 3) Add an 'mlmmj' transport which uses the pipe(8) delivery agent to execute
    mlmmj-receive as the mlmmj user by adding something like the following to
    master.cf (often in /etc/postfix)[7]:

        # mlmmj mailing lists
        mlmmj   unix  -       n       n       -       -       pipe
            flags=ORhu user=mlmmj argv=/usr/local/bin/mlmmj-receive -F -L /var/spool/mlmmj/$nexthop

    Note that $nexthop is used to specify the list directory. We will return
    to that later.

 4) Integrate some necessary options in main.cf (also often in /etc/postfix):

        # Only deliver one message to Mlmmj at a time
        mlmmj_destination_recipient_limit = 1

        # Consider the part after '+' but before '@' to be an address extension
        # i.e. addresses have the form user+extension@domain.tld
        recipient_delimiter = +

        # A map to forward mail to a dummy domain
        virtual_alias_maps = hash:/var/spool/mlmmj/virtual

	# Allow virtual alias maps to specify only the user part of the address
	# and have the +extension part preserved when forwarding, so that
	# list-name+subscribe, list-name+confsub012345678, etc. will all work
        propagate_unmatched_extensions = virtual

        # A map to forward mail for the dummy domain to the Mlmmj transport
        transport_maps = hash:/var/spool/mlmmj/transport

    Of course, you may need to merge these options with existing ones (e.g.
    you probably have existing virtual_alias_maps if you run a multi-domain
    server).

    It is probably unnecessary to change propagate_unmatched_extensions because
    it defaults to something including 'virtual'. You can check this with
    something like 'postconf | grep propagate'.

 5) (For each list) Create a mailing list (e.g. by using mlmmj-make-ml). The
    list directory should be like /var/spool/mlmmj/list-dir for a flat
    structure, or /var/spool/mlmmj/domain.tld/list-name for a hierarchical
    structure (the -s option to mlmmj-make-ml may be useful to get the list
    created where you want it). Ensure the list directory and everything in it
    is owned by the mlmmj user (except you may want control files to be owned
    by your www server user in order to use web configuration interfaces; they
    must be readable by the mlmmj user though).

 6) (For each list) Add entries to the Postfix tables to accept mail for the
    list and forward it to the Mlmmj transport:

    /var/spool/mlmmj/virtual:
        list-name@domain.tld    domain.tld--list-name@localhost.mlmmj

    /var/spool/mlmmj/transport:
        # for a flat structure
        domain.tld--list-name@localhost.mlmmj   mlmmj:list-dir
        # for a hierarchical structure
        domain.tld--list-name@localhost.mlmmj   mlmmj:domain.tld/list-name

    Note that we have used a dummy domain 'localhost.mlmmj' to connect the
    virtual alias with the Mlmmj transport. This could be anything as long as
    it isn't a real domain. The user part of the address could also be
    anything; as long as the address matches in both tables it should work.

    Also note that the text after 'mlmmj:' becomes $nexthop which was mentioned
    earlier, so it is used to specify the list directory when executing
    mlmmj-receive.

 7) Refresh your postfix tables and reload your configuration so it takes
    effect.

        postmap /var/spool/mlmmj/virtual
        postmap /var/spool/mlmmj/transport
        postfix reload

    Enjoy your new lists!



[1] Actually, the standard local(8) delivery agent will execute external
    programs (such as Mlmmj) as the 'receiving user'. However, unless you
    direct your mail to Mlmmj using a .forward file (see local(8)) or an
    :include: file (see aliases(5)), there is no 'receiving user'. Without a
    'receiving user', Postfix uses the user from the configuration option
    'default_privs', which defaults to 'nobody'.

[2] Using .forward files is not practical, as it requires a user to be created
    for every mailing list.

[3] Using :include: files would require delivery to commands to be enabled in
    :include: files, which is not recommended for security reasons.

[4] Other programs and daemons rely on 'nobody' not owning any files or having
    access to anything; they use 'nobody' as a way of denying access and
    keeping all your files and system secure. Most notably, some NFS
    implementations use 'nobody' when somebody connects but fails to
    authenticate. Your mailing lists should not be accessible in such
    situations, but they may be if they are owned by 'nobody'.

[5] Changing 'default_privs' to an 'mlmmj' user may open other security holes,
    and may not be appropriate if Postfix is used for other external programs
    besides Mlmmj.

[6] To do this, at step 4, you'll need to incorporate:
 
        alias_maps = hash:/var/spool/mlmmj/aliases
        propagate_unmatched_extensions = alias

    You probably will need to adjust propagate_unmatched_extensions in this
    case, probably by adding 'alias' to the existing value rather than using
    'alias' alone.

    At step 6, entries in /var/spool/mlmmj/aliases should look something like:

        list-name:    list-name@localhost.mlmmj

    And of course you can omit the virtual stuff if you're not using it.

    Note that this has not been tested, but we believe it should work.

[7] The flags are pretty critical here. In particular if the 'R' option is not
    used mlmmj-receive fails to receive the mail correctly. The options mean:

        D - Prepend a 'Delivered-To: recipient' header (not used)
        O - Prepend an 'X-Original-To: recipient' header
        R - Prepend a 'Return-Path:'. header
        h - fold $nexthop to lowercase
        u - fold $recipient to lowercase