diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/mailman/app/bounces.py | 17 | ||||
| -rw-r--r-- | src/mailman/app/tests/test_bounces.py | 28 | ||||
| -rw-r--r-- | src/mailman/queue/bounce.py | 37 |
3 files changed, 39 insertions, 43 deletions
diff --git a/src/mailman/app/bounces.py b/src/mailman/app/bounces.py index 62f24d39b..f216c959e 100644 --- a/src/mailman/app/bounces.py +++ b/src/mailman/app/bounces.py @@ -45,6 +45,7 @@ from mailman.core.i18n import _ from mailman.email.message import UserNotification from mailman.interfaces.bounce import IBounceDetector from mailman.interfaces.listmanager import IListManager +from mailman.interfaces.membership import ISubscriptionService from mailman.interfaces.pending import IPendable, IPendings from mailman.utilities.email import split_email from mailman.utilities.i18n import make @@ -132,7 +133,6 @@ class _BaseVERPParser: def get_verp(self, mlist, msg): """Extract a set of VERP bounce addresses. - :param mlist: The mailing list being checked. :type mlist: `IMailingList` :param msg: The message being parsed. @@ -163,7 +163,8 @@ class _BaseVERPParser: elog.error('Bad VERP pattern: {0}'.format(self._pattern)) return set() else: - verp_matches.add(original_address) + if original_address is not None: + verp_matches.add(original_address) return verp_matches @@ -183,8 +184,16 @@ class ProbeVERP(_BaseVERPParser): def _get_address(self, match_object): # Extract the token and get the matching address. token = match_object.group('token') - op, address, bmsg = getUtility(IPendings).confirm(token) - return address + pendable = getUtility(IPendings).confirm(token) + if pendable is None: + # The token must have already been confirmed, or it may have been + # evicted from the database already. + return None + member_id = pendable['member_id'] + member = getUtility(ISubscriptionService).get_member(member_id) + if member is None: + return None + return member.address.email diff --git a/src/mailman/app/tests/test_bounces.py b/src/mailman/app/tests/test_bounces.py index 47fadeb67..a79b1524c 100644 --- a/src/mailman/app/tests/test_bounces.py +++ b/src/mailman/app/tests/test_bounces.py @@ -32,7 +32,7 @@ import unittest from zope.component import getUtility -from mailman.app.bounces import StandardVERP, send_probe +from mailman.app.bounces import StandardVERP, ProbeVERP, send_probe from mailman.app.lifecycle import create_list from mailman.app.membership import add_member from mailman.config import config @@ -330,14 +330,38 @@ http://example.com/anne@example.com test-owner@example.com""") class TestProbe(unittest.TestCase): - """Test VERP probing.""" + """Test VERP probe parsing.""" layer = ConfigLayer def setUp(self): self._mlist = create_list('test@example.com') + self._member = add_member(self._mlist, 'anne@example.com', + 'Anne Person', 'xxx', + DeliveryMode.regular, 'en') + self._msg = message_from_string("""\ +From: bouncer@example.com +To: anne@example.com +Subject: You bounced +Message-ID: <first> + +""") + def test_get_addresses(self): + # Be able to extract the probed address from the pending database + # based on the token in a probe bounce. + token = send_probe(self._member, self._msg) + # Simulate a bounce of the message in the virgin queue. + message = get_queue_messages('virgin')[0].msg + bounce = message_from_string("""\ +To: {0} +From: mail-daemon@example.com +""".format(message['From'])) + addresses = ProbeVERP().get_verp(self._mlist, bounce) + self.assertEqual(addresses, set(['anne@example.com'])) + # The pendable is no longer in the database. + self.assertEqual(getUtility(IPendings).confirm(token), None) diff --git a/src/mailman/queue/bounce.py b/src/mailman/queue/bounce.py index 35c27c6d6..fb8b0124a 100644 --- a/src/mailman/queue/bounce.py +++ b/src/mailman/queue/bounce.py @@ -18,12 +18,10 @@ """Bounce queue runner.""" import os -import re import cPickle import logging import datetime -from email.utils import parseaddr from lazr.config import as_timedelta from mailman.app.bounces import StandardVERP @@ -31,7 +29,6 @@ from mailman.config import config from mailman.core.i18n import _ from mailman.interfaces.bounce import Stop from mailman.queue import Runner -from mailman.utilities.email import split_email COMMASPACE = ', ' @@ -228,40 +225,6 @@ class BounceRunner(Runner, BounceMixin): -def verp_probe(mlist, msg): - bmailbox, bdomain = split_email(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(config.mta.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: - elog.error( - "verp_probe_regexp doesn't yield the right match groups: %s", - config.mta.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. |
