Update of /cvsroot/mailman/mailman/Mailman/Queue
In directory usw-pr-cvs1:/tmp/cvs-serv13270/Mailman/Queue
Modified Files:
BounceRunner.py
Log Message:
A significant rewrite of the main bounce runner logic to make it
perform better. In general there are two changes: 1) we never lock a
list until and unless absolutely necessary, 2) we only run the bounce
runner once every minute (as opposed to the normal runners'
once-per-second sleep time). Specifically,
SLEEPTIME: The base class now looks at this attribute to decide how
long to sleep between loop iterations, and it defines a default. We
override the bounce runner's value to lengthen the time it sleeps to 1
minute (we may eventually want to move this to Defaults.py).
__scanbounce(): Gone. All its functionality is subsumed in the new
ScanMessages() method and the new _dispose().
__verpbounce(): Renamed to the non-method verp_bounce(). Also, we rip
out the code that iterates through all the lists if the bounce came to
the site list's -bounces address.
_dispose(): Simply calls verp_bounce() to find bouncing addresses, and
if that returns a false value (empty list), calls ScanMessages() to
see if the bounce detector can find some bouncing addresses. If not,
we're done (after possibly forwarding the non-matching message).
Otherwise, we register the bounce either on the target mailing list,
or on all the mailing lists if this came to the site's -bounces
address.
Index: BounceRunner.py
===================================================================
RCS file: /cvsroot/mailman/mailman/Mailman/Queue/BounceRunner.py,v
retrieving revision 2.11
retrieving revision 2.12
diff -C2 -d -r2.11 -r2.12
*** BounceRunner.py 13 Mar 2002 05:57:37 -0000 2.11
--- BounceRunner.py 26 Mar 2002 22:23:46 -0000 2.12
***************
*** 32,79 ****
class BounceRunner(Runner):
QDIR = mm_cfg.BOUNCEQUEUE_DIR
def _dispose(self, mlist, msg, msgdata):
outq = get_switchboard(mm_cfg.OUTQUEUE_DIR)
! # BAW: Not all the functions of this qrunner require the list to be
! # locked. Still, it's more convenient to lock it here and now and
! # deal with lock failures in one place.
! try:
! mlist.Lock(timeout=mm_cfg.LIST_LOCK_TIMEOUT)
! except LockFile.TimeOutError:
! # Oh well, try again later
! return 1
! try:
! # There are a few possibilities here:
! #
! # - the message could have been VERP'd in which case, we know
! # exactly who the message was destined for. That make our job
! # easy.
! # - the message could have been originally destined for a list
! # owner, but a list owner address itself bounced. That's bad,
! # and for now we'll simply log the problem and attempt to
! # deliver the message to the site owner.
! #
! # All messages to [EMAIL PROTECTED] have their envelope sender
! # set to [EMAIL PROTECTED] (no virtual domain). Is this a bounce
! # for a message to a list owner, coming to the site owner?
! if msg.get('to', '') == Utils.get_site_email(extra='-owner'):
! # Send it on to the site owners, but craft the envelope sender
! # to be the -loop detection address, so if /they/ bounce, we
! # won't get stuck in a bounce loop.
! outq.enqueue(msg, msgdata,
! recips=[Utils.get_site_email()],
! envsender=Utils.get_site_email(extra='loop'),
! )
! # List isn't doing bounce processing?
! if not mlist.bounce_processing:
! return
! # If VERPing, the method will take care of things.
! elif self.__verpbounce(mlist, msg):
! mlist.Save()
! return
! # Otherwise do bounce detection of the original message
! elif self.__scanbounce(mlist, msg):
! mlist.Save()
! return
# Does the list owner want to get non-matching bounce messages?
# If not, simply discard it.
--- 32,72 ----
class BounceRunner(Runner):
QDIR = mm_cfg.BOUNCEQUEUE_DIR
+ # We only do bounce processing once per minute.
+ SLEEPTIME = 60
def _dispose(self, mlist, msg, msgdata):
outq = get_switchboard(mm_cfg.OUTQUEUE_DIR)
! # There are a few possibilities here:
! #
! # - the message could have been VERP'd in which case, we know exactly
! # who the message was destined for. That make our job easy.
! # - the message could have been originally destined for a list owner,
! # but a list owner address itself bounced. That's bad, and for now
! # we'll simply log the problem and attempt to deliver the message to
! # the site owner.
! #
! # All messages to [EMAIL PROTECTED] have their envelope sender set
! # to [EMAIL PROTECTED] (no virtual domain). Is this a bounce for a
! # message to a list owner, coming to the site owner?
! if msg.get('to', '') == Utils.get_site_email(extra='-owner'):
! # Send it on to the site owners, but craft the envelope sender to
! # be the -loop detection address, so if /they/ bounce, we won't
! # get stuck in a bounce loop.
! outq.enqueue(msg, msgdata,
! recips=[Utils.get_site_email()],
! envsender=Utils.get_site_email(extra='loop'),
! )
! # List isn't doing bounce processing?
! if not mlist.bounce_processing:
! return
! # Try VERP detection first, since it's quick and easy
! addrs = verp_bounce(mlist, msg)
! if not addrs:
! # That didn't give us anything useful, so try the old fashion
! # bounce matching modules
! addrs = BouncerAPI.ScanMessages(mlist, msg)
! # If that still didn't return us any useful addresses, then send it on
! # or discard it.
! if not addrs:
# Does the list owner want to get non-matching bounce messages?
# If not, simply discard it.
***************
*** 92,169 ****
syslog('bounce', 'discarding unrecognized, message-id: %s',
msg.get('message-id', 'n/a'))
! finally:
! mlist.Unlock()
!
! def __verpbounce(self, mlist, msg):
! bmailbox, bdomain = Utils.ParseEmail(mlist.getListAddress('bounces'))
! # Sadly not every MTA bounces VERP messages correctly. Fall back to
! # Delivered-to: and Apparently-To:, and then short-circuit if we still
! # don't have anything to work with. Note that there can be multiple
! # Delivered-To: headers so we need to search them all (and we don't
! # worry about false positives for forwarded email, because only one
! # should match VERP_REGEXP).
! vals = []
! for header in ('to', 'delivered-to', 'apparently-to'):
! vals.extend(msg.get_all(header, []))
! for field in vals:
! to = parseaddr(field)[1]
! if not to:
! continue # empty header
! mo = re.search(mm_cfg.VERP_REGEXP, to)
! if not mo:
! continue # no match of regexp
! try:
! if bmailbox <> mo.group('bounces'):
! continue # not a bounce to our list
! # All is good
! addr = '%s@%s' % mo.group('mailbox', 'host')
! except IndexError:
! syslog('error',
! "VERP_REGEXP doesn't yield the right match groups: %s",
! mm_cfg.VERP_REGEXP)
! return 0
! # Now, if this message has come to the site list, then search not
! # only it, but all the mailing lists on the system, registering a
! # bounce with each for this address.
! if mlist.internal_name() == mm_cfg.MAILMAN_SITE_LIST:
! found = 0
! for listname in Utils.list_names():
! xlist = self._open_list(listname)
! if xlist.isMember(addr):
! unlockp = 0
! if not xlist.Locked():
! xlist.Lock()
! unlockp = 1
! try:
! xlist.registerBounce(addr, msg)
! found = 1
! xlist.Save()
! finally:
! if unlockp:
! xlist.Unlock()
! return found
! elif mlist.isMember(addr):
! mlist.registerBounce(addr, msg)
! return 1
! return 0
!
! def __scanbounce(self, mlist, msg):
if mlist.internal_name() == mm_cfg.MAILMAN_SITE_LIST:
- found = 0
for listname in Utils.list_names():
xlist = self._open_list(listname)
! unlockp = 0
! if not xlist.Locked():
! xlist.Lock()
! unlockp = 1
! try:
! status = BouncerAPI.ScanMessages(xlist, msg)
! if status:
found = 1
! xlist.Save()
! finally:
! if unlockp:
! xlist.Unlock()
! return found
else:
! return BouncerAPI.ScanMessages(mlist, msg)
--- 85,154 ----
syslog('bounce', 'discarding unrecognized, message-id: %s',
msg.get('message-id', 'n/a'))
! return
! # Okay, we have some recognized addresses. We now need to register
! # the bounces for each of these. If the bounce came to the site list,
! # then we'll register the address on every list in the system, but
! # note: this could be VERY resource intensive!
if mlist.internal_name() == mm_cfg.MAILMAN_SITE_LIST:
for listname in Utils.list_names():
xlist = self._open_list(listname)
! if xlist.isMember(addr):
! unlockp = 0
! if not xlist.Locked():
! try:
! xlist.Lock(timeout=mm_cfg.LIST_LOCK_TIMEOUT)
! except LockFile.TimeOutError:
! # Oh well, forget aboutf this list
! continue
! unlockp = 1
! try:
! xlist.registerBounce(addr, msg)
found = 1
! xlist.Save()
! finally:
! if unlockp:
! xlist.Unlock()
else:
! try:
! mlist.Lock(timeout=mm_cfg.LIST_LOCK_TIMEOUT)
! except LockFile.TimeOutError:
! # Oh well, forget about this bounce
! return
! try:
! for addr in addrs:
! mlist.registerBounce(addr, msg)
! mlist.Save()
! finally:
! mlist.Unlock()
!
!
!
! def verp_bounce(mlist, msg):
! bmailbox, bdomain = Utils.ParseEmail(mlist.GetBouncesEmail())
! # Sadly not every MTA bounces VERP messages correctly. Fall back to
! # Delivered-to: and Apparently-To:, and then short-circuit if we still
! # don't have anything to work with. Note that there can be multiple
! # Delivered-To: headers so we need to search them all (and we don't
! # worry about false positives for forwarded email, because only one
! # should match VERP_REGEXP).
! vals = []
! for header in ('to', 'delivered-to', 'apparently-to'):
! vals.extend(msg.get_all(header, []))
! for field in vals:
! to = parseaddr(field)[1]
! if not to:
! continue # empty header
! mo = re.search(mm_cfg.VERP_REGEXP, to)
! if not mo:
! continue # no match of regexp
! try:
! if bmailbox <> mo.group('bounces'):
! continue # not a bounce to our list
! # All is good
! addr = '%s@%s' % mo.group('mailbox', 'host')
! except IndexError:
! syslog('error',
! "VERP_REGEXP doesn't yield the right match groups: %s",
! mm_cfg.VERP_REGEXP)
! return []
! return [addr]
_______________________________________________
Mailman-checkins mailing list
[EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/mailman-checkins