launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #07116
[Merge] lp:~mbp/launchpad/893612-mail-too-big into lp:launchpad
Martin Pool has proposed merging lp:~mbp/launchpad/893612-mail-too-big into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #893612 in Launchpad itself: "Email too big message not helpful"
https://bugs.launchpad.net/launchpad/+bug/893612
For more details, see:
https://code.launchpad.net/~mbp/launchpad/893612-mail-too-big/+merge/101865
At the moment, if you send an >10MB message to Launchpad, it records an oops, and sends a message back to the user saying there was an oops.
This happens fairly late in processing, while running the handler.
This patch changes it so we do an up-front check as early as is easy, and give the user a regular error notification. This ought to eliminate one stream of oopses (I don't know if it's very common.)
There's a unit test and I also tried running a message through process-one-mail. I also confirmed the bug's still live on lp.
--
https://code.launchpad.net/~mbp/launchpad/893612-mail-too-big/+merge/101865
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~mbp/launchpad/893612-mail-too-big into lp:launchpad.
=== modified file 'lib/lp/services/mail/incoming.py'
--- lib/lp/services/mail/incoming.py 2012-01-04 03:23:19 +0000
+++ lib/lp/services/mail/incoming.py 2012-04-13 07:12:21 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Functions dealing with mails coming into Launchpad."""
@@ -45,6 +45,7 @@
from lp.services.mail.notification import send_process_error_notification
from lp.services.mail.sendmail import do_paranoid_envelope_to_validation
from lp.services.mail.signedmessage import signed_message_from_string
+from lp.services.messages.model.message import MAX_EMAIL_SIZE
from lp.services.webapp.errorlog import (
ErrorReportingUtility,
ScriptRequest,
@@ -461,6 +462,22 @@
log.info("Got a message with a precedence header.")
return
+ if mail.raw_length > MAX_EMAIL_SIZE:
+ complaint = (
+ "The mail you sent to Launchpad is too long.\n\n"
+ "Your message <%s>\nwas %d MB and the limit is %d MB." %
+ (mail['message-id'], mail.raw_length / 1e6, MAX_EMAIL_SIZE / 1e6))
+ log.info(complaint)
+ # It's probably big and it's probably mostly binary, so trim it pretty
+ # aggressively.
+ send_process_error_notification(
+ mail['From'],
+ 'Mail to Launchpad was too large',
+ complaint,
+ mail,
+ max_return_size=8192)
+ return
+
try:
principal = authenticateEmail(
mail, signature_timestamp_checker)
=== modified file 'lib/lp/services/mail/signedmessage.py'
--- lib/lp/services/mail/signedmessage.py 2011-08-12 14:36:25 +0000
+++ lib/lp/services/mail/signedmessage.py 2012-04-13 07:12:21 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
"""Classes for simpler handling of PGP signed email messages."""
@@ -153,6 +153,11 @@
signature, signed_content = self._getSignatureAndSignedContent()
return signature
+ @property
+ def raw_length(self):
+ """Return the length in bytes of the underlying raw form."""
+ return len(self.parsed_string)
+
def strip_pgp_signature(text):
"""Strip any PGP signature from the supplied text."""
=== modified file 'lib/lp/services/mail/tests/test_incoming.py'
--- lib/lp/services/mail/tests/test_incoming.py 2012-01-20 15:42:44 +0000
+++ lib/lp/services/mail/tests/test_incoming.py 2012-04-13 07:12:21 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
from doctest import DocTestSuite
@@ -69,6 +69,32 @@
"(7, 58, u'No data')",
body)
+ def test_mail_too_big(self):
+ """Much-too-big mail should generate a bounce, not an OOPS.
+
+ See <https://bugs.launchpad.net/launchpad/+bug/893612>.
+ """
+ person = self.factory.makePerson()
+ transaction.commit()
+ email_address = person.preferredemail.email
+ fat_body = '\n'.join(
+ ['some big mail with this line repeated many many times\n']
+ * 1000000)
+ ctrl = MailController(
+ email_address, 'to@xxxxxxxxxxx', 'subject', fat_body,
+ bulk=False)
+ ctrl.send()
+ handleMail()
+ self.assertEqual([], self.oopses)
+ [notification] = pop_notifications()
+ body = notification.get_payload()[0].get_payload(decode=True)
+ self.assertIn(
+ "The mail you sent to Launchpad is too long.",
+ body)
+ self.assertIn(
+ "was 55 MB\nand the limit is 10 MB.",
+ body)
+
def test_invalid_to_addresses(self):
"""Invalid To: header should not be handled as an OOPS."""
raw_mail = open(os.path.join(
=== modified file 'lib/lp/services/messages/model/message.py'
--- lib/lp/services/messages/model/message.py 2012-01-06 15:07:17 +0000
+++ lib/lp/services/messages/model/message.py 2012-04-13 07:12:21 +0000
@@ -1,4 +1,4 @@
-# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
+# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
# GNU Affero General Public License version 3 (see the file LICENSE).
# pylint: disable-msg=E0611,W0212
@@ -6,6 +6,7 @@
__metaclass__ = type
__all__ = [
'DirectEmailAuthorization',
+ 'MAX_EMAIL_SIZE',
'Message',
'MessageChunk',
'MessageJob',
@@ -310,7 +311,10 @@
if not rfc822msgid:
raise InvalidEmailMessage('Missing Message-Id')
- # make sure we don't process anything too long
+ # Make sure we don't process anything too long. Large messages should
+ # normally be rejected at the handle_one_mail level, which gives a
+ # nice message back to the user, but we check again here in case there
+ # are other paths.
if len(email_message) > MAX_EMAIL_SIZE:
raise InvalidEmailMessage('Msg %s size %d exceeds limit %d' % (
rfc822msgid, len(email_message), MAX_EMAIL_SIZE))