summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mailman/docs/NEWS.rst2
-rw-r--r--src/mailman/rest/post_moderation.py2
-rw-r--r--src/mailman/rest/tests/test_moderation.py19
3 files changed, 22 insertions, 1 deletions
diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst
index 328699371..a5e819c7a 100644
--- a/src/mailman/docs/NEWS.rst
+++ b/src/mailman/docs/NEWS.rst
@@ -24,6 +24,8 @@ Bugs
* Various message holds and rejects that gave 'N/A' as a reason now give an
appropriate reason. (Closes #368)
* Bounce messages are now composed for proper translations.
+* Messages with badly encoded ``Subject`` headers no longer crash the message
+ moderation REST API. (Closes #383)
Command line
------------
diff --git a/src/mailman/rest/post_moderation.py b/src/mailman/rest/post_moderation.py
index a747917de..b972bed53 100644
--- a/src/mailman/rest/post_moderation.py
+++ b/src/mailman/rest/post_moderation.py
@@ -95,7 +95,7 @@ class _HeldMessageBase(_ModerationBase):
# Store the original header and then try decoding it.
resource['original_subject'] = resource['subject']
# If we can't decode the header, leave the subject unchanged.
- with suppress(LookupError, MessageError):
+ with suppress(LookupError, MessageError, UnicodeDecodeError):
resource['subject'] = str(
make_header(decode_header(resource['subject'])))
# Also, held message resources will always be this type, so ignore
diff --git a/src/mailman/rest/tests/test_moderation.py b/src/mailman/rest/tests/test_moderation.py
index 0a9bb2608..4f6894ebb 100644
--- a/src/mailman/rest/tests/test_moderation.py
+++ b/src/mailman/rest/tests/test_moderation.py
@@ -144,6 +144,25 @@ Something else.
dict(action='discard'))
self.assertEqual(cm.exception.code, 404)
+ def test_subject_encoding_error(self):
+ # GL#383: messages with badly encoded Subject headers crash the REST
+ # server.
+ self._msg = mfs("""\
+From: anne@example.com
+To: ant@example.com
+Subject: =?GB2312?B?saa9o7fmtNPEpbVaQ2h1o6zDt7uoz+PX1L/guq7AtKGj?=
+Message-ID: <alpha>
+
+Something else.
+""")
+ with transaction():
+ held_id = hold_message(self._mlist, self._msg)
+ json, response = call_api(
+ 'http://localhost:9001/3.0/lists/ant@example.com/held')
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(json['total_size'], 1)
+ self.assertEqual(json['entries'][0]['request_id'], held_id)
+
class TestSubscriptionModeration(unittest.TestCase):
layer = RESTLayer