Merge lp:~gary/launchpad/bug650343-2 into lp:launchpad

Proposed by Gary Poster
Status: Merged
Approved by: Leonard Richardson
Approved revision: no longer in the source branch.
Merged at revision: 11705
Proposed branch: lp:~gary/launchpad/bug650343-2
Merge into: lp:launchpad
Prerequisite: lp:~gary/launchpad/bug650343
Diff against target: 666 lines (+133/-125)
10 files modified
cronscripts/process-mail.py (+2/-1)
lib/canonical/launchpad/doc/emailauthentication.txt (+7/-4)
lib/canonical/launchpad/ftests/test_system_documentation.py (+55/-77)
lib/canonical/launchpad/mail/handlers.py (+1/-1)
lib/lp/blueprints/doc/spec-mail-exploder.txt (+1/-1)
lib/lp/services/mail/incoming.py (+2/-2)
lib/lp/services/mail/tests/incomingmail.txt (+6/-6)
lib/lp/services/mail/tests/test_dkim.py (+31/-26)
lib/lp/services/mail/tests/test_incoming.py (+24/-2)
lib/lp/services/mail/tests/test_signedmessage.py (+4/-5)
To merge this branch: bzr merge lp:~gary/launchpad/bug650343-2
Reviewer Review Type Date Requested Status
Leonard Richardson (community) Approve
Review via email: mp+38224@code.launchpad.net

Commit message

Add X-Launchpad-Original-To to recipient lists; move some related files from c/l/mail to lp/services/mail.

Description of the change

In the reviews for https://code.edge.launchpad.net/~gary/launchpad/bug650343/+merge/37633 , I was asked to move the "incoming"-related files I touched over to lp/services/mail. This branch performs that move, and does the various changes that make lint then requests.

While we're speaking of lint, here's the output.

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  cronscripts/process-mail.py
  lib/canonical/launchpad/doc/emailauthentication.txt
  lib/canonical/launchpad/ftests/test_system_documentation.py
  lib/canonical/launchpad/mail/handlers.py
  lib/lp/blueprints/doc/spec-mail-exploder.txt
  lib/lp/services/mail/incoming.py
  lib/lp/services/mail/tests/incomingmail.txt
  lib/lp/services/mail/tests/test_dkim.py
  lib/lp/services/mail/tests/test_incoming.py
  lib/lp/services/mail/tests/test_signedmessage.py

./cronscripts/process-mail.py
       9: '_pythonpath' imported but unused
./lib/canonical/launchpad/doc/emailauthentication.txt
     155: want exceeds 78 characters.

The ./cronscripts/process-mail.py request is because of our weird _pythonpath dance (maybe we should make these all buildout-generated scripts someday...or not). Anyway, it's not pertinent.

The request for ./lib/canonical/launchpad/doc/emailauthentication.txt appears to not be appropriate: the test explicitly turns off whitespace normalization there, so I think the long line is intended.

Tests passed on ec2 with the current branch, except for a Windmill error that appears to be spurious.

Other than that, the only thing I know to mention is that I did not move the files I touched for this move (lib/canonical/launchpad/doc/emailauthentication.txt lib/canonical/launchpad/ftests/test_system_documentation.py lib/canonical/launchpad/mail/handlers.py). Hopefully the move request does not have to cascade like that, or I may be at this for awhile. :-)

Thank you.

To post a comment you must log in.
Revision history for this message
Leonard Richardson (leonardr) wrote :

Good progress. Approved with minor changes discussed on IRC: reword "no signature is treated" and fix "message message" typo.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cronscripts/process-mail.py'
2--- cronscripts/process-mail.py 2010-10-03 15:30:06 +0000
3+++ cronscripts/process-mail.py 2010-10-14 20:59:59 +0000
4@@ -13,7 +13,7 @@
5 from canonical.config import config
6 from lp.services.scripts.base import (
7 LaunchpadCronScript, LaunchpadScriptFailure)
8-from canonical.launchpad.mail.incoming import handleMail
9+from lp.services.mail.incoming import handleMail
10 from canonical.launchpad.interfaces import IMailBox
11
12
13@@ -21,6 +21,7 @@
14 usage = """%prog [options]
15
16 """ + __doc__
17+
18 def main(self):
19 try:
20 handleMail(self.txn)
21
22=== modified file 'lib/canonical/launchpad/doc/emailauthentication.txt'
23--- lib/canonical/launchpad/doc/emailauthentication.txt 2010-10-04 19:50:45 +0000
24+++ lib/canonical/launchpad/doc/emailauthentication.txt 2010-10-14 20:59:59 +0000
25@@ -1,9 +1,10 @@
26-= Authentication of Emails =
27+Authentication of Emails
28+========================
29
30 When an email arrives in Launchpad the user who sent it needs to be
31 authenticated. This is done by authenticateEmail:
32
33- >>> from canonical.launchpad.mail.incoming import authenticateEmail
34+ >>> from lp.services.mail.incoming import authenticateEmail
35
36 The only way of authenticating the user is by looking at the OpenPGP
37 signature. First we have to import the OpenPGP keys we will use in the
38@@ -159,7 +160,8 @@
39 Sample Person
40
41
42-== IWeaklyAuthenticatedPrinipal ==
43+IWeaklyAuthenticatedPrincipal
44+-----------------------------
45
46 It's a huge difference to signing an email with a key that is associated
47 with the authenticated Person, and signing it with a key that isn't
48@@ -172,7 +174,8 @@
49
50 An unsigned email:
51
52- >>> from canonical.launchpad.interfaces import IWeaklyAuthenticatedPrincipal
53+ >>> from canonical.launchpad.interfaces import (
54+ ... IWeaklyAuthenticatedPrincipal)
55 >>> msg = read_test_message('unsigned_multipart.txt')
56 >>> principal = authenticateEmail(msg)
57 >>> IWeaklyAuthenticatedPrincipal.providedBy(principal)
58
59=== modified file 'lib/canonical/launchpad/ftests/test_system_documentation.py'
60--- lib/canonical/launchpad/ftests/test_system_documentation.py 2010-10-03 15:30:06 +0000
61+++ lib/canonical/launchpad/ftests/test_system_documentation.py 2010-10-14 20:59:59 +0000
62@@ -52,6 +52,7 @@
63
64 here = os.path.dirname(os.path.realpath(__file__))
65
66+
67 def lobotomize_stevea():
68 """Set SteveA's email address' status to NEW.
69
70@@ -79,17 +80,20 @@
71 LaunchpadZopelessLayer.switchDbUser('poexport')
72 setUp(test)
73
74+
75 def poExportTearDown(test):
76 """Tear down the PO export script tests."""
77 # XXX sinzui 2007-11-14:
78 # This function is not needed. The test should be switched to tearDown.
79 tearDown(test)
80
81+
82 def uploaderSetUp(test):
83 """setup the package uploader script tests."""
84 setUp(test)
85 LaunchpadZopelessLayer.switchDbUser('uploader')
86
87+
88 def uploaderTearDown(test):
89 """Tear down the package uploader script tests."""
90 # XXX sinzui 2007-11-14:
91@@ -115,6 +119,7 @@
92 # This function is not needed. The test should be switched to tearDown.
93 tearDown(test)
94
95+
96 def uploadQueueSetUp(test):
97 lobotomize_stevea()
98 test_dbuser = config.uploadqueue.dbuser
99@@ -127,6 +132,7 @@
100 """Clean up any Zope registrations."""
101 cleanUp()
102
103+
104 def _createUbuntuBugTaskLinkedToQuestion():
105 """Get the id of an Ubuntu bugtask linked to a question.
106
107@@ -154,10 +160,13 @@
108 pop_notifications()
109 return ubuntu_bugtask.id
110
111+
112 def bugLinkedToQuestionSetUp(test):
113 """Setup the question and linked bug for testing."""
114+
115 def get_bugtask_linked_to_question():
116 return getUtility(IBugTaskSet).get(bugtask_id)
117+
118 setUp(test)
119 bugtask_id = _createUbuntuBugTaskLinkedToQuestion()
120 test.globs['get_bugtask_linked_to_question'] = (
121@@ -166,6 +175,7 @@
122 # interaction in the test.
123 login('no-priv@canonical.com')
124
125+
126 def uploaderBugLinkedToQuestionSetUp(test):
127 LaunchpadZopelessLayer.switchDbUser('launchpad')
128 bugLinkedToQuestionSetUp(test)
129@@ -173,6 +183,7 @@
130 uploaderSetUp(test)
131 login(ANONYMOUS)
132
133+
134 def uploadQueueBugLinkedToQuestionSetUp(test):
135 LaunchpadZopelessLayer.switchDbUser('launchpad')
136 bugLinkedToQuestionSetUp(test)
137@@ -185,8 +196,7 @@
138 special = {
139 # No setup or teardown at all, since it is demonstrating these features.
140 'old-testing.txt': LayeredDocFileSuite(
141- '../doc/old-testing.txt', layer=FunctionalLayer
142- ),
143+ '../doc/old-testing.txt', layer=FunctionalLayer),
144
145 'autodecorate.txt':
146 LayeredDocFileSuite('../doc/autodecorate.txt', layer=BaseLayer),
147@@ -194,84 +204,70 @@
148
149 # And this test want minimal environment too.
150 'package-relationship.txt': LayeredDocFileSuite(
151- '../doc/package-relationship.txt',
152- stdout_logging=False, layer=None
153- ),
154+ '../doc/package-relationship.txt',
155+ stdout_logging=False, layer=None),
156
157 'webservice-configuration.txt': LayeredDocFileSuite(
158- '../doc/webservice-configuration.txt',
159- setUp=setGlobs, tearDown=layerlessTearDown, layer=None
160- ),
161+ '../doc/webservice-configuration.txt',
162+ setUp=setGlobs, tearDown=layerlessTearDown, layer=None),
163
164
165 # POExport stuff is Zopeless and connects as a different database user.
166 # poexport-distroseries-(date-)tarball.txt is excluded, since they add
167 # data to the database as well.
168 'message.txt': LayeredDocFileSuite(
169- '../doc/message.txt',
170- setUp=setUp, tearDown=tearDown, layer=LaunchpadFunctionalLayer
171- ),
172+ '../doc/message.txt',
173+ setUp=setUp, tearDown=tearDown, layer=LaunchpadFunctionalLayer),
174 'close-account.txt': LayeredDocFileSuite(
175- '../doc/close-account.txt', setUp=setUp, tearDown=tearDown,
176- layer=LaunchpadZopelessLayer
177- ),
178+ '../doc/close-account.txt', setUp=setUp, tearDown=tearDown,
179+ layer=LaunchpadZopelessLayer),
180 'launchpadform.txt': LayeredDocFileSuite(
181- '../doc/launchpadform.txt',
182- setUp=setUp, tearDown=tearDown,
183- layer=LaunchpadFunctionalLayer
184- ),
185+ '../doc/launchpadform.txt',
186+ setUp=setUp, tearDown=tearDown,
187+ layer=LaunchpadFunctionalLayer),
188 'launchpadformharness.txt': LayeredDocFileSuite(
189- '../doc/launchpadformharness.txt',
190- setUp=setUp, tearDown=tearDown,
191- layer=LaunchpadFunctionalLayer
192- ),
193+ '../doc/launchpadformharness.txt',
194+ setUp=setUp, tearDown=tearDown,
195+ layer=LaunchpadFunctionalLayer),
196 'uri.txt': LayeredDocFileSuite(
197- '../doc/uri.txt',
198- setUp=setUp, tearDown=tearDown,
199- layer=FunctionalLayer
200- ),
201+ '../doc/uri.txt',
202+ setUp=setUp, tearDown=tearDown,
203+ layer=FunctionalLayer),
204 'notification-text-escape.txt': LayeredDocFileSuite(
205- '../doc/notification-text-escape.txt',
206- setUp=test_notifications.setUp,
207- tearDown=test_notifications.tearDown,
208- stdout_logging=False, layer=None
209- ),
210+ '../doc/notification-text-escape.txt',
211+ setUp=test_notifications.setUp,
212+ tearDown=test_notifications.tearDown,
213+ stdout_logging=False, layer=None),
214 # This test is actually run twice to prove that the AppServerLayer
215 # properly isolates the database between tests.
216 'launchpadlib.txt': LayeredDocFileSuite(
217 '../doc/launchpadlib.txt',
218 layer=AppServerLayer,
219- setUp=browser.setUp, tearDown=browser.tearDown,
220- ),
221+ setUp=browser.setUp, tearDown=browser.tearDown,),
222 'launchpadlib2.txt': LayeredDocFileSuite(
223 '../doc/launchpadlib.txt',
224 layer=AppServerLayer,
225- setUp=browser.setUp, tearDown=browser.tearDown,
226- ),
227+ setUp=browser.setUp, tearDown=browser.tearDown,),
228 # XXX gary 2008-12-08 bug=306246 bug=305858: Disabled test because of
229 # multiple spurious problems with layer and test.
230 # 'google-service-stub.txt': LayeredDocFileSuite(
231- # '../doc/google-service-stub.txt',
232- # layer=GoogleServiceLayer,
233- # ),
234+ # '../doc/google-service-stub.txt',
235+ # layer=GoogleServiceLayer,),
236 'canonical_url.txt': LayeredDocFileSuite(
237- '../doc/canonical_url.txt',
238- setUp=setUp,
239- tearDown=tearDown,
240- layer=FunctionalLayer,
241- ),
242+ '../doc/canonical_url.txt',
243+ setUp=setUp,
244+ tearDown=tearDown,
245+ layer=FunctionalLayer,),
246 'google-searchservice.txt': LayeredDocFileSuite(
247- '../doc/google-searchservice.txt',
248- setUp=setUp, tearDown=tearDown,
249- layer=GoogleLaunchpadFunctionalLayer,
250- ),
251+ '../doc/google-searchservice.txt',
252+ setUp=setUp, tearDown=tearDown,
253+ layer=GoogleLaunchpadFunctionalLayer,),
254 }
255
256
257 class ProcessMailLayer(LaunchpadZopelessLayer):
258 """Layer containing the tests running inside process-mail.py."""
259
260-
261 @classmethod
262 def testSetUp(cls):
263 """Fixture replicating the process-mail.py environment.
264@@ -287,7 +283,7 @@
265 """Tear down the test fixture."""
266 setSecurityPolicy(cls._old_policy)
267
268- doctests_without_logging = [
269+ doctests = [
270 # XXX gary 2008-12-06 bug=305856: Spurious test failure
271 # discovered on buildbot, build 40. Note that, to completely
272 # disable the test from running, the filename has been changed
273@@ -299,21 +295,16 @@
274 '../doc/emailauthentication.txt',
275 ]
276
277- doctests_with_logging = [
278- '../doc/incomingmail.txt',
279- ]
280-
281 @classmethod
282 def addTestsToSpecial(cls):
283 """Adds all the tests related to process-mail.py to special"""
284- for filepath in cls.doctests_without_logging:
285- filename = os.path.basename(filepath)
286- special[filename] = cls.createLayeredDocFileSuite(filepath)
287-
288- for filepath in cls.doctests_with_logging:
289- filename = os.path.basename(filepath)
290- special[filename] = cls.createLayeredDocFileSuite(
291- filepath, stdout_logging=True)
292+ for filepath in cls.doctests:
293+ filename = os.path.basename(filepath)
294+ special[filename] = LayeredDocFileSuite(
295+ filepath,
296+ setUp=setUp, tearDown=tearDown,
297+ layer=cls,
298+ stdout_logging=False)
299
300 # Adds a copy of some bug doctests that will be run with
301 # the processmail user.
302@@ -337,16 +328,6 @@
303 layer=cls,
304 stdout_logging=False)
305
306- @classmethod
307- def createLayeredDocFileSuite(cls, filename, stdout_logging=False):
308- """Helper to create a doctest using this layer."""
309- return LayeredDocFileSuite(
310- filename,
311- setUp=setUp, tearDown=tearDown,
312- layer=cls,
313- stdout_logging=stdout_logging,
314- stdout_logging_level=logging.WARNING)
315-
316
317 ProcessMailLayer.addTestsToSpecial()
318
319@@ -360,15 +341,13 @@
320 suite.addTest(special_suite)
321
322 testsdir = os.path.abspath(
323- os.path.normpath(os.path.join(here, '..', 'doc'))
324- )
325+ os.path.normpath(os.path.join(here, '..', 'doc')))
326
327 # Add tests using default setup/teardown
328 filenames = [filename
329 for filename in os.listdir(testsdir)
330 if filename.lower().endswith('.txt')
331- and filename not in special
332- ]
333+ and filename not in special]
334 # Sort the list to give a predictable order. We do this because when
335 # tests interfere with each other, the varying orderings that os.listdir
336 # gives on different people's systems make reproducing and debugging
337@@ -383,8 +362,7 @@
338 layer=LaunchpadFunctionalLayer,
339 # 'icky way of running doctests with __future__ imports
340 globs={'with_statement': with_statement},
341- stdout_logging_level=logging.WARNING
342- )
343+ stdout_logging_level=logging.WARNING)
344 suite.addTest(one_test)
345
346 return suite
347
348=== modified file 'lib/canonical/launchpad/mail/handlers.py'
349--- lib/canonical/launchpad/mail/handlers.py 2010-10-03 15:30:06 +0000
350+++ lib/canonical/launchpad/mail/handlers.py 2010-10-14 20:59:59 +0000
351@@ -61,7 +61,7 @@
352
353 def extract_signature_timestamp(signed_msg):
354 # break import cycle
355- from canonical.launchpad.mail.incoming import (
356+ from lp.services.mail.incoming import (
357 canonicalise_line_endings)
358 signature = getUtility(IGPGHandler).getVerifiedSignature(
359 canonicalise_line_endings(signed_msg.signedContent),
360
361=== modified file 'lib/lp/blueprints/doc/spec-mail-exploder.txt'
362--- lib/lp/blueprints/doc/spec-mail-exploder.txt 2010-10-14 20:59:48 +0000
363+++ lib/lp/blueprints/doc/spec-mail-exploder.txt 2010-10-14 20:59:59 +0000
364@@ -269,7 +269,7 @@
365 >>> moin_change['Sender'] = 'webmaster@ubuntu.com'
366
367 >>> from lp.services.mail.sendmail import sendmail
368- >>> from canonical.launchpad.mail.incoming import handleMail
369+ >>> from lp.services.mail.incoming import handleMail
370 >>> sendmail(moin_change, bulk=False)
371 '...'
372
373
374=== renamed file 'lib/canonical/launchpad/mail/incoming.py' => 'lib/lp/services/mail/incoming.py'
375--- lib/canonical/launchpad/mail/incoming.py 2010-10-14 20:59:48 +0000
376+++ lib/lp/services/mail/incoming.py 2010-10-14 20:59:59 +0000
377@@ -325,7 +325,7 @@
378 mail = signed_message_from_string(raw_mail)
379 except email.Errors.MessageError, error:
380 mailbox.delete(mail_id)
381- log = logging.getLogger('canonical.launchpad.mail')
382+ log = logging.getLogger('lp.services.mail')
383 log.warn(
384 "Couldn't convert email to email.Message: %s" % (
385 file_alias_url, ),
386@@ -369,7 +369,7 @@
387 if 'X-Launchpad-Original-To' in mail:
388 addresses = [mail['X-Launchpad-Original-To']]
389 else:
390- log = logging.getLogger('canonical.launchpad.mail')
391+ log = logging.getLogger('lp.services.mail')
392 log.warn(
393 "No X-Launchpad-Original-To header was present "
394 "in email: %s" %
395
396=== renamed file 'lib/canonical/launchpad/doc/incomingmail.txt' => 'lib/lp/services/mail/tests/incomingmail.txt'
397--- lib/canonical/launchpad/doc/incomingmail.txt 2010-10-14 20:59:48 +0000
398+++ lib/lp/services/mail/tests/incomingmail.txt 2010-10-14 20:59:59 +0000
399@@ -4,7 +4,7 @@
400 When an email is sent to Launchpad we need to handle it somehow. This
401 is done by handleEmails:
402
403- >>> from canonical.launchpad.mail.incoming import handleMail
404+ >>> from lp.services.mail.incoming import handleMail
405
406 Basically what it does is to open the Launchpad mail box, and for each
407 message it:
408@@ -88,10 +88,10 @@
409 header is missing.)
410
411 >>> handleMail(zopeless_transaction)
412- WARNING:canonical.launchpad.mail:No X-Launchpad-Original-To header was present ...
413- WARNING:canonical.launchpad.mail:No X-Launchpad-Original-To header was present ...
414- WARNING:canonical.launchpad.mail:No X-Launchpad-Original-To header was present ...
415- WARNING:canonical.launchpad.mail:No X-Launchpad-Original-To header was present ...
416+ WARNING:lp.services.mail:No X-Launchpad-Original-To header was present ...
417+ WARNING:lp.services.mail:No X-Launchpad-Original-To header was present ...
418+ WARNING:lp.services.mail:No X-Launchpad-Original-To header was present ...
419+ WARNING:lp.services.mail:No X-Launchpad-Original-To header was present ...
420
421 Now we can see that each handler handled the emails sent to its domain:
422
423@@ -389,7 +389,7 @@
424 >>> len(stub.test_emails)
425 2
426
427- >>> handleMail(transaction)
428+ >>> handleMail(zopeless_transaction)
429 ERROR:...:Upload to Librarian failed...
430 ...
431 UploadFailed: ...Connection refused...
432
433=== modified file 'lib/lp/services/mail/tests/test_dkim.py'
434--- lib/lp/services/mail/tests/test_dkim.py 2010-08-20 20:31:18 +0000
435+++ lib/lp/services/mail/tests/test_dkim.py 2010-10-14 20:59:59 +0000
436@@ -11,14 +11,11 @@
437
438 import dkim
439 import dns.resolver
440-from zope.component import getUtility
441
442 from canonical.launchpad.interfaces.mail import IWeaklyAuthenticatedPrincipal
443-from canonical.launchpad.mail import (
444- incoming,
445- signed_message_from_string,
446- )
447-from canonical.launchpad.mail.incoming import authenticateEmail
448+from canonical.launchpad.mail import signed_message_from_string
449+from lp.services.mail import incoming
450+from lp.services.mail.incoming import authenticateEmail
451 from canonical.testing.layers import DatabaseFunctionalLayer
452 from lp.testing import TestCaseWithFactory
453
454@@ -77,33 +74,36 @@
455
456 def fake_signing(self, plain_message, canonicalize=None):
457 if canonicalize is None:
458- canonicalize = (dkim.Relaxed, dkim.Relaxed)
459+ canonicalize = (dkim.Relaxed, dkim.Relaxed)
460 dkim_line = dkim.sign(plain_message,
461- selector='example',
462+ selector='example',
463 domain='canonical.com',
464 privkey=sample_privkey,
465 debuglog=self._log_output,
466- canonicalize=canonicalize
467- )
468+ canonicalize=canonicalize)
469 assert dkim_line[-1] == '\n'
470 return dkim_line + plain_message
471
472 def monkeypatch_dns(self):
473 self._dns_responses = {}
474+
475 def my_lookup(name):
476 try:
477 return self._dns_responses[name]
478 except KeyError:
479 raise dns.resolver.NXDOMAIN()
480+
481 orig_dnstxt = dkim.dnstxt
482 dkim.dnstxt = my_lookup
483+
484 def restore():
485 dkim.dnstxt = orig_dnstxt
486+
487 self.addCleanup(restore)
488
489 def get_dkim_log(self):
490 return self._log_output.getvalue()
491-
492+
493 def assertStronglyAuthenticated(self, principal, signed_message):
494 if IWeaklyAuthenticatedPrincipal.providedBy(principal):
495 self.fail('expected strong authentication; got weak:\n'
496@@ -157,8 +157,10 @@
497 self._dns_responses['example._domainkey.canonical.com.'] = \
498 sample_dns
499 saved_domains = incoming._trusted_dkim_domains[:]
500+
501 def restore():
502 incoming._trusted_dkim_domains = saved_domains
503+
504 self.addCleanup(restore)
505 incoming._trusted_dkim_domains = []
506 principal = authenticateEmail(
507@@ -185,14 +187,15 @@
508 'steve.alexander@ubuntulinux.com')
509
510 def test_dkim_changed_from_address(self):
511- # if the address part of the message has changed, it's detected. we
512- # still treat this as weakly authenticated by the purported From-header
513- # sender, though perhaps in future we would prefer to reject these
514- # messages.
515+ # If the address part of the message has changed, it's detected.
516+ # We still treat this as weakly authenticated by the purported
517+ # From-header sender, though perhaps in future we would prefer
518+ # to reject these messages.
519 signed_message = self.fake_signing(plain_content)
520 self._dns_responses['example._domainkey.canonical.com.'] = \
521 sample_dns
522- fiddled_message = signed_message.replace('From: Foo Bar <foo.bar@canonical.com>',
523+ fiddled_message = signed_message.replace(
524+ 'From: Foo Bar <foo.bar@canonical.com>',
525 'From: Carlos <carlos@canonical.com>')
526 principal = authenticateEmail(
527 signed_message_from_string(fiddled_message))
528@@ -202,22 +205,23 @@
529 'carlos@canonical.com')
530
531 def test_dkim_changed_from_realname(self):
532- # if the real name part of the message has changed, it's detected
533+ # If the real name part of the message has changed, it's detected.
534 signed_message = self.fake_signing(plain_content)
535 self._dns_responses['example._domainkey.canonical.com.'] = \
536 sample_dns
537- fiddled_message = signed_message.replace('From: Foo Bar <foo.bar@canonical.com>',
538+ fiddled_message = signed_message.replace(
539+ 'From: Foo Bar <foo.bar@canonical.com>',
540 'From: Evil Foo <foo.bar@canonical.com>')
541 principal = authenticateEmail(
542 signed_message_from_string(fiddled_message))
543- # we don't care about the real name for determining the principal
544+ # We don't care about the real name for determining the principal.
545 self.assertWeaklyAuthenticated(principal, fiddled_message)
546 self.assertEqual(principal.person.preferredemail.email,
547 'foo.bar@canonical.com')
548
549 def test_dkim_nxdomain(self):
550- # if there's no DNS entry for the pubkey
551- # it should be handled decently
552+ # If there's no DNS entry for the pubkey it should be handled
553+ # decently.
554 signed_message = self.fake_signing(plain_content)
555 principal = authenticateEmail(
556 signed_message_from_string(signed_message))
557@@ -226,18 +230,19 @@
558 'foo.bar@canonical.com')
559
560 def test_dkim_message_unsigned(self):
561- # degenerate case: no signature treated as weakly authenticated
562+ # This is a degenerate case: a message with no signature is
563+ # treated as weakly authenticated.
564+ # The library doesn't log anything if there's no header at all.
565 principal = authenticateEmail(
566 signed_message_from_string(plain_content))
567 self.assertWeaklyAuthenticated(principal, plain_content)
568 self.assertEqual(principal.person.preferredemail.email,
569 'foo.bar@canonical.com')
570- # the library doesn't log anything if there's no header at all
571
572 def test_dkim_body_mismatch(self):
573- # The message message has a syntactically valid DKIM signature that
574- # doesn't actually correspond to what was signed. We log something about
575- # this but we don't want to drop the message.
576+ # The message has a syntactically valid DKIM signature that
577+ # doesn't actually correspond to what was signed. We log
578+ # something about this but we don't want to drop the message.
579 signed_message = self.fake_signing(plain_content)
580 signed_message += 'blah blah'
581 self._dns_responses['example._domainkey.canonical.com.'] = \
582
583=== renamed file 'lib/canonical/launchpad/mail/tests/test_incoming.py' => 'lib/lp/services/mail/tests/test_incoming.py'
584--- lib/canonical/launchpad/mail/tests/test_incoming.py 2010-10-04 19:50:45 +0000
585+++ lib/lp/services/mail/tests/test_incoming.py 2010-10-14 20:59:59 +0000
586@@ -2,13 +2,19 @@
587 # GNU Affero General Public License version 3 (see the file LICENSE).
588
589 from doctest import DocTestSuite
590+import logging
591 import os
592 import unittest
593
594 import transaction
595
596+from zope.security.management import setSecurityPolicy
597+
598+from canonical.config import config
599 from canonical.launchpad.mail.ftests.helpers import testmails_path
600-from canonical.launchpad.mail.incoming import (
601+from canonical.launchpad.testing.systemdocs import LayeredDocFileSuite
602+from canonical.launchpad.webapp.authorization import LaunchpadSecurityPolicy
603+from lp.services.mail.incoming import (
604 handleMail,
605 MailErrorUtility,
606 )
607@@ -77,10 +83,26 @@
608 self.assertEqual(old_oops.id, current_oops.id)
609
610
611+def setUp(test):
612+ test._old_policy = setSecurityPolicy(LaunchpadSecurityPolicy)
613+ LaunchpadZopelessLayer.switchDbUser(config.processmail.dbuser)
614+
615+
616+def tearDown(test):
617+ setSecurityPolicy(test._old_policy)
618+
619+
620 def test_suite():
621 suite = unittest.TestSuite()
622 suite.addTest(unittest.TestLoader().loadTestsFromName(__name__))
623- suite.addTest(DocTestSuite('canonical.launchpad.mail.incoming'))
624+ suite.addTest(DocTestSuite('lp.services.mail.incoming'))
625+ suite.addTest(
626+ LayeredDocFileSuite(
627+ 'incomingmail.txt',
628+ setUp=setUp,
629+ tearDown=tearDown,
630+ layer=LaunchpadZopelessLayer,
631+ stdout_logging_level=logging.WARNING))
632 return suite
633
634
635
636=== modified file 'lib/lp/services/mail/tests/test_signedmessage.py'
637--- lib/lp/services/mail/tests/test_signedmessage.py 2010-08-20 20:31:18 +0000
638+++ lib/lp/services/mail/tests/test_signedmessage.py 2010-10-14 20:59:59 +0000
639@@ -25,18 +25,18 @@
640 from canonical.launchpad.interfaces.gpghandler import IGPGHandler
641 from canonical.launchpad.interfaces.mail import IWeaklyAuthenticatedPrincipal
642 from canonical.launchpad.mail import signed_message_from_string
643-from canonical.launchpad.mail.incoming import (
644+from canonical.testing.layers import DatabaseFunctionalLayer
645+from lp.registry.interfaces.person import IPersonSet
646+from lp.services.mail.incoming import (
647 authenticateEmail,
648 canonicalise_line_endings,
649 )
650-from canonical.testing.layers import DatabaseFunctionalLayer
651-from lp.registry.interfaces.person import IPersonSet
652 from lp.testing import TestCaseWithFactory
653 from lp.testing.factory import GPGSigningContext
654
655
656 class TestSignedMessage(TestCaseWithFactory):
657- """Test SignedMessage class correctly extracts and verifies the GPG signatures."""
658+ "Test SignedMessage class correctly extracts and verifies GPG signatures."
659
660 layer = DatabaseFunctionalLayer
661
662@@ -154,4 +154,3 @@
663
664 def test_suite():
665 return unittest.TestLoader().loadTestsFromName(__name__)
666-