Barry Warsaw pushed to branch master at mailman / Mailman
Commits: 5a02cc71 by Abhilash Raj at 2016-11-25T11:45:06-05:00 Return 'defective message' for a bad held message If a message can't be parsed by Python due to bad structure, don't raise an error but return a generic 'this message is defective' string instead. - - - - - 1f4919ab by Abhilash Raj at 2016-11-25T11:45:06-05:00 Rename test email and use resource filename instead of __file__. - - - - - 17ec3681 by Barry Warsaw at 2016-11-25T11:54:10-05:00 Add NEWS and a little bit of cleanup. - - - - - 5 changed files: - src/mailman/docs/NEWS.rst - src/mailman/rest/post_moderation.py - + src/mailman/rest/tests/data/__init__.py - + src/mailman/rest/tests/data/bad_email.eml - src/mailman/rest/tests/test_moderation.py Changes: ===================================== src/mailman/docs/NEWS.rst ===================================== --- a/src/mailman/docs/NEWS.rst +++ b/src/mailman/docs/NEWS.rst @@ -101,6 +101,8 @@ Bugs addresses. Given by Tom Briles. (Closes: #68) * Transmit the moderation reason and expose it in the REST API as the ``reason`` attribute. Given by Aurélien Bompard. + * Don't return a 500 error from the REST API when trying to handle a held + message with defective content. Given by Abhilash Raj. (Closes: #256) Configuration ------------- ===================================== src/mailman/rest/post_moderation.py ===================================== --- a/src/mailman/rest/post_moderation.py +++ b/src/mailman/rest/post_moderation.py @@ -71,7 +71,14 @@ class _HeldMessageBase(_ModerationBase): # resource. XXX See LP: #967954 key = resource.pop('key') msg = getUtility(IMessageStore).get_message_by_id(key) - resource['msg'] = msg.as_string() + try: + resource['msg'] = msg.as_string() + except KeyError: + # If the message can't be parsed, return a generic message instead + # of raising an error. + # + # See http://bugs.python.org/issue27321 and GL#256 + resource['msg'] = 'This message is defective' # Some of the _mod_* keys we want to rename and place into the JSON # resource. Others we can drop. Since we're mutating the dictionary, # we need to make a copy of the keys. When you port this to Python 3, ===================================== src/mailman/rest/tests/data/__init__.py ===================================== --- /dev/null +++ b/src/mailman/rest/tests/data/__init__.py ===================================== src/mailman/rest/tests/data/bad_email.eml ===================================== --- /dev/null +++ b/src/mailman/rest/tests/data/bad_email.eml @@ -0,0 +1,8 @@ +To: <t...@example.com> +Subject: =?koi8-r?B?UF9AX/NfQ1/5X+xfS1/p?= +From: =?koi8-r?B?8sXL0sXB1MnXzs/FIMHHxc7U09TXzw==?= +Content-Type: text/plain; charset=koi8-r +Message-Id: <20160614102505.9OFQ19L1C> + + ? + ? ===================================== src/mailman/rest/tests/test_moderation.py ===================================== --- a/src/mailman/rest/tests/test_moderation.py +++ b/src/mailman/rest/tests/test_moderation.py @@ -17,8 +17,10 @@ """REST moderation tests.""" +import os import unittest +from email import message_from_binary_file from mailman.app.lifecycle import create_list from mailman.app.moderator import hold_message from mailman.database.transaction import transaction @@ -31,6 +33,7 @@ from mailman.testing.helpers import ( call_api, get_queue_messages, set_preferred, specialized_message_from_string as mfs) from mailman.testing.layers import RESTLayer +from pkg_resources import resource_filename from urllib.error import HTTPError from zope.component import getUtility @@ -206,6 +209,24 @@ class TestSubscriptionModeration(unittest.TestCase): emails = set(json['email'] for json in content['entries']) self.assertEqual(emails, {'a...@example.com', 'b...@example.com'}) + def test_view_malformed_held_message(self): + # Opening a bad (i.e. bad structure) email and holding it. + email_path = resource_filename( + 'mailman.rest.tests.data', 'bad_email.eml') + with open(email_path, 'rb') as fp: + msg = message_from_binary_file(fp) + msg.sender = 'aper...@example.com' + with transaction(): + hold_message(self._mlist, msg) + # Now trying to access held messages from REST API should not give + # 500 server error if one of the messages can't be parsed properly. + content, response = call_api( + 'http://localhost:9001/3.0/lists/a...@example.com/held') + self.assertEqual(response.status, 200) + self.assertEqual(len(content['entries']), 1) + self.assertEqual(content['entries'][0]['msg'], + 'This message is defective') + def test_individual_request(self): # We can view an individual request. with transaction(): View it on GitLab: https://gitlab.com/mailman/mailman/compare/055082f2694c84d5dd46ba194224b1b9f51f835f...17ec368191f4e2c80fbead954511bb5a251dfe45
_______________________________________________ Mailman-checkins mailing list Mailman-checkins@python.org Unsubscribe: https://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org