Merge lp:~matsubara/launchpad/bug-504124-oops-handling-email into lp:launchpad

Proposed by Diogo Matsubara
Status: Merged
Approved by: Graham Binns
Approved revision: no longer in the source branch.
Merged at revision: 10937
Proposed branch: lp:~matsubara/launchpad/bug-504124-oops-handling-email
Merge into: lp:launchpad
Diff against target: 115 lines (+54/-0)
4 files modified
lib/canonical/launchpad/mail/ftests/emails/invalid-to-header.txt (+23/-0)
lib/canonical/launchpad/mail/incoming.py (+9/-0)
lib/canonical/launchpad/mail/tests/test_incoming.py (+21/-0)
lib/lp/services/mail/sendmail.py (+1/-0)
To merge this branch: bzr merge lp:~matsubara/launchpad/bug-504124-oops-handling-email
Reviewer Review Type Date Requested Status
Curtis Hovey (community) rc Approve
Graham Binns (community) code Approve
Review via email: mp+26457@code.launchpad.net

Description of the change

This branch fixes bug 504124 by using do_paranoid_envelope_to_validation() function to assert the parsed email addresses from the email message are sane. In case the addresses are not sane (i.e. spam), email is deleted from the mailbox and an OOPS is not logged. This fixes the top OOPS report from lpnet OOPS summary.

= Tests =

bin/test test_incoming

To post a comment you must log in.
Revision history for this message
Graham Binns (gmb) :
review: Approve (code)
Revision history for this message
Curtis Hovey (sinzui) wrote :

Thanks for providing this fix. You have my RC to land this branch into db-devel. We will use your revision as the release branch.

review: Approve (rc)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'lib/canonical/launchpad/mail/ftests/emails/invalid-to-header.txt'
2--- lib/canonical/launchpad/mail/ftests/emails/invalid-to-header.txt 1970-01-01 00:00:00 +0000
3+++ lib/canonical/launchpad/mail/ftests/emails/invalid-to-header.txt 2010-06-01 01:38:34 +0000
4@@ -0,0 +1,23 @@
5+From: "Fonti Hanna" <manager@cinemahollywood.com>
6+To: <<35845@bugs.launchpad.net>,
7+ <380449@bugs.launchpad.net>,
8+ <377016@bugs.launchpad.net>,
9+ <302452@bugs.launchpad.net>,
10+ <244148@bugs.launchpad.net>,
11+ <323848@bugs.launchpad.net>,
12+ <322385@bugs.launchpad.net>,
13+ <469470@bugs.launchpad.net>,
14+ <407133@bugs.launchpad.net>>
15+Subject: (no subject)
16+Date: Sat, 29 May 2010 10:13:18 +0800
17+Message-ID: <01caff17$8ee25a10$b28c2872@manager>
18+MIME-Version: 1.0
19+Content-Type: multipart/alternative;
20+ boundary="----=_NextPart_000_000E_01CAFF17.8EE25A10"
21+X-Priority: 3 (Normal)
22+X-MSMail-Priority: Normal
23+X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0)
24+X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2670
25+Importance: Normal
26+
27+Some spam with invalid To: header.
28
29=== modified file 'lib/canonical/launchpad/mail/incoming.py'
30--- lib/canonical/launchpad/mail/incoming.py 2010-03-12 12:20:35 +0000
31+++ lib/canonical/launchpad/mail/incoming.py 2010-06-01 01:38:34 +0000
32@@ -29,6 +29,7 @@
33 from canonical.launchpad.webapp.interaction import setupInteraction
34 from canonical.launchpad.mail.commands import get_error_message
35 from canonical.launchpad.mail.handlers import mail_handlers
36+from lp.services.mail.sendmail import do_paranoid_envelope_to_validation
37 from lp.services.mail.signedmessage import signed_message_from_string
38 from canonical.launchpad.mailnotification import (
39 send_process_error_notification)
40@@ -273,6 +274,14 @@
41 names_addresses = getaddresses(to + cc)
42 addresses = [addr for name, addr in names_addresses]
43
44+ try:
45+ do_paranoid_envelope_to_validation(addresses)
46+ except AssertionError, e:
47+ _handle_error(
48+ "Invalid email address: %s" % e,
49+ file_alias_url, notify=False)
50+ continue
51+
52 handler = None
53 for email_addr in addresses:
54 user, domain = email_addr.split('@')
55
56=== modified file 'lib/canonical/launchpad/mail/tests/test_incoming.py'
57--- lib/canonical/launchpad/mail/tests/test_incoming.py 2010-04-12 06:21:37 +0000
58+++ lib/canonical/launchpad/mail/tests/test_incoming.py 2010-06-01 01:38:34 +0000
59@@ -1,16 +1,19 @@
60 # Copyright 2009 Canonical Ltd. This software is licensed under the
61 # GNU Affero General Public License version 3 (see the file LICENSE).
62
63+import os
64 import unittest
65
66 import transaction
67 from zope.testing.doctest import DocTestSuite
68
69+from canonical.launchpad.mail.ftests.helpers import testmails_path
70 from canonical.launchpad.mail.incoming import handleMail, MailErrorUtility
71 from canonical.testing import LaunchpadZopelessLayer
72 from lp.testing import TestCaseWithFactory
73 from lp.testing.mail_helpers import pop_notifications
74 from lp.services.mail.sendmail import MailController
75+from lp.services.mail.stub import TestMailer
76
77
78 class TestIncoming(TestCaseWithFactory):
79@@ -52,6 +55,24 @@
80 "Error message:\n\nSignature couldn't be verified: No data",
81 body)
82
83+ def test_invalid_to_addresses(self):
84+ """Invalid To: header should not be handled as an OOPS."""
85+ raw_mail = open(os.path.join(
86+ testmails_path, 'invalid-to-header.txt')).read()
87+ # Due to the way handleMail works, even if we pass a valid To header
88+ # to the TestMailer, as we're doing here, it falls back to parse all
89+ # To and CC headers from the raw_mail. Also, TestMailer is used here
90+ # because MailController won't send an email with a broken To: header.
91+ TestMailer().send("from@example.com", "to@example.com", raw_mail)
92+ error_utility = MailErrorUtility()
93+ old_oops = error_utility.getLastOopsReport()
94+ handleMail()
95+ current_oops = error_utility.getLastOopsReport()
96+ if old_oops is None:
97+ self.assertIs(None, current_oops)
98+ else:
99+ self.assertEqual(old_oops.id, current_oops.id)
100+
101
102 def test_suite():
103 suite = unittest.TestSuite()
104
105=== modified file 'lib/lp/services/mail/sendmail.py'
106--- lib/lp/services/mail/sendmail.py 2010-04-30 15:45:43 +0000
107+++ lib/lp/services/mail/sendmail.py 2010-06-01 01:38:34 +0000
108@@ -16,6 +16,7 @@
109
110 __all__ = [
111 'append_footer',
112+ 'do_paranoid_envelope_to_validation',
113 'format_address',
114 'format_address_for_person',
115 'get_msgid',