aboutsummaryrefslogtreecommitdiffstats
path: root/Mailman/Queue/BounceRunner.py
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman/Queue/BounceRunner.py')
-rw-r--r--Mailman/Queue/BounceRunner.py56
1 files changed, 55 insertions, 1 deletions
diff --git a/Mailman/Queue/BounceRunner.py b/Mailman/Queue/BounceRunner.py
index ffffc2a6..6ea1fc68 100644
--- a/Mailman/Queue/BounceRunner.py
+++ b/Mailman/Queue/BounceRunner.py
@@ -37,6 +37,12 @@ COMMASPACE = ', '
REGISTER_BOUNCES_EVERY = mm_cfg.minutes(15)
+try:
+ True, False
+except NameError:
+ True = 1
+ False = 0
+
class BounceRunner(Runner):
@@ -82,8 +88,21 @@ class BounceRunner(Runner):
# Try VERP detection first, since it's quick and easy
addrs = verp_bounce(mlist, msg)
if not addrs:
+ # See if this was a probe message.
+ token = verp_probe(mlist, msg)
+ if token:
+ # The list must be locked to perform these operations
+ mlist.Lock()
+ try:
+ op, addr, bmsg = mlist.pend_confirm(token)
+ info = mlist.getBounceInfo(addr)
+ mlist.disableBouncingMember(addr, info, bmsg)
+ mlist.Save()
+ finally:
+ mlist.Unlock()
+ return
# That didn't give us anything useful, so try the old fashion
- # bounce matching modules
+ # 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.
@@ -173,6 +192,41 @@ def verp_bounce(mlist, msg):
+def verp_probe(mlist, msg):
+ bmailbox, bdomain = Utils.ParseEmail(mlist.GetBouncesEmail())
+ # Sadly not every MTA bounces VERP messages correctly, or consistently.
+ # Fall back to Delivered-To: (Postfix), Envelope-To: (Exim) 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', 'envelope-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_PROBE_REGEXP, to)
+ if not mo:
+ continue # no match of regexp
+ try:
+ if bmailbox <> mo.group('bounces'):
+ continue # not a bounce to our list
+ # Extract the token and see if there's an entry
+ token = mo.group('token')
+ data = mlist.pend_confirm(token, expunge=False)
+ if data is not None:
+ return token
+ except IndexError:
+ syslog(
+ 'error',
+ "VERP_PROBE_REGEXP doesn't yield the right match groups: %s",
+ mm_cfg.VERP_PROBE_REGEXP)
+ return None
+
+
+
def maybe_forward(mlist, msg):
# Does the list owner want to get non-matching bounce messages?
# If not, simply discard it.