# HG changeset patch # User mortenp # Date 1261376578 -39600 # Node ID 52189a450b0c674ec2fbca1cada5857e0783d378 # Parent 79dd917e0150d5487520d95c6d4063d303372bc0 Added README.postfix (Jeremy Hinegardner, Andreas Schneider) diff -r 79dd917e0150 -r 52189a450b0c ChangeLog --- a/ChangeLog Mon Jul 27 21:55:27 2009 +1000 +++ b/ChangeLog Mon Dec 21 17:22:58 2009 +1100 @@ -1,3 +1,4 @@ + o Added README.postfix (Jeremy Hinegardner, Andreas Schneider) o Added support for digest and nomail to +list (Christoph Wilke) o Caseinsensitive string compare for owner addr when +list is invoked. Spotted by Pavel Kolar. diff -r 79dd917e0150 -r 52189a450b0c README.postfix --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README.postfix Mon Dec 21 17:22:58 2009 +1100 @@ -0,0 +1,124 @@ +README.postfix Dec 16th 2009 + +POSTFIX ISSUES + + The main issue with Postfix and mlmmj is the mlmmj requirement that + the mlmmj executables must be executed by root or the owner of the + list directory. + + This is at odds with Postfix. The standard local delivery mechanism + for Postfix is local(8) that ships with Postfix. According to + local(8) delivery to external programs is done on behalf of the + receiving user. But when delivering to a program without using a + .forward file there is no user context. And using an alias file + does not provide user context. + + The man page also explains that in the absence of user context the + local(8) daemon will use the owner of the :include: file from the + aliases file. But this is a problem too. By default :include: + files are disabled as a security precaution in aliases files for + delivering to external programs. + + This leaves us with a conundrum on how to execute the mlmmj + executables as an 'mlmmj' user without using alias files. One + answer is to use a postfix transport. + + First we'll get the 'mlmmj' user setup and then move onto the + postfix configuration: + +MLMMJ SETUP + + Create a 'mlmmj' user that will own all the lists. Use whatever + user creation app/script is provided by your system. Generally + 'useradd'. + + Create the spool directory that is owned by the 'mlmmj' user. + This is typically /var/spool/mlmmj but can be any directory so long + as it is owned by 'mlmmj'. It can even be the home directory of the + 'mlmmj' user. If the spool directory is not /var/spool/mlmmj then + everywhere in this file replace /var/spool/mlmmj with your spool + directory. + + Create a mailing list using mlmmj-make-ml.sh. Make sure to use the + -s flag to set the spool directory if it isn't /var/spool/mlmmj + +POSTFIX SETUP + + First thing is to make sure that the postfix server accepts mail for + the mailing lists. For a server that handles mail for multiple + domains, this is done with a 'virtual_alias_map'. This is how I'll + demonstrate. + + Add a virtual_alias_map file to main.cf configuration. We'll use a + regular expression map since we need to be able to match all the + various mjmml delimiter addresses (list-subscribe, list-unsubscribe, + etc) + + main.cf: + virtual_alias_maps = hash:/etc/postfix/virtual, + regexp:/var/spool/mlmmj/virtual.regexp + + /var/spool/mlmmj/virtual.regexp: + /^(mlmmj-test.*)@example\.com$/ ${1} + /^(another-list.*)@sample\.com$/ ${1} + + + One line needs to be in the virtual map for each list the 'mlmmj' id + is to handle. The regex formula is: + + /^(list-name.*)@(domain\.com)$/ ${1} + + + Next we make sure that postfix can invoke the mlmmj executables as + the 'mlmmj' user. This is where the transport map comes in. So we + add a transport map and a configuration option that instructs the + transport to only deliver one file at a time. See transport(5) for + more information on transports. + + main.cf: + transport_maps = regexp:/var/spool/mlmmj/transport + mlmmj_destination_recipient_limit = 1 + + /var/spool/mlmmj/transport: + /^(list-test).*$/ mlmmj:list-test + /^(another-list).*$/ mlmmj:another-list + + What this transport file says, is that any message destined for an + email address that matches the regexp on the left, deliver it using + the transport 'mlmmj' and setting 'nexthop' to the value in $1. + Which in this case is the mailing list name. 'nexthop' is special + variable for transports. + + Now we setup the 'mlmmj' transport. The 'mlmmj' in mlmmj:$1 above + indicates a transport listed in the postfix master.cf file. We are + just going to create a transport called 'mlmmj' but it is nothing + more than a pipe(8) to the mlmmj-recieve program that is invoked as + the 'mlmmj' user. + + master.cf: + # mlmmj mailing lists + mlmmj unix - n n - - pipe + flags=DORhu user=mlmmj argv=/usr/local/bin/mlmmj-recieve -F -L /var/spool/mlmmj/$nexthop/ + + This takes the pipe(8) postfix delivery agent and tells it to invoke + '/usr/local/bin/mlmmj-recieve' as the 'mlmmj' user and pipe the + email to it on stdin. This mode of transportation is given the name + 'mlmmj'. + + The 'flags' parameter to pipe(8) is pretty critical here. In + particular if the 'R' option is not used mlmmj-recieve fails to + recieve the mail correctly. The options mean: + + D - Prepend a 'Delivered-To: recipient' header + O - Prepend an 'X-Original-To: recipient' header + R - Prepend a 'Return-Path:'. header + h - fold $nexthop to lowercase + u - fold $recipient to lowercase + + $nexthop gets set to what was on the right had side of the ':' in + the transport file. The way we have that configured is that + $nexthop will get set to the name of the mailing list. + + Restart postfix and enjoy your new lists. + +