diff options
| -rw-r--r-- | src/mailman/app/tests/test_notifications.py | 5 | ||||
| -rw-r--r-- | src/mailman/chains/headers.py | 3 | ||||
| -rw-r--r-- | src/mailman/chains/tests/test_headers.py | 30 | ||||
| -rw-r--r-- | src/mailman/database/alembic/versions/fa0d96e28631_template_manager.py | 4 | ||||
| -rw-r--r-- | src/mailman/database/tests/test_migrations.py | 12 | ||||
| -rw-r--r-- | src/mailman/docs/NEWS.rst | 16 | ||||
| -rw-r--r-- | src/mailman/rest/listconf.py | 4 | ||||
| -rw-r--r-- | src/mailman/rest/tests/test_listconf.py | 10 |
8 files changed, 57 insertions, 27 deletions
diff --git a/src/mailman/app/tests/test_notifications.py b/src/mailman/app/tests/test_notifications.py index 05ce4cf2f..4a6f56a72 100644 --- a/src/mailman/app/tests/test_notifications.py +++ b/src/mailman/app/tests/test_notifications.py @@ -48,7 +48,8 @@ class TestNotifications(unittest.TestCase): self._mlist = create_list('test@example.com') self._mlist.display_name = 'Test List' getUtility(ITemplateManager).set( - 'user:ack:welcome', self._mlist.list_id, 'mailman:///welcome.txt') + 'list:user:notice:welcome', self._mlist.list_id, + 'mailman:///welcome.txt') config.push('template config', """\ [paths.testing] template_dir: {}/templates @@ -94,7 +95,7 @@ Welcome to the Test List mailing list. # The welcome message url can contain placeholders for the fqdn list # name and language. getUtility(ITemplateManager).set( - 'user:ack:welcome', self._mlist.list_id, + 'list:user:notice:welcome', self._mlist.list_id, 'mailman:///$listname/$language/welcome.txt') # Add the xx language and subscribe Anne using it. manager = getUtility(ILanguageManager) diff --git a/src/mailman/chains/headers.py b/src/mailman/chains/headers.py index d41e64386..6fc061fe4 100644 --- a/src/mailman/chains/headers.py +++ b/src/mailman/chains/headers.py @@ -20,6 +20,7 @@ import re import logging +from email.header import Header from itertools import count from mailman.chains.base import Chain, Link from mailman.config import config @@ -101,6 +102,8 @@ class HeaderMatchRule: for p in msg.walk(): headers.extend(p.get_all(self.header, [])) for value in headers: + if isinstance(value, Header): + value = value.encode() if re.search(self.pattern, value, re.IGNORECASE): return True return False diff --git a/src/mailman/chains/tests/test_headers.py b/src/mailman/chains/tests/test_headers.py index b74b8ebc9..3da7a2435 100644 --- a/src/mailman/chains/tests/test_headers.py +++ b/src/mailman/chains/tests/test_headers.py @@ -19,6 +19,7 @@ import unittest +from email.header import Header from mailman.app.lifecycle import create_list from mailman.chains.headers import HeaderMatchRule, make_link from mailman.config import config @@ -209,6 +210,35 @@ This is junk self.assertIsInstance(event, HoldEvent) self.assertEqual(event.chain, config.chains['hold']) + def test_get_all_returns_non_string(self): + # Test case where msg.get_all() returns header instance. + msg = mfs("""\ +From: anne@example.com +To: test@example.com +Subject: =?unknown-8bit?q?Become_smarter_now_=96_Increase__your_brain...?= +Message-ID: <ant> + +body + +""") + # XXX In the wild we have seen a message instance in which the subject + # header value is an email.header.Header instance rather than a + # string. We don't know how to recreate that here so we cheat. + msg['Subject'] = Header( + 'Become_smarter_now \x96 Increase your brain...', 'utf-8') + msgdata = {} + header_matches = IHeaderMatchList(self._mlist) + header_matches.append('Subject', '=\?utf', 'hold') + # This event subscriber records the event that occurs when the message + # is processed by the owner chain. + events = [] + with event_subscribers(events.append): + process(self._mlist, msg, msgdata, start_chain='header-match') + self.assertEqual(len(events), 1) + event = events[0] + self.assertIsInstance(event, HoldEvent) + self.assertEqual(event.chain, config.chains['hold']) + @configuration('antispam', header_checks=""" Foo: foo """, jump_chain='hold') diff --git a/src/mailman/database/alembic/versions/fa0d96e28631_template_manager.py b/src/mailman/database/alembic/versions/fa0d96e28631_template_manager.py index 8fb8c1056..4e8fc39c6 100644 --- a/src/mailman/database/alembic/versions/fa0d96e28631_template_manager.py +++ b/src/mailman/database/alembic/versions/fa0d96e28631_template_manager.py @@ -24,9 +24,9 @@ CONVERSION_MAPPING = dict( digest_footer_uri='list:digest:footer', digest_header_uri='list:digest:header', footer_uri='list:regular:footer', - goodbye_message_uri='user:ack:goodbye', + goodbye_message_uri='list:user:notice:goodbye', header_uri='list:regular:header', - welcome_message_uri='user:ack:welcome', + welcome_message_uri='list:user:notice:welcome', ) REVERSE_MAPPING = {value: key for key, value in CONVERSION_MAPPING.items()} diff --git a/src/mailman/database/tests/test_migrations.py b/src/mailman/database/tests/test_migrations.py index cba5dbbd5..b5d17d6db 100644 --- a/src/mailman/database/tests/test_migrations.py +++ b/src/mailman/database/tests/test_migrations.py @@ -374,16 +374,16 @@ class TestMigrations(unittest.TestCase): 'list:digest:header': 'digest_header', 'list:regular:footer': 'footer', 'list:regular:header': 'header', - 'user:ack:goodbye': 'goodbye', - 'user:ack:welcome': 'welcome', + 'list:user:notice:goodbye': 'goodbye', + 'list:user:notice:welcome': 'welcome', }.get(name, name))) self.assertEqual(sorted(seen_names), [ 'list:digest:footer', 'list:digest:header', 'list:regular:footer', 'list:regular:header', - 'user:ack:goodbye', - 'user:ack:welcome', + 'list:user:notice:goodbye', + 'list:user:notice:welcome', ]) def test_fa0d96e28631_upgrade_no_uris(self): @@ -435,10 +435,10 @@ class TestMigrations(unittest.TestCase): manager.set('list:regular:header', 'ant.example.com', 'mailman:///header.txt') - manager.set('user:ack:welcome', + manager.set('list:user:notice:welcome', 'ant.example.com', 'mailman:///welcome.txt') - manager.set('user:ack:goodbye', + manager.set('list:user:notice:goodbye', 'ant.example.com', 'mailman:///goodbye.txt') mlist_table = sa.sql.table( diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst index 3a2398b74..c7bbc6de6 100644 --- a/src/mailman/docs/NEWS.rst +++ b/src/mailman/docs/NEWS.rst @@ -164,15 +164,6 @@ Interfaces * ``ISubscriptionService`` now supports mass unsubscribes. Given by Harshit Bansal. -Internal --------- - * Add official support for Python 3.6. (Closes #295) - * A handful of unused legacy exceptions have been removed. The redundant - ``MailmanException`` has been removed; use ``MailmanError`` everywhere. - * Drop the use of the ``lazr.smtptest`` library, which is based on the - asynchat/asyncore-based smtpd.py stdlib module. Instead, use the - asyncio-based aiosmtpd package. - Message handling ---------------- * New DMARC mitigations have been added. Given by Mark Sapiro. (Closes #247) @@ -273,7 +264,12 @@ REST Other ----- - * The test suite is now Python 3.5 compatible. + * Add official support for Python 3.5 and 3.6. (Closes #295) + * A handful of unused legacy exceptions have been removed. The redundant + ``MailmanException`` has been removed; use ``MailmanError`` everywhere. + * Drop the use of the ``lazr.smtptest`` library, which is based on the + asynchat/asyncore-based smtpd.py stdlib module. Instead, use the + asyncio-based `aiosmtpd <http://aiosmtpd.readthedocs.io/>`_ package. * Improvements in importing Mailman 2.1 lists, given by Aurélien Bompard. * The ``prototype`` archiver is not web accessible so it does not have a ``list_url`` or permalink. Given by Aurélien Bompard. diff --git a/src/mailman/rest/listconf.py b/src/mailman/rest/listconf.py index 87535ce48..da7111d0f 100644 --- a/src/mailman/rest/listconf.py +++ b/src/mailman/rest/listconf.py @@ -65,9 +65,9 @@ TEMPLATE_ATTRIBUTES = dict( digest_footer_uri='list:digest:footer', digest_header_uri='list:digest:header', footer_uri='list:regular:footer', - goodbye_message_uri='user:ack:goodbye', + goodbye_message_uri='list:user:notice:goodbye', header_uri='list:regular:header', - welcome_message_uri='user:ack:welcome', + welcome_message_uri='list:user:notice:welcome', ) diff --git a/src/mailman/rest/tests/test_listconf.py b/src/mailman/rest/tests/test_listconf.py index 06c138fee..782effd29 100644 --- a/src/mailman/rest/tests/test_listconf.py +++ b/src/mailman/rest/tests/test_listconf.py @@ -379,7 +379,7 @@ class TestConfiguration(unittest.TestCase): def test_get_goodbye_message_uri(self): with transaction(): getUtility(ITemplateManager).set( - 'user:ack:goodbye', self._mlist.list_id, + 'list:user:notice:goodbye', self._mlist.list_id, 'mailman:///goodbye.txt') resource, response = call_api( 'http://localhost:9001/3.0/lists/ant.example.com/config' @@ -395,7 +395,7 @@ class TestConfiguration(unittest.TestCase): self.assertEqual(response.status_code, 204) self.assertEqual( getUtility(ITemplateManager).raw( - 'user:ack:goodbye', self._mlist.list_id).uri, + 'list:user:notice:goodbye', self._mlist.list_id).uri, 'mailman:///salutation.txt') def test_patch_goodbye_message_uri(self): @@ -407,14 +407,14 @@ class TestConfiguration(unittest.TestCase): self.assertEqual(response.status_code, 204) self.assertEqual( getUtility(ITemplateManager).raw( - 'user:ack:goodbye', self._mlist.list_id).uri, + 'list:user:notice:goodbye', self._mlist.list_id).uri, 'mailman:///salutation.txt') def test_put_goodbye_message_uri(self): manager = getUtility(ITemplateManager) with transaction(): manager.set( - 'user:ack:goodbye', + 'list:user:notice:goodbye', self._mlist.list_id, 'mailman:///somefile.txt') resource, response = call_api( @@ -424,7 +424,7 @@ class TestConfiguration(unittest.TestCase): 'PUT') self.assertEqual(response.status_code, 204) self.assertEqual( - manager.raw('user:ack:goodbye', self._mlist.list_id).uri, + manager.raw('list:user:notice:goodbye', self._mlist.list_id).uri, 'mailman:///salutation.txt') def test_advertised(self): |
