diff options
| author | Barry Warsaw | 2008-12-26 09:04:33 -0500 |
|---|---|---|
| committer | Barry Warsaw | 2008-12-26 09:04:33 -0500 |
| commit | 1ffa4c74935a56a3c5de736fab052e33e4ab3d38 (patch) | |
| tree | e44781f9de6e2ab284990000c08772664e999a5f | |
| parent | b8e68e7577aa12e0e355aabe2845981f0d73e3b5 (diff) | |
| download | mailman-1ffa4c74935a56a3c5de736fab052e33e4ab3d38.tar.gz mailman-1ffa4c74935a56a3c5de736fab052e33e4ab3d38.tar.zst mailman-1ffa4c74935a56a3c5de736fab052e33e4ab3d38.zip | |
| -rw-r--r-- | mailman/config/schema.cfg | 4 | ||||
| -rw-r--r-- | mailman/pipeline/docs/to-outgoing.txt | 19 | ||||
| -rw-r--r-- | mailman/pipeline/smtp_direct.py | 23 | ||||
| -rw-r--r-- | mailman/queue/bounce.py | 27 | ||||
| -rw-r--r-- | mailman/queue/docs/outgoing.txt | 5 | ||||
| -rw-r--r-- | mailman/queue/outgoing.py | 13 | ||||
| -rw-r--r-- | mailman/testing/helpers.py | 25 |
7 files changed, 64 insertions, 52 deletions
diff --git a/mailman/config/schema.cfg b/mailman/config/schema.cfg index 0a27c28f4..59ae160f4 100644 --- a/mailman/config/schema.cfg +++ b/mailman/config/schema.cfg @@ -25,14 +25,14 @@ # delivered to a human, but which can't be delivered to a list owner (e.g. a # bounce from a list owner), will be sent to this address. It should point to # a human. -site-owner: changeme@example.com +site_owner: changeme@example.com # This address is used as the from address whenever a message comes from some # entity to which there is no natural reply recipient. Set this to a real # human or to /dev/null. It will be appended with the host name of the list # involved. This address must not bounce and it must not point to a Mailman # process. -noreply-address: noreply +noreply_address: noreply # Where all the runtime data will be kept. This directory must exist. var_dir: /tmp/mailman diff --git a/mailman/pipeline/docs/to-outgoing.txt b/mailman/pipeline/docs/to-outgoing.txt index 046ed9be8..81e870e6c 100644 --- a/mailman/pipeline/docs/to-outgoing.txt +++ b/mailman/pipeline/docs/to-outgoing.txt @@ -65,8 +65,9 @@ option to VERP personalized deliveries is set, then the message will be VERP'd. # Save the original value for clean up. - >>> verp_personalized_delivieries = config.VERP_PERSONALIZED_DELIVERIES - >>> config.VERP_PERSONALIZED_DELIVERIES = True + >>> from mailman import Defaults + >>> verp_personalized_delivieries = Defaults.VERP_PERSONALIZED_DELIVERIES + >>> Defaults.VERP_PERSONALIZED_DELIVERIES = True >>> from mailman.interfaces import Personalization >>> mlist.personalize = Personalization.individual >>> msgdata = dict(foo=1, bar=2) @@ -79,7 +80,7 @@ VERP'd. However, if the global configuration variable prohibits VERP'ing, even personalized lists will not VERP. - >>> config.VERP_PERSONALIZED_DELIVERIES = False + >>> Defaults.VERP_PERSONALIZED_DELIVERIES = False >>> msgdata = dict(foo=1, bar=2) >>> handler.process(mlist, msg, msgdata) >>> print msgdata.get('verp') @@ -93,8 +94,8 @@ Mailman how often to VERP even non-personalized mailing lists. It can be set to zero, which means non-personalized messages will never be VERP'd. # Save the original value for clean up. - >>> verp_delivery_interval = config.VERP_DELIVERY_INTERVAL - >>> config.VERP_DELIVERY_INTERVAL = 0 + >>> verp_delivery_interval = Defaults.VERP_DELIVERY_INTERVAL + >>> Defaults.VERP_DELIVERY_INTERVAL = 0 >>> mlist.personalize = Personalization.none >>> msgdata = dict(foo=1, bar=2) >>> handler.process(mlist, msg, msgdata) @@ -105,7 +106,7 @@ to zero, which means non-personalized messages will never be VERP'd. If the interval is set to 1, then every message will be VERP'd. - >>> config.VERP_DELIVERY_INTERVAL = 1 + >>> Defaults.VERP_DELIVERY_INTERVAL = 1 >>> for i in range(10): ... msgdata = dict(foo=1, bar=2) ... handler.process(mlist, msg, msgdata) @@ -126,7 +127,7 @@ If the interval is set to 1, then every message will be VERP'd. If the interval is set to some other number, then one out of that many posts will be VERP'd. - >>> config.VERP_DELIVERY_INTERVAL = 3 + >>> Defaults.VERP_DELIVERY_INTERVAL = 3 >>> for i in range(10): ... mlist.post_id = i ... msgdata = dict(foo=1, bar=2) @@ -149,5 +150,5 @@ will be VERP'd. Clean up ======== - >>> config.VERP_PERSONALIZED_DELIVERIES = verp_personalized_delivieries - >>> config.VERP_DELIVERY_INTERVAL = verp_delivery_interval + >>> Defaults.VERP_PERSONALIZED_DELIVERIES = verp_personalized_delivieries + >>> Defaults.VERP_DELIVERY_INTERVAL = verp_delivery_interval diff --git a/mailman/pipeline/smtp_direct.py b/mailman/pipeline/smtp_direct.py index ab5ca0096..75c5da1ba 100644 --- a/mailman/pipeline/smtp_direct.py +++ b/mailman/pipeline/smtp_direct.py @@ -36,15 +36,16 @@ import copy import time import email import socket -import string import logging import smtplib from email.Charset import Charset from email.Header import Header from email.Utils import formataddr +from string import Template from zope.interface import implements +from mailman import Defaults from mailman import Utils from mailman.config import config from mailman.core import errors @@ -65,8 +66,11 @@ class Connection: def __connect(self): self.__conn = smtplib.SMTP() - self.__conn.connect(config.SMTPHOST, config.SMTPPORT) - self.__numsessions = config.SMTP_MAX_SESSIONS_PER_CONNECTION + host = config.mta.smtp_host + port = int(config.mta.smtp_port) + log.debug('Connecting to %s:%s', host, port) + self.__conn.connect(host, port) + self.__numsessions = Defaults.SMTP_MAX_SESSIONS_PER_CONNECTION def sendmail(self, envsender, recips, msgtext): if self.__conn is None: @@ -122,10 +126,10 @@ def process(mlist, msg, msgdata): chunks = [[recip] for recip in recips] msgdata['personalize'] = 1 deliveryfunc = verpdeliver - elif config.SMTP_MAX_RCPTS <= 0: + elif Defaults.SMTP_MAX_RCPTS <= 0: chunks = [recips] else: - chunks = chunkify(recips, config.SMTP_MAX_RCPTS) + chunks = chunkify(recips, Defaults.SMTP_MAX_RCPTS) # See if this is an unshunted message for which some were undelivered if msgdata.has_key('undelivered'): chunks = msgdata['undelivered'] @@ -316,7 +320,8 @@ def verpdeliver(mlist, msg, msgdata, envsender, failures, conn): 'mailbox': rmailbox, 'host' : DOT.join(rdomain), } - envsender = '%s@%s' % ((config.VERP_FORMAT % d), DOT.join(bdomain)) + envsender = '%s@%s' % ((Defaults.VERP_FORMAT % d), + DOT.join(bdomain)) if mlist.personalize == Personalization.full: # When fully personalizing, we want the To address to point to the # recipient, not to the mailing list @@ -378,10 +383,10 @@ def bulkdeliver(mlist, msg, msgdata, envsender, failures, conn): # Send the message refused = conn.sendmail(envsender, recips, msgtext) except smtplib.SMTPRecipientsRefused, e: - flog.error('%s recipients refused: %s', msgid, e) + log.error('%s recipients refused: %s', msgid, e) refused = e.recipients except smtplib.SMTPResponseException, e: - flog.error('%s SMTP session failure: %s, %s', + log.error('%s SMTP session failure: %s, %s', msgid, e.smtp_code, e.smtp_error) # If this was a permanent failure, don't add the recipients to the # refused, because we don't want them to be added to failures. @@ -397,7 +402,7 @@ def bulkdeliver(mlist, msg, msgdata, envsender, failures, conn): # MTA not responding, or other socket problems, or any other kind of # SMTPException. In that case, nothing got delivered, so treat this # as a temporary failure. - flog.error('%s low level smtp error: %s', msgid, e) + log.error('%s low level smtp error: %s', msgid, e) error = str(e) for r in recips: refused[r] = (-1, error) diff --git a/mailman/queue/bounce.py b/mailman/queue/bounce.py index 18fa08437..9f390130d 100644 --- a/mailman/queue/bounce.py +++ b/mailman/queue/bounce.py @@ -27,6 +27,7 @@ from email.MIMEMessage import MIMEMessage from email.MIMEText import MIMEText from email.Utils import parseaddr +from mailman import Defaults from mailman import Utils from mailman.Bouncers import BouncerAPI from mailman.Message import UserNotification @@ -80,7 +81,7 @@ class BounceMixin: self._bounce_events_fp = None self._bouncecnt = 0 self._nextaction = (datetime.datetime.now() + - config.REGISTER_BOUNCES_EVERY) + Defaults.REGISTER_BOUNCES_EVERY) def _queue_bounces(self, listname, addrs, msg): today = datetime.date.today() @@ -132,7 +133,7 @@ class BounceMixin: if self._nextaction > now or self._bouncecnt == 0: return # Let's go ahead and register the bounces we've got stored up - self._nextaction = now + config.REGISTER_BOUNCES_EVERY + self._nextaction = now + Defaults.REGISTER_BOUNCES_EVERY self._register_bounces() def _probe_bounce(self, mlist, token): @@ -153,7 +154,7 @@ class BounceMixin: class BounceRunner(Runner, BounceMixin): - QDIR = config.BOUNCEQUEUE_DIR + """The bounce runner.""" def __init__(self, slice=None, numslices=1): Runner.__init__(self, slice, numslices) @@ -162,7 +163,6 @@ class BounceRunner(Runner, BounceMixin): def _dispose(self, mlist, msg, msgdata): # Make sure we have the most up-to-date state mlist.Load() - outq = Switchboard(config.OUTQUEUE_DIR) # There are a few possibilities here: # # - the message could have been VERP'd in which case, we know exactly @@ -176,14 +176,15 @@ class BounceRunner(Runner, BounceMixin): # owner address. That way, if a list owner address bounces, at least # some human has a chance to deal with it. Is this a bounce for a # message to a list owner, coming to the site owner? - if msg.get('to', '') == config.SITE_OWNER_ADDRESS: + if msg.get('to', '') == config.mailman.site_owner: # Send it on to the site owners, but craft the envelope sender to # be the noreply address, so if the site owner bounce, we won't # get stuck in a bounce loop. - outq.enqueue(msg, msgdata, - recips=[config.SITE_OWNER_ADDRESS], - envsender=config.NO_REPLY_ADDRESS, - ) + config.switchboards['out'].enqueue( + msg, msgdata, + recips=[config.mailman.site_owner], + envsender=config.mailman.noreply_address, + ) # List isn't doing bounce processing? if not mlist.bounce_processing: return @@ -241,7 +242,7 @@ def verp_bounce(mlist, msg): to = parseaddr(field)[1] if not to: continue # empty header - mo = re.search(config.VERP_REGEXP, to) + mo = re.search(Defaults.VERP_REGEXP, to) if not mo: continue # no match of regexp try: @@ -251,7 +252,7 @@ def verp_bounce(mlist, msg): addr = '%s@%s' % mo.group('mailbox', 'host') except IndexError: elog.error("VERP_REGEXP doesn't yield the right match groups: %s", - config.VERP_REGEXP) + Defaults.VERP_REGEXP) return [] return [addr] @@ -272,7 +273,7 @@ def verp_probe(mlist, msg): to = parseaddr(field)[1] if not to: continue # empty header - mo = re.search(config.VERP_PROBE_REGEXP, to) + mo = re.search(Defaults.VERP_PROBE_REGEXP, to) if not mo: continue # no match of regexp try: @@ -286,7 +287,7 @@ def verp_probe(mlist, msg): except IndexError: elog.error( "VERP_PROBE_REGEXP doesn't yield the right match groups: %s", - config.VERP_PROBE_REGEXP) + Defaults.VERP_PROBE_REGEXP) return None diff --git a/mailman/queue/docs/outgoing.txt b/mailman/queue/docs/outgoing.txt index 9af554af7..851bdf474 100644 --- a/mailman/queue/docs/outgoing.txt +++ b/mailman/queue/docs/outgoing.txt @@ -47,8 +47,7 @@ injecting a message directly into the outgoing queue. >>> handler = config.handlers['calculate-recipients'] >>> handler.process(mlist, msg, msgdata) - >>> from mailman.queue import Switchboard - >>> outgoing_queue = Switchboard(config.OUTQUEUE_DIR) + >>> outgoing_queue = config.switchboards['out'] >>> ignore = outgoing_queue.enqueue( ... msg, msgdata, ... verp=True, listname=mlist.fqdn_listname, tolist=True, @@ -59,7 +58,7 @@ upstream SMTP, which happens to be our test server. >>> from mailman.queue.outgoing import OutgoingRunner >>> from mailman.testing.helpers import make_testable_runner - >>> outgoing = make_testable_runner(OutgoingRunner) + >>> outgoing = make_testable_runner(OutgoingRunner, 'out') >>> outgoing.run() Three messages have been delivered to our SMTP server, one for each recipient. diff --git a/mailman/queue/outgoing.py b/mailman/queue/outgoing.py index 9eb287e6b..2043d8bc8 100644 --- a/mailman/queue/outgoing.py +++ b/mailman/queue/outgoing.py @@ -26,6 +26,7 @@ import logging from datetime import datetime +from mailman import Defaults from mailman import Message from mailman.config import config from mailman.core import errors @@ -41,19 +42,19 @@ log = logging.getLogger('mailman.error') class OutgoingRunner(Runner, BounceMixin): - QDIR = config.OUTQUEUE_DIR + """The outgoing queue runner.""" def __init__(self, slice=None, numslices=1): Runner.__init__(self, slice, numslices) BounceMixin.__init__(self) # We look this function up only at startup time - handler = config.handlers[config.DELIVERY_MODULE] + handler = config.handlers[Defaults.DELIVERY_MODULE] self._func = handler.process # This prevents smtp server connection problems from filling up the # error log. It gets reset if the message was successfully sent, and # set if there was a socket.error. self._logged = False - self._retryq = Switchboard(config.RETRYQUEUE_DIR) + self._retryq = config.switchboards['retry'] def _dispose(self, mlist, msg, msgdata): # See if we should retry delivery of this message again. @@ -73,13 +74,13 @@ class OutgoingRunner(Runner, BounceMixin): # There was a problem connecting to the SMTP server. Log this # once, but crank up our sleep time so we don't fill the error # log. - port = config.SMTPPORT + port = int(config.mta.port) if port == 0: port = 'smtp' # Log this just once. if not self._logged: log.error('Cannot connect to SMTP server %s on port %s', - config.SMTPHOST, port) + config.mta.host, port) self._logged = True return True except errors.SomeRecipientsFailed, e: @@ -115,7 +116,7 @@ class OutgoingRunner(Runner, BounceMixin): return False else: # Keep trying to delivery this message for a while - deliver_until = now + config.DELIVERY_RETRY_PERIOD + deliver_until = now + Defaults.DELIVERY_RETRY_PERIOD msgdata['last_recip_count'] = len(recips) msgdata['deliver_until'] = deliver_until msgdata['recips'] = recips diff --git a/mailman/testing/helpers.py b/mailman/testing/helpers.py index 62b0d8d95..1bcadedaf 100644 --- a/mailman/testing/helpers.py +++ b/mailman/testing/helpers.py @@ -51,17 +51,21 @@ log = logging.getLogger('mailman.debug') -def make_testable_runner(runner_class): +def make_testable_runner(runner_class, name=None): """Create a queue runner that runs until its queue is empty. - :param runner_class: An IRunner + :param runner_class: The queue runner's class. + :type runner_class: class + :param name: Optional queue name; if not given, it is calculated from the + class name. + :type name: string or None :return: A runner instance. """ - assert runner_class.__name__.endswith('Runner'), ( - 'Unparseable runner class name: %s' % runner_class.__name__) - - name = runner_class.__name__[:-6].lower() + if name is None: + assert runner_class.__name__.endswith('Runner'), ( + 'Unparseable runner class name: %s' % runner_class.__name__) + name = runner_class.__name__[:-6].lower() class EmptyingRunner(runner_class): """Stop processing when the queue is empty.""" @@ -163,12 +167,11 @@ class TestableMaster(Master): class SMTPServer: """An smtp server for testing.""" - host = 'localhost' - port = 10825 - def __init__(self): self._messages = [] self._queue = Queue() + self.host = config.mta.smtp_host + self.port = int(config.mta.smtp_port) self._server = Server((self.host, self.port), self._queue) self._thread = threading.Thread(target=self._server.start) @@ -177,9 +180,11 @@ class SMTPServer: log.info('test SMTP server starting') self._thread.start() smtpd = smtplib.SMTP() + log.info('connecting to %s:%s', self.host, self.port) smtpd.connect(self.host, self.port) - smtpd.helo('test.localhost') + response = smtpd.helo('test.localhost') smtpd.quit() + log.info('SMTP server is running: %s', response) def stop(self): """Stop the smtp server.""" |
