Here's a slightly better version of auto, which works with cross-posting. The key insight was that Postfix calls auto once for each mailing list recipient, with the Delivered-To: header set to the mailing list address. So this version sucks out the Delivered-To:'s and parses the necessary information out of there. Turns out the recipient_delimiter is necessary in order to get the name of the mailing list in the Delivered-To: header (with the `mm' prefix, which is stripped off). Because of this, each sha hash will be unique so they shouldn't step on each other's toes.
The (potential) performance issue isn't addressed here, nor is the bogus address bounce notifications. The former will need a little bit of extra help from other parts of Mailman, and the latter may take some changes in Postfix. But IMO, it's not a bad hack!
Enjoy, -Barry
-------------------- snip snip -------------------- #! /usr/bin/env python # # Copyright (C) 1998,1999,2000 by the Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import sys
import paths from Mailman import mm_cfg from Mailman import Utils from Mailman import MailList from Mailman import Message from Mailman.Logging.Utils import LogStdErr from Mailman.Logging.Syslog import syslog
# Error code if it's really not a Mailman list addr destination EX_NOUSER = 67
LogStdErr('auto', 'auto')
def fqdn_listname(listname, hostname): return ('%s@%s' % (listname, hostname)).lower()
def main(): syslog('auto', 'Running the auto deliver script')
# valid destinations
valids = {}
lists = {}
for listname in Utils.list_names():
mlist = MailList.MailList(listname, lock=0)
lists[listname] = mlist
valids[fqdn_listname(listname, mlist.host_name)] = 1
# Get the message from standard input
msg = Message.Message(sys.stdin)
addrs = [addr for name, addr in msg.getaddrlist('delivered-to')]
syslog('auto', 'found these addresses: %s' % addrs)
# Parse the headers. Keys are 'post', 'request', 'owner'
destinations = {}
for addr in addrs:
localpart, hostname = addr.split('@', 1)
try:
listname, subdest = localpart.split('-', 1)
except ValueError:
listname = localpart
subdest = 'post'
try:
prefix, listname = listname.split('+')
except ValueError:
prefix = None
if subdest in ('post', 'request', 'owner', 'admin') and \
valids.has_key(fqdn_listname(listname, hostname)) and \
prefix == 'mm':
destinations.setdefault(subdest, []).append(listname)
if not destinations:
# Tell Postfix we found no valid list destinations
syslog('auto', 'No Mailman destination found')
return EX_NOUSER
syslog('auto', 'destinations: %s' % destinations)
# TBD: This may not work for cross-posted messages
for subdest, listnames in destinations.items():
for listname in listnames:
syslog('auto', 'Enqueuing to %s-%s' % (listname, subdest))
mlist = lists[listname]
if subdest == 'post':
msg.Enqueue(mlist, tolist=1)
elif subdest == 'request':
msg.Enqueue(mlist, torequest=1)
elif subdest in ('owner', 'admin'):
msg.Enqueue(mlist, toadmin=1)
# success
return 0
if __name__ == '__main__': code = main() sys.exit(code)