Florian Wagner has proposed merging lp:~wagnerflo/mailman/2.1-postfix-transport 
into lp:mailman/2.1.

Requested reviews:
    Mailman Coders (mailman-coders)

This branch extends the Postfix handling in Mailman to generate additional maps 
for a different handling of virtual hosts then the one already included:

- virtual-transport is a transport map (as in 
http://www.postfix.org/transport.5.html) for use with the transport_maps 
configuration parameter. It can be used to overwrite the transport Postfix uses 
to deliver mail intended for a Mailman mailinglist. All list addresses known to 
the Postfix installation are included as keys. The value is set to the contents 
of a new POSTFIX_VIRTUAL_TRANSPORT configuration parameter ("mailman" by 
default).

- virtual-id is a virtual alias map (as in 
http://www.postfix.org/virtual.5.html) for use with the virtual_alias_maps 
parameter. It is a identity mapping for all list addresses known to the Mailman 
installation. It can be used to make these addresses known to Postfix (for 
mails not to be rejected by reject_unauth_destination in 
smtpd_recipient_restrictions for example).

An implementation of the transport that passes mail to Mailman is also included 
as contrib/postfix-transport.py. It is a cleaned-up version of 
postfix-to-mailman.py from the Debian Mailman package and available on the net.

The setup has been running for a low volume mailinglist for a few weeks.
-- 
https://code.launchpad.net/~wagnerflo/mailman/2.1-postfix-transport/+merge/7901
Your team Mailman Checkins is subscribed to branch lp:mailman/2.1.
=== modified file 'Mailman/Defaults.py.in'
--- Mailman/Defaults.py.in	2008-12-23 01:24:44 +0000
+++ Mailman/Defaults.py.in	2009-06-05 20:52:57 +0000
@@ -403,6 +403,11 @@
 POSTFIX_ALIAS_CMD = '/usr/sbin/postalias'
 POSTFIX_MAP_CMD = '/usr/sbin/postmap'
 
+# Tells genaliases what to put into the generated virtual-transport
+# table. This is supposed to be one of the delivery transports defined
+# in the postfix master.cf.
+POSTFIX_VIRTUAL_TRANSPORT = 'mailman'
+
 # Ceiling on the number of recipients that can be specified in a single SMTP
 # transaction.  Set to 0 to submit the entire recipient list in one
 # transaction.  Only used with the SMTPDirect DELIVERY_MODULE.

=== modified file 'Mailman/MTA/Postfix.py'
--- Mailman/MTA/Postfix.py	2008-08-22 22:21:26 +0000
+++ Mailman/MTA/Postfix.py	2009-06-05 21:06:16 +0000
@@ -34,6 +34,8 @@
 LOCKFILE = os.path.join(mm_cfg.LOCK_DIR, 'creator')
 ALIASFILE = os.path.join(mm_cfg.DATA_DIR, 'aliases')
 VIRTFILE = os.path.join(mm_cfg.DATA_DIR, 'virtual-mailman')
+VIRTTRFILE = os.path.join(mm_cfg.DATA_DIR, 'virtual-transport')
+VIRTIDFILE = os.path.join(mm_cfg.DATA_DIR, 'virtual-id')
 
 try:
     True, False
@@ -51,13 +53,14 @@
         errstr = os.strerror(status)
         syslog('error', msg, acmd, status, errstr)
         raise RuntimeError, msg % (acmd, status, errstr)
-    if os.path.exists(VIRTFILE):
-        vcmd = mm_cfg.POSTFIX_MAP_CMD + ' ' + VIRTFILE
-        status = (os.system(vcmd) >> 8) & 0xff
-        if status:
-            errstr = os.strerror(status)
-            syslog('error', msg, vcmd, status, errstr)
-            raise RuntimeError, msg % (vcmd, status, errstr)
+    for mapfile in VIRTFILE, VIRTTRFILE, VIRTIDFILE:
+        if os.path.exists(mapfile):
+            vcmd = mm_cfg.POSTFIX_MAP_CMD + ' ' + mapfile
+            status = (os.system(vcmd) >> 8) & 0xff
+            if status:
+                errstr = os.strerror(status)
+                syslog('error', msg, vcmd, status, errstr)
+                raise RuntimeError, msg % (vcmd, status, errstr)
 
 
 
@@ -76,6 +79,8 @@
 def clear():
     _zapfile(ALIASFILE)
     _zapfile(VIRTFILE)
+    _zapfile(VIRTTRFILE)
+    _zapfile(VIRTIDFILE)
 
 
 
@@ -116,20 +121,16 @@
 
 
 
-def _addvirtual(mlist, fp):
+def _addmap(mlist, fp, loopfunc, itemfunc):
     listname = mlist.internal_name()
     fieldsz = len(listname) + len('-unsubscribe')
-    hostname = mlist.host_name
-    # Set up the mailman-loop address
-    loopaddr = Utils.get_site_email(mlist.host_name, extra='loop')
-    loopdest = Utils.ParseEmail(loopaddr)[0]
     # Seek to the end of the text file, but if it's empty write the standard
     # disclaimer, and the loop catch address.
     fp.seek(0, 2)
     if not fp.tell():
         print >> fp, """\
 # This file is generated by Mailman, and is kept in sync with the binary hash
-# file virtual-mailman.db.  YOU SHOULD NOT MANUALLY EDIT THIS FILE unless you
+# file <name-of-file>.db.  YOU SHOULD NOT MANUALLY EDIT THIS FILE unless you
 # know what you're doing, and can keep the two files properly in sync.  If you
 # screw it up, you're on your own.
 #
@@ -139,25 +140,73 @@
 # LOOP ADDRESSES START
 %s\t%s
 # LOOP ADDRESSES END
-""" % (loopaddr, loopdest)
+""" % loopfunc(mlist)
     # The text file entries get a little extra info
     print >> fp, '# STANZA START:', listname
     print >> fp, '# CREATED:', time.ctime(time.time())
     # Now add all the standard alias entries
     for k, v in makealiases(listname):
-        fqdnaddr = '%...@%s' % (k, hostname)
+        first,second = itemfunc(mlist, k, v)
         # Format the text file nicely
-        print >> fp, fqdnaddr, ((fieldsz - len(k)) * ' '), k
+        print >> fp, first, ((fieldsz - len(k)) * ' '), second
     # Finish the text file stanza
     print >> fp, '# STANZA END:', listname
     print >> fp
 
+
+def _addvirtual_loop(mlist):
+    # Set up the mailman-loop address
+    loopaddr = Utils.get_site_email(mlist.host_name, extra='loop')
+    loopdest = Utils.ParseEmail(loopaddr)[0]
+    return (loopaddr, loopdest)
+
+
+def _addvirtual_item(mlist, k, v):
+    return ('%...@%s' % (k, mlist.host_name), k)
+
+
+def _addvirtual(mlist, fp):
+    return _addmap(mlist, fp, _addvirtual_loop, _addvirtual_item)
+
+
+def _addvirtualtransport_loop(mlist):
+    # Set up the mailman-loop address
+    loopaddr = Utils.get_site_email(mlist.host_name, extra='loop')
+    return (loopaddr, mm_cfg.POSTFIX_VIRTUAL_TRANSPORT)
+
+
+def _addvirtualtransport_item(mlist, k, v):
+    return ('%...@%s' % (k, mlist.host_name),
+            mm_cfg.POSTFIX_VIRTUAL_TRANSPORT)
+
+
+def _addvirtualtransport(mlist, fp):
+    return _addmap(mlist, fp,
+                   _addvirtualtransport_loop,
+                   _addvirtualtransport_item)
+
+
+def _addvirtualid_loop(mlist):
+    # Set up the mailman-loop address
+    loopaddr = Utils.get_site_email(mlist.host_name, extra='loop')
+    print loopaddr
+    return (loopaddr, loopaddr)
+
+
+def _addvirtualid_item(mlist, k, v):
+    fqaddr = '%...@%s' % (k, mlist.host_name)
+    return (fqaddr, fqaddr)
+
+
+def _addvirtualid(mlist, fp):
+    return _addmap(mlist, fp,
+                   _addvirtualid_loop,
+                   _addvirtualid_item)
 
 
 # Blech.
-def _check_for_virtual_loopaddr(mlist, filename):
-    loopaddr = Utils.get_site_email(mlist.host_name, extra='loop')
-    loopdest = Utils.ParseEmail(loopaddr)[0]
+def _check_for_virtual_loop(mlist, filename, loopfunc):
+    loopaddr,loopdest = loopfunc(mlist)
     infp = open(filename)
     omask = os.umask(007)
     try:
@@ -196,6 +245,17 @@
         outfp.close()
     os.rename(filename + '.tmp', filename)
 
+
+def _check_for_virtual_loopaddr(mlist, filename):
+    _check_for_virtual_loop(mlist, filename, _addvirtual_loop)
+
+
+def _check_for_virtualtransport_loopaddr(mlist, filename):
+    _check_for_virtual_loop(mlist, filename, _addvirtualtransport_loop)
+
+
+def _check_for_virtualid_loopaddr(mlist, filename):
+    _check_for_virtual_loop(mlist, filename, _addvirtualid_loop)
 
 
 def _do_create(mlist, textfile, func):
@@ -216,6 +276,10 @@
     # Now double check the virtual plain text file
     if func is _addvirtual:
         _check_for_virtual_loopaddr(mlist, textfile)
+    elif func is _addvirtualtransport:
+        _check_for_virtualtransport_loopaddr(mlist, textfile)
+    elif func is _addvirtualid:
+        _check_for_virtualid_loopaddr(mlist, textfile)
 
 
 def create(mlist, cgi=False, nolock=False, quiet=False):
@@ -229,6 +293,8 @@
         _do_create(mlist, ALIASFILE, _addlist)
         if mlist and mlist.host_name in mm_cfg.POSTFIX_STYLE_VIRTUAL_DOMAINS:
             _do_create(mlist, VIRTFILE, _addvirtual)
+            _do_create(mlist, VIRTTRFILE, _addvirtualtransport)
+            _do_create(mlist, VIRTIDFILE, _addvirtualid)
         _update_maps()
     finally:
         if lock:
@@ -297,6 +363,8 @@
         _do_remove(mlist, ALIASFILE, False)
         if mlist.host_name in mm_cfg.POSTFIX_STYLE_VIRTUAL_DOMAINS:
             _do_remove(mlist, VIRTFILE, True)
+            _do_remove(mlist, VIRTTRFILE, True)
+            _do_remove(mlist, VIRTIDFILE, True)
         # Regenerate the alias and map files
         _update_maps()
     finally:
@@ -306,7 +374,7 @@
 
 def checkperms(state):
     targetmode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP
-    for file in ALIASFILE, VIRTFILE:
+    for file in ALIASFILE, VIRTFILE, VIRTTRFILE, VIRTIDFILE:
         if state.VERBOSE:
             print _('checking permissions on %(file)s')
         stat = None

=== added file 'contrib/postfix-transport.py'
--- contrib/postfix-transport.py	1970-01-01 00:00:00 +0000
+++ contrib/postfix-transport.py	2009-06-10 12:42:31 +0000
@@ -0,0 +1,101 @@
+#! @PYTHON@
+
+# postfix-transport.py
+#
+# Interface mailman to a postfix with a mailman transport.
+#
+# based on postfix-to-mailman.py from Debian package by
+#   Dax Kelson <[email protected]>,
+#   Simen E. Sandberg <[email protected]>,
+#   Henrique de Moraes Holschuh <[email protected]> and
+#   Siggy Brentrup <[email protected]>
+#
+# and on qmail-to-mailman.py by
+#   Bruce Perens <[email protected]>
+#
+# by
+#   Florian Wagner <[email protected]>
+#
+#
+# This is free software under the GNU General Public License.
+#
+# This scripts implements a postfix transport intended to be used by
+# the postfix pipe delivery system. It expects a single commandline
+# parameter being the mailinglist name and suffix (listname,
+# listname-admin, listname-bounces, ...) and the mail to be passed
+# in on stdin.
+#
+# It requires postfix to be configured with a custom transport map
+# for mailing list destination addresses.
+#
+
+import os
+import sys
+
+# Exit codes accepted by postfix
+#  from postfix-2.0.16/src/global/sys_exits.h
+#
+EX_USAGE    = 64    # command line usage error 
+EX_NOUSER   = 67    # addressee unknown
+EX_SOFTWARE = 70    # internal software error
+
+
+def main():
+    # handle mailing lists at non-interactive priority
+    os.nice(5)
+
+    import re
+    import os.path as path
+    
+    sys.path.append(path.join('@prefix@', 'bin'))
+    
+    import paths
+    import Mailman.Utils
+    import Mailman.mm_cfg
+
+    if len(sys.argv) != 2:
+        sys.stderr.write('Illegal invocation: %s\n' % ' '.join(sys.argv))
+        sys.stderr.write('Did you forget to set '
+                         'mailman_destination_recipient_limit=1 '
+                         'in main.cf?\n')
+        return EX_USAGE
+
+    local = sys.argv[1].lower()
+    mlist = local
+    func = 'post'
+    
+    for action in ('admin', 'bounces', 'confirm', 'join', 'leave', 'owner',
+                   'request', 'subscribe', 'unsubscribe', 'loop'):
+        if not local.endswith('-' + action):
+            continue
+
+        func = action
+        mlist = local[:-len(action)-1]
+        break
+
+    if func == 'loop':
+        cmd = Mailman.mm_cfg.SENDMAIL_CMD
+        os.execv(cmd, (cmd, 'postmaster'))
+        errno = os.errno
+        
+    elif Mailman.Utils.list_exists(mlist):
+        cmd = path.join(paths.prefix, 'mail', 'mailman')
+        os.execv(cmd, (cmd, func, mlist))
+        errno = os.errno
+
+    else:
+        sys.stderr.write('Mail to invalid mailing list \'%s\'.\n' % mlist)
+        return EX_NOUSER
+    
+    sys.stderr.write('execv error: %s.\n' % os.strerror(errno))
+    return EX_SOFTWARE
+
+
+if __name__ == '__main__':
+    try:
+        os._exit(main())
+    
+    except:
+        import traceback
+        sys.stderr.write(traceback.format_exc())
+        os._exit(EX_SOFTWARE)

_______________________________________________
Mailman-checkins mailing list
[email protected]
Unsubscribe: 
http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org

Reply via email to