summaryrefslogtreecommitdiff
path: root/src/mailman/mta/postfix.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/mta/postfix.py')
-rw-r--r--src/mailman/mta/postfix.py53
1 files changed, 24 insertions, 29 deletions
diff --git a/src/mailman/mta/postfix.py b/src/mailman/mta/postfix.py
index 81a2a7945..a4fe0f331 100644
--- a/src/mailman/mta/postfix.py
+++ b/src/mailman/mta/postfix.py
@@ -30,30 +30,28 @@ import logging
import datetime
from flufl.lock import Lock
+from operator import attrgetter
from zope.component import getUtility
from zope.interface import implements
from mailman.config import config
from mailman.interfaces.listmanager import IListManager
-from mailman.interfaces.mta import IMailTransportAgentAliases
+from mailman.interfaces.mta import (
+ IMailTransportAgentAliases, IMailTransportAgentLifecycle)
-log = logging.getLogger('mailman.error')
-LOCKFILE = os.path.join(config.LOCK_DIR, 'mta')
-SUBDESTINATIONS = (
- 'bounces', 'confirm', 'join', 'leave',
- 'owner', 'request', 'subscribe', 'unsubscribe',
- )
+log = logging.getLogger('mailman.error')
+ALIASTMPL = '{0:{2}}lmtp:[{1.mta.lmtp_host}]:{1.mta.lmtp_port}'
class LMTP:
"""Connect Mailman to Postfix via LMTP."""
- implements(IMailTransportAgentAliases)
+ implements(IMailTransportAgentLifecycle)
def create(self, mlist):
- """See `IMailTransportAgentAliases`."""
+ """See `IMailTransportAgentLifecycle`."""
# We can ignore the mlist argument because for LMTP delivery, we just
# generate the entire file every time.
self.regenerate()
@@ -61,13 +59,14 @@ class LMTP:
delete = create
def regenerate(self, output=None):
- """See `IMailTransportAgentAliases`.
+ """See `IMailTransportAgentLifecycle`.
The format for Postfix's LMTP transport map is defined here:
http://www.postfix.org/transport.5.html
"""
# Acquire a lock file to prevent other processes from racing us here.
- with Lock(LOCKFILE):
+ lock_file = os.path.join(config.LOCK_DIR, 'mta')
+ with Lock(lock_file):
# If output is a filename, open up a backing file and write the
# output there, then do the atomic rename dance. First though, if
# it's None, we use a calculated path.
@@ -104,9 +103,8 @@ class LMTP:
# Sort all existing mailing list names first by domain, then my local
# part. For postfix we need a dummy entry for the domain.
by_domain = {}
- for mailing_list in getUtility(IListManager).mailing_lists:
- by_domain.setdefault(mailing_list.host_name, []).append(
- mailing_list.list_name)
+ for mlist in getUtility(IListManager).mailing_lists:
+ by_domain.setdefault(mlist.host_name, []).append(mlist)
print >> fp, """\
# AUTOMATICALLY GENERATED BY MAILMAN ON {0}
#
@@ -115,22 +113,19 @@ class LMTP:
# doing, and can keep the two files properly in sync. If you screw it up,
# you're on your own.
""".format(datetime.datetime.now().replace(microsecond=0))
+ sort_key = attrgetter('list_name')
for domain in sorted(by_domain):
print >> fp, """\
-# Aliases which are visible only in the @{0} domain.
-""".format(domain)
- for list_name in by_domain[domain]:
- # Calculate the field width of the longest alias. 10 ==
- # len('-subscribe') + '@'.
- longest = len(list_name + domain) + 10
- print >> fp, """\
-{0}@{1:{3}}lmtp:[{2.mta.lmtp_host}]:{2.mta.lmtp_port}""".format(
- list_name, domain, config,
+# Aliases which are visible only in the @{0} domain.""".format(domain)
+ for mlist in sorted(by_domain[domain], key=sort_key):
+ utility = getUtility(IMailTransportAgentAliases)
+ aliases = list(utility.aliases(mlist))
+ longest = max(len(alias) for alias in aliases)
+ print >> fp, ALIASTMPL.format(
+ aliases.pop(0), config,
# Add 1 because the bare list name has no dash.
- longest + 1)
- for destination in SUBDESTINATIONS:
- print >> fp, """\
-{0}-{1}@{2:{4}}lmtp:[{3.mta.lmtp_host}]:{3.mta.lmtp_port}""".format(
- list_name, destination, domain, config,
- longest - len(destination))
+ longest + 3)
+ for alias in aliases:
+ print >> fp, ALIASTMPL.format(
+ alias, config, longest + 3)
print >> fp