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

Reply via email to