Mark Sapiro pushed to branch master at GNU Mailman / Mailman Core
Commits: eba826d4 by Mark Sapiro at 2021-04-21T13:46:42-07:00 Handle header instances in To and CC in avoid_duplicates and deliver. Fix other minor inconsistencies. - - - - - 48a21206 by Mark Sapiro at 2021-04-21T21:35:33+00:00 Merge branch 'fixes' into 'master' Handle header instances in To and CC in avoid_duplicates and deliver. Closes #883, #882, and #881 See merge request mailman/mailman!841 - - - - - 7 changed files: - src/mailman/docs/NEWS.rst - src/mailman/handlers/avoid_duplicates.py - src/mailman/handlers/tests/test_avoid_duplicates.py - src/mailman/mta/deliver.py - src/mailman/mta/tests/test_delivery.py - src/mailman/runners/docs/outgoing.rst - src/mailman/runners/tests/test_outgoing.py Changes: ===================================== src/mailman/docs/NEWS.rst ===================================== @@ -39,6 +39,12 @@ Bugs * Attempts to get a message from the message store with a missing file are now handled. (Closes #877) * The task runner no longer prematurely deletes saved DSNs. (Closes #878) +* The avoid_duplicates handler properly handles headers that are returned as + email.header.Header instances rather than strings. (Closeds #881) +* The mta.deliver module properly handles headers that are returned as + email.header.Header instances rather than strings. (Closeds #882) +* Places where ``to_list`` in the message metadata were increctly referenced + as ``tolist`` have been corrected. (Closes #883) Command line ------------ ===================================== src/mailman/handlers/avoid_duplicates.py ===================================== @@ -65,7 +65,8 @@ class AvoidDuplicates: # '"real name\r\n (dept)" <u...@example.com>' which parses incorrectly, # so we "unfold" headers here. for header in ('to', 'cc', 'resent-to', 'resent-cc'): - hdrs_unfolded = [re.sub('[\r\n]', '', value) for value in + # The value can contain a Header instance so stringify it. + hdrs_unfolded = [re.sub('[\r\n]', '', str(value)) for value in msg.get_all(header, [])] addrs = getaddresses(hdrs_unfolded) header_addresses = dict((addr, formataddr((name, addr))) ===================================== src/mailman/handlers/tests/test_avoid_duplicates.py ===================================== @@ -19,6 +19,7 @@ import unittest +from email.header import make_header from mailman.app.lifecycle import create_list from mailman.handlers.avoid_duplicates import AvoidDuplicates from mailman.interfaces.member import MemberRole @@ -139,5 +140,35 @@ To: a...@example.com Subject: A subject X-Mailman-Version: X.Y +More things to say. +""") + + def test_cc_with_header_instance(self): + # Ensure we can process header instances. + msg = mfs("""\ +From: a...@example.com +To: a...@example.com +Subject: A subject +X-Mailman-Version: X.Y + +More things to say. +""") + msgdata = dict(recipients=set(['a...@example.com'])) + msg['Cc'] = make_header( + [('"last, first" <ot...@example.com>', None), + ('"real name (dept)" <u...@example.com>', None)]) + AvoidDuplicates().process(self._mlist, msg, msgdata) + # Don't test the whole message. The order in the Cc: varies with + # Python version. + ccs = msg.get('cc') + self.assertIn('"last, first" <ot...@example.com>', ccs) + self.assertIn('"real name (dept)" <u...@example.com>', ccs) + del msg['cc'] + self.assertMultiLineEqual(msg.as_string(), """\ +From: a...@example.com +To: a...@example.com +Subject: A subject +X-Mailman-Version: X.Y + More things to say. """) ===================================== src/mailman/mta/deliver.py ===================================== @@ -121,10 +121,14 @@ def deliver(mlist, msg, msgdata): # Log the successful post, but if it was not destined to the mailing # list (e.g. to the owner or admin), print the actual recipients # instead of just the number. - if not msgdata.get('tolist', False): + if not msgdata.get('to_list', False): + # XXX This is meaningless as the config.logging.smtp.success + # template doesn't contain a recip substitution, but do it anyway + # in case the template is changed. recips = msg.get_all('to', []) recips.extend(msg.get_all('cc', [])) - substitutions['recips'] = COMMA.join(recips) + # recips can contain a Header() instance. Stringify it. + substitutions['recip'] = COMMA.join(map(str, recips)) template = config.logging.smtp.success if template.lower() != 'no': log.info('%s', expand(template, mlist, substitutions)) ===================================== src/mailman/mta/tests/test_delivery.py ===================================== @@ -22,6 +22,7 @@ import shutil import tempfile import unittest +from email.header import make_header from mailman.app.lifecycle import create_list from mailman.config import config from mailman.interfaces.mailinglist import Personalization @@ -381,8 +382,24 @@ Message-ID: def test_logging_with_folded_messageid(self): # Test that folded Message-ID header doesn't fold the log messages. mark = LogFileMark('mailman.smtp') - msgdata = dict(recipients=['a...@example.org'], tolist=True) + msgdata = dict(recipients=['a...@example.org'], to_list=True) self._deliverer(self._mlist, self._msg, msgdata) logs = mark.read() self.assertRegex(logs, r' \(\d+\) <AM6PR09MB347488.*smtp') self.assertRegex(logs, r' \(\d+\) <AM6PR09MB347488.*post') + + def test_logging_with_header_instance(self): + msgdata = dict(recipients=['t...@example.com', 'b...@example.org']) + self._mlist.personalize = Personalization.none + msgdata['recipients'] = ['t...@example.com', 'b...@example.org'] + self._msg['CC'] = make_header([('b...@example.org', None)]) + config.push('logging', """ + [logging.smtp] + success: post for $recip recips + """) + self.addCleanup(config.pop, 'logging') + mark = LogFileMark('mailman.smtp') + self._deliverer(self._mlist, self._msg, msgdata) + self.assertIn( + 'post for t...@example.com,b...@example.org recips', + mark.read()) ===================================== src/mailman/runners/docs/outgoing.rst ===================================== @@ -58,7 +58,7 @@ destination mailing list name. Simulate that here too. >>> ignore = outgoing_queue.enqueue( ... msg, msgdata, - ... tolist=True, + ... to_list=True, ... listid=mlist.list_id) Running the outgoing runner processes the message, delivering it to the ===================================== src/mailman/runners/tests/test_outgoing.py ===================================== @@ -73,7 +73,7 @@ Message-Id: <first> deliver_after = now() + timedelta(days=10) self._msgdata['deliver_after'] = deliver_after self._outq.enqueue(self._msg, self._msgdata, - tolist=True, listid='test.example.com') + to_list=True, listid='test.example.com') self._runner.run() items = get_queue_messages('out', expected_count=1) self.assertEqual(items[0].msgdata['deliver_after'], deliver_after) View it on GitLab: https://gitlab.com/mailman/mailman/-/compare/a767e0db48891aa8be48977abd6b7b2be7ac052e...48a21206ab16ac267df8e0889026e248fdf512c5 -- View it on GitLab: https://gitlab.com/mailman/mailman/-/compare/a767e0db48891aa8be48977abd6b7b2be7ac052e...48a21206ab16ac267df8e0889026e248fdf512c5 You're receiving this email because of your account on gitlab.com.
_______________________________________________ Mailman-checkins mailing list -- mailman-checkins@python.org To unsubscribe send an email to mailman-checkins-le...@python.org https://mail.python.org/mailman3/lists/mailman-checkins.python.org/ Member address: arch...@jab.org