Mark Sapiro pushed to branch master at GNU Mailman / Mailman Core


Commits:
59049e41 by TommyLike Hu at 2021-04-28T18:45:31+00:00
Fix encoding issue in command handler

- - - - -
b87ca121 by Mark Sapiro at 2021-04-28T18:45:40+00:00
Merge branch 'bug/fix-encoding-issue' into 'master'

Fix encoding issue in command handler

Closes #858 and #859

See merge request mailman/mailman!822
- - - - -


3 changed files:

- src/mailman/docs/NEWS.rst
- src/mailman/runners/command.py
- src/mailman/runners/tests/test_confirm.py


Changes:

=====================================
src/mailman/docs/NEWS.rst
=====================================
@@ -50,6 +50,10 @@ Bugs
   says.  (Closes #169)
 * Some exceptions in ARC signing of some posts from HyperKitty and some from
   prod.outlook.com are now handled without shunting the message.  (Closes #885)
+* Command runner now will remove all non-ascii characters in the message
+  subject before processing it.(Closes #858)
+* Command runner now will decode the message body before processing it.
+ (Closes #859)
 
 Command line
 ------------


=====================================
src/mailman/runners/command.py
=====================================
@@ -84,7 +84,9 @@ class CommandFinder:
         try:
             subject = str(make_header(decode_header(raw_subject)))
             # Mail commands must be ASCII.
-            self.command_lines.append(subject.encode('us-ascii'))
+            # NOTE(tommylikehu): remove all none ascii characters via encoding
+            # with ignore option.
+            self.command_lines.append(subject.encode('us-ascii', 'ignore'))
         except (HeaderParseError, UnicodeError, LookupError):
             # The Subject header was unparseable or not ASCII.  If the raw
             # subject is a unicode object, convert it to ASCII ignoring all
@@ -104,9 +106,11 @@ class CommandFinder:
         if part is None:
             # There was no text/plain part to be found.
             return
-        body = part.get_payload()
+        body = part.get_payload(decode=True)
         # text/plain parts better have string payloads.
-        assert isinstance(body, (bytes, str)), 'Non-string decoded payload'
+        assert body is not None, 'Non-text payload'
+        body = body.decode(part.get_content_charset('us-ascii'),
+                           errors='replace')
         lines = body.splitlines()
         # Use no more lines than specified
         max_lines = int(config.mailman.email_commands_max_lines)


=====================================
src/mailman/runners/tests/test_confirm.py
=====================================
@@ -17,6 +17,7 @@
 
 """Test the `confirm` command."""
 
+import base64
 import unittest
 
 from datetime import datetime
@@ -89,6 +90,61 @@ To: test-conf...@example.com
         address = manager.get_address('a...@example.org')
         self.assertEqual(address.email, 'a...@example.org')
 
+    def test_confirm_with_non_ascii_prefix(self):
+        confirm_subject = str("confirm {}".format(self._token))
+        subject = '=?utf-8?b?5Zue5aSN?= =?utf-8?b?{0}?='.format(
+            base64.encodebytes(confirm_subject.encode()).decode().rstrip())
+        msg = mfs("""\
+From: a...@example.org
+To: test-conf...@example.com
+""")
+        msg['Subject'] = subject
+        self._commandq.enqueue(msg, dict(listid='test.example.com'))
+        self._runner.run()
+        # Anne is now a confirmed member so her user record and email address
+        # should exist in the database.
+        manager = getUtility(IUserManager)
+        user = manager.get_user('a...@example.org')
+        address = list(user.addresses)[0]
+        self.assertEqual(address.email, 'a...@example.org')
+        self.assertEqual(address.verified_on,
+                         datetime(2005, 8, 1, 7, 49, 23))
+        address = manager.get_address('a...@example.org')
+        self.assertEqual(address.email, 'a...@example.org')
+
+    def test_confirm_with_base64_encoded_body(self):
+        # Clear out the virgin queue so that the test below only sees the
+        # reply to the confirmation message.
+        mail_content = "hello from mailman fake user"
+        get_queue_messages('virgin')
+        subject = 'Re: confirm {}'.format(self._token)
+        to = 'test-confirm+{}@example.com'.format(self._token)
+        msg = mfs("""\
+From: Anne Person <a...@example.org>
+MIME-Version: 1.0
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: base64
+Content-Disposition: inline
+
+{}
+""".format(base64.encodebytes(mail_content.encode()).decode()))
+        msg['Subject'] = subject
+        msg['To'] = to
+        self._commandq.enqueue(msg, dict(listid='test.example.com'))
+        self._runner.run()
+        # Anne is now a confirmed member so her user record and email address
+        # should exist in the database.
+        manager = getUtility(IUserManager)
+        user = manager.get_user('a...@example.org')
+        address = list(user.addresses)[0]
+        self.assertEqual(address.email, 'a...@example.org')
+        address = manager.get_address('a...@example.org')
+        self.assertEqual(address.email, 'a...@example.org')
+        items = get_queue_messages('virgin', expected_count=1)
+        self.assertEqual(items[0].msgdata['recipients'],
+                         set(['a...@example.org']))
+        self.assertIn(mail_content, str(items[0].msg))
+
     def test_confirm_with_folded_to_header(self):
         # Test that a folded To: header is properly parsed.
         msg = mfs("""\



View it on GitLab: 
https://gitlab.com/mailman/mailman/-/compare/af3570376f3e691e70a2a7be656edac8ad288289...b87ca1217402e70d0eceb499c7db97540f746b9e

-- 
View it on GitLab: 
https://gitlab.com/mailman/mailman/-/compare/af3570376f3e691e70a2a7be656edac8ad288289...b87ca1217402e70d0eceb499c7db97540f746b9e
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

Reply via email to