Code

7599aba9b6e2c4ee3c966ccba499c80648ba8d95
[roundup.git] / test / test_mailgw.py
1 #
2 # Copyright (c) 2001 Richard Jones, richard@bofh.asn.au.
3 # This module is free software, and you may redistribute it and/or modify
4 # under the same terms as Python, so long as this copyright message and
5 # disclaimer are retained in their original form.
6 #
7 # This module is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 #
11 # $Id: test_mailgw.py,v 1.67 2004-04-09 01:32:58 richard Exp $
13 import unittest, tempfile, os, shutil, errno, imp, sys, difflib, rfc822
15 from cStringIO import StringIO
17 if not os.environ.has_key('SENDMAILDEBUG'):
18     os.environ['SENDMAILDEBUG'] = 'mail-test.log'
19 SENDMAILDEBUG = os.environ['SENDMAILDEBUG']
21 from roundup.mailgw import MailGW, Unauthorized, uidFromAddress, \
22     parseContent, IgnoreLoop, IgnoreBulk
23 from roundup import init, instance, rfc2822, __version__
26 class Message(rfc822.Message):
27     """String-based Message class with equivalence test."""
28     def __init__(self, s):
29         rfc822.Message.__init__(self, StringIO(s.strip()))
30         
31     def __eq__(self, other):
32         return (self.dict == other.dict and
33                 self.fp.read() == other.fp.read()) 
35 class DiffHelper:
36     def compareMessages(self, new, old):
37         """Compare messages for semantic equivalence."""
38         new, old = Message(new), Message(old)
39         del new['date'], old['date']
41         if not new == old:
42             res = []
44             for key in new.keys():
45                 if key.lower() == 'x-roundup-version':
46                     # version changes constantly, so handle it specially
47                     if new[key] != __version__:
48                         res.append('  %s: %s != %s' % (key, __version__,
49                             new[key]))
50                 elif new[key] != old[key]:
51                     res.append('  %s: %s != %s' % (key, old[key], new[key]))
53             body_diff = self.compareStrings(new.fp.read(), old.fp.read())
54             if body_diff:
55                 res.append('')
56                 res.extend(body_diff)
58             if res:
59                 res.insert(0, 'Generated message not correct (diff follows):')
60                 raise AssertionError, '\n'.join(res)
61     
62     def compareStrings(self, s2, s1):
63         '''Note the reversal of s2 and s1 - difflib.SequenceMatcher wants
64            the first to be the "original" but in the calls in this file,
65            the second arg is the original. Ho hum.
66         '''
67         l1 = s1.strip().split('\n')
68         l2 = s2.strip().split('\n')
69         if l1 == l2:
70             return
71         s = difflib.SequenceMatcher(None, l1, l2)
72         res = []
73         for value, s1s, s1e, s2s, s2e in s.get_opcodes():
74             if value == 'equal':
75                 for i in range(s1s, s1e):
76                     res.append('  %s'%l1[i])
77             elif value == 'delete':
78                 for i in range(s1s, s1e):
79                     res.append('- %s'%l1[i])
80             elif value == 'insert':
81                 for i in range(s2s, s2e):
82                     res.append('+ %s'%l2[i])
83             elif value == 'replace':
84                 for i, j in zip(range(s1s, s1e), range(s2s, s2e)):
85                     res.append('- %s'%l1[i])
86                     res.append('+ %s'%l2[j])
88         return res
90 class MailgwTestCase(unittest.TestCase, DiffHelper):
91     count = 0
92     schema = 'classic'
93     def setUp(self):
94         MailgwTestCase.count = MailgwTestCase.count + 1
95         self.dirname = '_test_mailgw_%s'%self.count
96         try:
97             shutil.rmtree(self.dirname)
98         except OSError, error:
99             if error.errno not in (errno.ENOENT, errno.ESRCH): raise
100         # create the instance
101         init.install(self.dirname, 'templates/classic')
102         init.write_select_db(self.dirname, 'sqlite')
103         init.initialise(self.dirname, 'sekrit')
105         # check we can load the package
106         self.instance = instance.open(self.dirname)
108         # and open the database
109         self.db = self.instance.open('admin')
110         self.chef_id = self.db.user.create(username='Chef',
111             address='chef@bork.bork.bork', realname='Bork, Chef', roles='User')
112         self.richard_id = self.db.user.create(username='richard',
113             address='richard@test', roles='User')
114         self.mary_id = self.db.user.create(username='mary', address='mary@test',
115             roles='User', realname='Contrary, Mary')
116         self.john_id = self.db.user.create(username='john', address='john@test',
117             alternate_addresses='jondoe@test\njohn.doe@test', roles='User',
118             realname='John Doe')
120     def tearDown(self):
121         if os.path.exists(SENDMAILDEBUG):
122             os.remove(SENDMAILDEBUG)
123         self.db.close()
124         try:
125             shutil.rmtree(self.dirname)
126         except OSError, error:
127             if error.errno not in (errno.ENOENT, errno.ESRCH): raise
129     def _handle_mail(self, message):
130         handler = self.instance.MailGW(self.instance, self.db)
131         handler.trapExceptions = 0
132         ret = handler.main(StringIO(message))
133         # handler can close the db on us and open a new one
134         self.db = handler.db
135         return ret
136         
137     def _get_mail(self):
138         f = open(SENDMAILDEBUG)
139         try:
140             return f.read()
141         finally:
142             f.close()
144     def testEmptyMessage(self):
145         nodeid = self._handle_mail('''Content-Type: text/plain;
146   charset="iso-8859-1"
147 From: Chef <chef@bork.bork.bork>
148 To: issue_tracker@your.tracker.email.domain.example
149 Cc: richard@test
150 Reply-To: chef@bork.bork.bork
151 Message-Id: <dummy_test_message_id>
152 Subject: [issue] Testing...
154 ''')
155         assert not os.path.exists(SENDMAILDEBUG)
156         self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
158     def doNewIssue(self):
159         nodeid = self._handle_mail('''Content-Type: text/plain;
160   charset="iso-8859-1"
161 From: Chef <chef@bork.bork.bork>
162 To: issue_tracker@your.tracker.email.domain.example
163 Cc: richard@test
164 Message-Id: <dummy_test_message_id>
165 Subject: [issue] Testing...
167 This is a test submission of a new issue.
168 ''')
169         assert not os.path.exists(SENDMAILDEBUG)
170         l = self.db.issue.get(nodeid, 'nosy')
171         l.sort()
172         self.assertEqual(l, [self.chef_id, self.richard_id])
173         return nodeid
175     def testNewIssue(self):
176         self.doNewIssue()
178     def testNewIssueNosy(self):
179         self.instance.config.ADD_AUTHOR_TO_NOSY = 'yes'
180         nodeid = self._handle_mail('''Content-Type: text/plain;
181   charset="iso-8859-1"
182 From: Chef <chef@bork.bork.bork>
183 To: issue_tracker@your.tracker.email.domain.example
184 Cc: richard@test
185 Message-Id: <dummy_test_message_id>
186 Subject: [issue] Testing...
188 This is a test submission of a new issue.
189 ''')
190         assert not os.path.exists(SENDMAILDEBUG)
191         l = self.db.issue.get(nodeid, 'nosy')
192         l.sort()
193         self.assertEqual(l, [self.chef_id, self.richard_id])
195     def testAlternateAddress(self):
196         self._handle_mail('''Content-Type: text/plain;
197   charset="iso-8859-1"
198 From: John Doe <john.doe@test>
199 To: issue_tracker@your.tracker.email.domain.example
200 Message-Id: <dummy_test_message_id>
201 Subject: [issue] Testing...
203 This is a test submission of a new issue.
204 ''')
205         userlist = self.db.user.list()        
206         assert not os.path.exists(SENDMAILDEBUG)
207         self.assertEqual(userlist, self.db.user.list(),
208             "user created when it shouldn't have been")
210     def testNewIssueNoClass(self):
211         self._handle_mail('''Content-Type: text/plain;
212   charset="iso-8859-1"
213 From: Chef <chef@bork.bork.bork>
214 To: issue_tracker@your.tracker.email.domain.example
215 Cc: richard@test
216 Message-Id: <dummy_test_message_id>
217 Subject: Testing...
219 This is a test submission of a new issue.
220 ''')
221         assert not os.path.exists(SENDMAILDEBUG)
223     def testNewIssueAuthMsg(self):
224         # TODO: fix the damn config - this is apalling
225         self.db.config.MESSAGES_TO_AUTHOR = 'yes'
226         self._handle_mail('''Content-Type: text/plain;
227   charset="iso-8859-1"
228 From: Chef <chef@bork.bork.bork>
229 To: issue_tracker@your.tracker.email.domain.example
230 Message-Id: <dummy_test_message_id>
231 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
233 This is a test submission of a new issue.
234 ''')
235         self.compareMessages(self._get_mail(),
236 '''FROM: roundup-admin@your.tracker.email.domain.example
237 TO: chef@bork.bork.bork, mary@test, richard@test
238 Content-Type: text/plain; charset=utf-8
239 Subject: [issue1] Testing...
240 To: chef@bork.bork.bork, mary@test, richard@test
241 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
242 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
243 MIME-Version: 1.0
244 Message-Id: <dummy_test_message_id>
245 X-Roundup-Name: Roundup issue tracker
246 X-Roundup-Loop: hello
247 Content-Transfer-Encoding: quoted-printable
250 New submission from Bork, Chef <chef@bork.bork.bork>:
252 This is a test submission of a new issue.
254 ----------
255 assignedto: richard
256 messages: 1
257 nosy: Chef, mary, richard
258 status: unread
259 title: Testing...
261 _______________________________________________________________________
262 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
263 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
264 _______________________________________________________________________
265 ''')
267     # BUG
268     # def testMultipart(self):
269     #         '''With more than one part'''
270     #        see MultipartEnc tests: but if there is more than one part
271     #        we return a multipart/mixed and the boundary contains
272     #        the ip address of the test machine. 
274     # BUG should test some binary attamchent too.
276     def testSimpleFollowup(self):
277         self.doNewIssue()
278         self._handle_mail('''Content-Type: text/plain;
279   charset="iso-8859-1"
280 From: mary <mary@test>
281 To: issue_tracker@your.tracker.email.domain.example
282 Message-Id: <followup_dummy_id>
283 In-Reply-To: <dummy_test_message_id>
284 Subject: [issue1] Testing...
286 This is a second followup
287 ''')
288         self.compareMessages(self._get_mail(),
289 '''FROM: roundup-admin@your.tracker.email.domain.example
290 TO: chef@bork.bork.bork, richard@test
291 Content-Type: text/plain; charset=utf-8
292 Subject: [issue1] Testing...
293 To: chef@bork.bork.bork, richard@test
294 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
295 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
296 MIME-Version: 1.0
297 Message-Id: <followup_dummy_id>
298 In-Reply-To: <dummy_test_message_id>
299 X-Roundup-Name: Roundup issue tracker
300 X-Roundup-Loop: hello
301 Content-Transfer-Encoding: quoted-printable
304 Contrary, Mary <mary@test> added the comment:
306 This is a second followup
308 ----------
309 status: unread -> chatting
311 _______________________________________________________________________
312 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
313 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
314 _______________________________________________________________________
315 ''')
317     def testFollowup(self):
318         self.doNewIssue()
320         self._handle_mail('''Content-Type: text/plain;
321   charset="iso-8859-1"
322 From: richard <richard@test>
323 To: issue_tracker@your.tracker.email.domain.example
324 Message-Id: <followup_dummy_id>
325 In-Reply-To: <dummy_test_message_id>
326 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
328 This is a followup
329 ''')
330         l = self.db.issue.get('1', 'nosy')
331         l.sort()
332         self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
333             self.john_id])
335         self.compareMessages(self._get_mail(),
336 '''FROM: roundup-admin@your.tracker.email.domain.example
337 TO: chef@bork.bork.bork, john@test, mary@test
338 Content-Type: text/plain; charset=utf-8
339 Subject: [issue1] Testing...
340 To: chef@bork.bork.bork, john@test, mary@test
341 From: richard <issue_tracker@your.tracker.email.domain.example>
342 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
343 MIME-Version: 1.0
344 Message-Id: <followup_dummy_id>
345 In-Reply-To: <dummy_test_message_id>
346 X-Roundup-Name: Roundup issue tracker
347 X-Roundup-Loop: hello
348 Content-Transfer-Encoding: quoted-printable
351 richard <richard@test> added the comment:
353 This is a followup
355 ----------
356 assignedto:  -> mary
357 nosy: +john, mary
358 status: unread -> chatting
360 _______________________________________________________________________
361 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
362 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
363 _______________________________________________________________________
364 ''')
366     def testFollowupTitleMatch(self):
367         self.doNewIssue()
368         self._handle_mail('''Content-Type: text/plain;
369   charset="iso-8859-1"
370 From: richard <richard@test>
371 To: issue_tracker@your.tracker.email.domain.example
372 Message-Id: <followup_dummy_id>
373 In-Reply-To: <dummy_test_message_id>
374 Subject: Re: Testing... [assignedto=mary; nosy=+john]
376 This is a followup
377 ''')
378         self.compareMessages(self._get_mail(),
379 '''FROM: roundup-admin@your.tracker.email.domain.example
380 TO: chef@bork.bork.bork, john@test, mary@test
381 Content-Type: text/plain; charset=utf-8
382 Subject: [issue1] Testing...
383 To: chef@bork.bork.bork, john@test, mary@test
384 From: richard <issue_tracker@your.tracker.email.domain.example>
385 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
386 MIME-Version: 1.0
387 Message-Id: <followup_dummy_id>
388 In-Reply-To: <dummy_test_message_id>
389 X-Roundup-Name: Roundup issue tracker
390 X-Roundup-Loop: hello
391 Content-Transfer-Encoding: quoted-printable
394 richard <richard@test> added the comment:
396 This is a followup
398 ----------
399 assignedto:  -> mary
400 nosy: +john, mary
401 status: unread -> chatting
403 _______________________________________________________________________
404 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
405 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
406 _______________________________________________________________________
407 ''')
409     def testFollowupNosyAuthor(self):
410         self.doNewIssue()
411         self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
412         self._handle_mail('''Content-Type: text/plain;
413   charset="iso-8859-1"
414 From: john@test
415 To: issue_tracker@your.tracker.email.domain.example
416 Message-Id: <followup_dummy_id>
417 In-Reply-To: <dummy_test_message_id>
418 Subject: [issue1] Testing...
420 This is a followup
421 ''')
423         self.compareMessages(self._get_mail(),
424 '''FROM: roundup-admin@your.tracker.email.domain.example
425 TO: chef@bork.bork.bork, richard@test
426 Content-Type: text/plain; charset=utf-8
427 Subject: [issue1] Testing...
428 To: chef@bork.bork.bork, richard@test
429 From: John Doe <issue_tracker@your.tracker.email.domain.example>
430 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
431 MIME-Version: 1.0
432 Message-Id: <followup_dummy_id>
433 In-Reply-To: <dummy_test_message_id>
434 X-Roundup-Name: Roundup issue tracker
435 X-Roundup-Loop: hello
436 Content-Transfer-Encoding: quoted-printable
439 John Doe <john@test> added the comment:
441 This is a followup
443 ----------
444 nosy: +john
445 status: unread -> chatting
447 _______________________________________________________________________
448 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
449 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
450 _______________________________________________________________________
452 ''')
454     def testFollowupNosyRecipients(self):
455         self.doNewIssue()
456         self.db.config.ADD_RECIPIENTS_TO_NOSY = 'yes'
457         self._handle_mail('''Content-Type: text/plain;
458   charset="iso-8859-1"
459 From: richard@test
460 To: issue_tracker@your.tracker.email.domain.example
461 Cc: john@test
462 Message-Id: <followup_dummy_id>
463 In-Reply-To: <dummy_test_message_id>
464 Subject: [issue1] Testing...
466 This is a followup
467 ''')
468         self.compareMessages(self._get_mail(),
469 '''FROM: roundup-admin@your.tracker.email.domain.example
470 TO: chef@bork.bork.bork
471 Content-Type: text/plain; charset=utf-8
472 Subject: [issue1] Testing...
473 To: chef@bork.bork.bork
474 From: richard <issue_tracker@your.tracker.email.domain.example>
475 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
476 MIME-Version: 1.0
477 Message-Id: <followup_dummy_id>
478 In-Reply-To: <dummy_test_message_id>
479 X-Roundup-Name: Roundup issue tracker
480 X-Roundup-Loop: hello
481 Content-Transfer-Encoding: quoted-printable
484 richard <richard@test> added the comment:
486 This is a followup
488 ----------
489 nosy: +john
490 status: unread -> chatting
492 _______________________________________________________________________
493 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
494 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
495 _______________________________________________________________________
497 ''')
499     def testFollowupNosyAuthorAndCopy(self):
500         self.doNewIssue()
501         self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
502         self.db.config.MESSAGES_TO_AUTHOR = 'yes'
503         self._handle_mail('''Content-Type: text/plain;
504   charset="iso-8859-1"
505 From: john@test
506 To: issue_tracker@your.tracker.email.domain.example
507 Message-Id: <followup_dummy_id>
508 In-Reply-To: <dummy_test_message_id>
509 Subject: [issue1] Testing...
511 This is a followup
512 ''')
513         self.compareMessages(self._get_mail(),
514 '''FROM: roundup-admin@your.tracker.email.domain.example
515 TO: chef@bork.bork.bork, john@test, richard@test
516 Content-Type: text/plain; charset=utf-8
517 Subject: [issue1] Testing...
518 To: chef@bork.bork.bork, john@test, richard@test
519 From: John Doe <issue_tracker@your.tracker.email.domain.example>
520 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
521 MIME-Version: 1.0
522 Message-Id: <followup_dummy_id>
523 In-Reply-To: <dummy_test_message_id>
524 X-Roundup-Name: Roundup issue tracker
525 X-Roundup-Loop: hello
526 Content-Transfer-Encoding: quoted-printable
529 John Doe <john@test> added the comment:
531 This is a followup
533 ----------
534 nosy: +john
535 status: unread -> chatting
537 _______________________________________________________________________
538 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
539 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
540 _______________________________________________________________________
542 ''')
544     def testFollowupNoNosyAuthor(self):
545         self.doNewIssue()
546         self.instance.config.ADD_AUTHOR_TO_NOSY = 'no'
547         self._handle_mail('''Content-Type: text/plain;
548   charset="iso-8859-1"
549 From: john@test
550 To: issue_tracker@your.tracker.email.domain.example
551 Message-Id: <followup_dummy_id>
552 In-Reply-To: <dummy_test_message_id>
553 Subject: [issue1] Testing...
555 This is a followup
556 ''')
557         self.compareMessages(self._get_mail(),
558 '''FROM: roundup-admin@your.tracker.email.domain.example
559 TO: chef@bork.bork.bork, richard@test
560 Content-Type: text/plain; charset=utf-8
561 Subject: [issue1] Testing...
562 To: chef@bork.bork.bork, richard@test
563 From: John Doe <issue_tracker@your.tracker.email.domain.example>
564 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
565 MIME-Version: 1.0
566 Message-Id: <followup_dummy_id>
567 In-Reply-To: <dummy_test_message_id>
568 X-Roundup-Name: Roundup issue tracker
569 X-Roundup-Loop: hello
570 Content-Transfer-Encoding: quoted-printable
573 John Doe <john@test> added the comment:
575 This is a followup
577 ----------
578 status: unread -> chatting
580 _______________________________________________________________________
581 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
582 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
583 _______________________________________________________________________
585 ''')
587     def testFollowupNoNosyRecipients(self):
588         self.doNewIssue()
589         self.instance.config.ADD_RECIPIENTS_TO_NOSY = 'no'
590         self._handle_mail('''Content-Type: text/plain;
591   charset="iso-8859-1"
592 From: richard@test
593 To: issue_tracker@your.tracker.email.domain.example
594 Cc: john@test
595 Message-Id: <followup_dummy_id>
596 In-Reply-To: <dummy_test_message_id>
597 Subject: [issue1] Testing...
599 This is a followup
600 ''')
601         self.compareMessages(self._get_mail(),
602 '''FROM: roundup-admin@your.tracker.email.domain.example
603 TO: chef@bork.bork.bork
604 Content-Type: text/plain; charset=utf-8
605 Subject: [issue1] Testing...
606 To: chef@bork.bork.bork
607 From: richard <issue_tracker@your.tracker.email.domain.example>
608 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
609 MIME-Version: 1.0
610 Message-Id: <followup_dummy_id>
611 In-Reply-To: <dummy_test_message_id>
612 X-Roundup-Name: Roundup issue tracker
613 X-Roundup-Loop: hello
614 Content-Transfer-Encoding: quoted-printable
617 richard <richard@test> added the comment:
619 This is a followup
621 ----------
622 status: unread -> chatting
624 _______________________________________________________________________
625 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
626 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
627 _______________________________________________________________________
629 ''')
631     def testFollowupEmptyMessage(self):
632         self.doNewIssue()
634         self._handle_mail('''Content-Type: text/plain;
635   charset="iso-8859-1"
636 From: richard <richard@test>
637 To: issue_tracker@your.tracker.email.domain.example
638 Message-Id: <followup_dummy_id>
639 In-Reply-To: <dummy_test_message_id>
640 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
642 ''')
643         l = self.db.issue.get('1', 'nosy')
644         l.sort()
645         self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
646             self.john_id])
648         # should be no file created (ie. no message)
649         assert not os.path.exists(SENDMAILDEBUG)
651     def testNosyRemove(self):
652         self.doNewIssue()
654         self._handle_mail('''Content-Type: text/plain;
655   charset="iso-8859-1"
656 From: richard <richard@test>
657 To: issue_tracker@your.tracker.email.domain.example
658 Message-Id: <followup_dummy_id>
659 In-Reply-To: <dummy_test_message_id>
660 Subject: [issue1] Testing... [nosy=-richard]
662 ''')
663         l = self.db.issue.get('1', 'nosy')
664         l.sort()
665         self.assertEqual(l, [self.chef_id])
667         # NO NOSY MESSAGE SHOULD BE SENT!
668         assert not os.path.exists(SENDMAILDEBUG)
670     def testNewUserAuthor(self):
671         # first without the permission
672         # heh... just ignore the API for a second ;)
673         self.db.security.role['anonymous'].permissions=[]
674         anonid = self.db.user.lookup('anonymous')
675         self.db.user.set(anonid, roles='Anonymous')
677         self.db.security.hasPermission('Email Registration', anonid)
678         l = self.db.user.list()
679         l.sort()
680         message = '''Content-Type: text/plain;
681   charset="iso-8859-1"
682 From: fubar <fubar@bork.bork.bork>
683 To: issue_tracker@your.tracker.email.domain.example
684 Message-Id: <dummy_test_message_id>
685 Subject: [issue] Testing...
687 This is a test submission of a new issue.
688 '''
689         self.assertRaises(Unauthorized, self._handle_mail, message)
690         m = self.db.user.list()
691         m.sort()
692         self.assertEqual(l, m)
694         # now with the permission
695         p = self.db.security.getPermission('Email Registration')
696         self.db.security.role['anonymous'].permissions=[p]
697         self._handle_mail(message)
698         m = self.db.user.list()
699         m.sort()
700         self.assertNotEqual(l, m)
702     def testEnc01(self):
703         self.doNewIssue()
704         self._handle_mail('''Content-Type: text/plain;
705   charset="iso-8859-1"
706 From: mary <mary@test>
707 To: issue_tracker@your.tracker.email.domain.example
708 Message-Id: <followup_dummy_id>
709 In-Reply-To: <dummy_test_message_id>
710 Subject: [issue1] Testing...
711 Content-Type: text/plain;
712         charset="iso-8859-1"
713 Content-Transfer-Encoding: quoted-printable
715 A message with encoding (encoded oe =F6)
717 ''')
718         self.compareMessages(self._get_mail(),
719 '''FROM: roundup-admin@your.tracker.email.domain.example
720 TO: chef@bork.bork.bork, richard@test
721 Content-Type: text/plain; charset=utf-8
722 Subject: [issue1] Testing...
723 To: chef@bork.bork.bork, richard@test
724 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
725 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
726 MIME-Version: 1.0
727 Message-Id: <followup_dummy_id>
728 In-Reply-To: <dummy_test_message_id>
729 X-Roundup-Name: Roundup issue tracker
730 X-Roundup-Loop: hello
731 Content-Transfer-Encoding: quoted-printable
734 Contrary, Mary <mary@test> added the comment:
736 A message with encoding (encoded oe =C3=B6)
738 ----------
739 status: unread -> chatting
741 _______________________________________________________________________
742 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
743 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
744 _______________________________________________________________________
745 ''')
748     def testMultipartEnc01(self):
749         self.doNewIssue()
750         self._handle_mail('''Content-Type: text/plain;
751   charset="iso-8859-1"
752 From: mary <mary@test>
753 To: issue_tracker@your.tracker.email.domain.example
754 Message-Id: <followup_dummy_id>
755 In-Reply-To: <dummy_test_message_id>
756 Subject: [issue1] Testing...
757 Content-Type: multipart/mixed;
758         boundary="----_=_NextPart_000_01"
760 This message is in MIME format. Since your mail reader does not understand
761 this format, some or all of this message may not be legible.
763 ------_=_NextPart_000_01
764 Content-Type: text/plain;
765         charset="iso-8859-1"
766 Content-Transfer-Encoding: quoted-printable
768 A message with first part encoded (encoded oe =F6)
770 ''')
771         self.compareMessages(self._get_mail(),
772 '''FROM: roundup-admin@your.tracker.email.domain.example
773 TO: chef@bork.bork.bork, richard@test
774 Content-Type: text/plain; charset=utf-8
775 Subject: [issue1] Testing...
776 To: chef@bork.bork.bork, richard@test
777 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
778 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
779 MIME-Version: 1.0
780 Message-Id: <followup_dummy_id>
781 In-Reply-To: <dummy_test_message_id>
782 X-Roundup-Name: Roundup issue tracker
783 X-Roundup-Loop: hello
784 Content-Transfer-Encoding: quoted-printable
787 Contrary, Mary <mary@test> added the comment:
789 A message with first part encoded (encoded oe =C3=B6)
791 ----------
792 status: unread -> chatting
794 _______________________________________________________________________
795 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
796 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
797 _______________________________________________________________________
798 ''')
800     def testContentDisposition(self):
801         self.doNewIssue()
802         self._handle_mail('''Content-Type: text/plain;
803   charset="iso-8859-1"
804 From: mary <mary@test>
805 To: issue_tracker@your.tracker.email.domain.example
806 Message-Id: <followup_dummy_id>
807 In-Reply-To: <dummy_test_message_id>
808 Subject: [issue1] Testing...
809 Content-Type: multipart/mixed; boundary="bCsyhTFzCvuiizWE" 
810 Content-Disposition: inline 
811  
812  
813 --bCsyhTFzCvuiizWE 
814 Content-Type: text/plain; charset=us-ascii 
815 Content-Disposition: inline 
817 test attachment binary 
819 --bCsyhTFzCvuiizWE 
820 Content-Type: application/octet-stream 
821 Content-Disposition: attachment; filename="main.dvi" 
823 xxxxxx 
825 --bCsyhTFzCvuiizWE--
826 ''')
827         messages = self.db.issue.get('1', 'messages')
828         messages.sort()
829         file = self.db.msg.get(messages[-1], 'files')[0]
830         self.assertEqual(self.db.file.get(file, 'name'), 'main.dvi')
832     def testFollowupStupidQuoting(self):
833         self.doNewIssue()
835         self._handle_mail('''Content-Type: text/plain;
836   charset="iso-8859-1"
837 From: richard <richard@test>
838 To: issue_tracker@your.tracker.email.domain.example
839 Message-Id: <followup_dummy_id>
840 In-Reply-To: <dummy_test_message_id>
841 Subject: Re: "[issue1] Testing... "
843 This is a followup
844 ''')
845         self.compareMessages(self._get_mail(),
846 '''FROM: roundup-admin@your.tracker.email.domain.example
847 TO: chef@bork.bork.bork
848 Content-Type: text/plain; charset=utf-8
849 Subject: [issue1] Testing...
850 To: chef@bork.bork.bork
851 From: richard <issue_tracker@your.tracker.email.domain.example>
852 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
853 MIME-Version: 1.0
854 Message-Id: <followup_dummy_id>
855 In-Reply-To: <dummy_test_message_id>
856 X-Roundup-Name: Roundup issue tracker
857 X-Roundup-Loop: hello
858 Content-Transfer-Encoding: quoted-printable
861 richard <richard@test> added the comment:
863 This is a followup
865 ----------
866 status: unread -> chatting
868 _______________________________________________________________________
869 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
870 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
871 _______________________________________________________________________
872 ''')
874     def testEmailQuoting(self):
875         self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
876         self.innerTestQuoting('''This is a followup
877 ''')
879     def testEmailQuotingRemove(self):
880         self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
881         self.innerTestQuoting('''Blah blah wrote:
882 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
883 >  skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
886 This is a followup
887 ''')
889     def innerTestQuoting(self, expect):
890         nodeid = self.doNewIssue()
892         messages = self.db.issue.get(nodeid, 'messages')
894         self._handle_mail('''Content-Type: text/plain;
895   charset="iso-8859-1"
896 From: richard <richard@test>
897 To: issue_tracker@your.tracker.email.domain.example
898 Message-Id: <followup_dummy_id>
899 In-Reply-To: <dummy_test_message_id>
900 Subject: Re: [issue1] Testing...
902 Blah blah wrote:
903 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
904 >  skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
907 This is a followup
908 ''')
909         # figure the new message id
910         newmessages = self.db.issue.get(nodeid, 'messages')
911         for msg in messages:
912             newmessages.remove(msg)
913         messageid = newmessages[0]
915         self.compareMessages(self.db.msg.get(messageid, 'content'), expect)
917     def testUserLookup(self):
918         i = self.db.user.create(username='user1', address='user1@foo.com')
919         self.assertEqual(uidFromAddress(self.db, ('', 'user1@foo.com'), 0), i)
920         self.assertEqual(uidFromAddress(self.db, ('', 'USER1@foo.com'), 0), i)
921         i = self.db.user.create(username='user2', address='USER2@foo.com')
922         self.assertEqual(uidFromAddress(self.db, ('', 'USER2@foo.com'), 0), i)
923         self.assertEqual(uidFromAddress(self.db, ('', 'user2@foo.com'), 0), i)
925     def testUserAlternateLookup(self):
926         i = self.db.user.create(username='user1', address='user1@foo.com',
927                                 alternate_addresses='user1@bar.com')
928         self.assertEqual(uidFromAddress(self.db, ('', 'user1@bar.com'), 0), i)
929         self.assertEqual(uidFromAddress(self.db, ('', 'USER1@bar.com'), 0), i)
931     def testUserCreate(self):
932         i = uidFromAddress(self.db, ('', 'user@foo.com'), 1)
933         self.assertNotEqual(uidFromAddress(self.db, ('', 'user@bar.com'), 1), i)
935     def testRFC2822(self):
936         ascii_header = "[issue243] This is a \"test\" - with 'quotation' marks"
937         unicode_header = '[issue244] \xd0\xb0\xd0\xbd\xd0\xb4\xd1\x80\xd0\xb5\xd0\xb9'
938         unicode_encoded = '=?utf-8?q?[issue244]_=D0=B0=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?='
939         self.assertEqual(rfc2822.encode_header(ascii_header), ascii_header)
940         self.assertEqual(rfc2822.encode_header(unicode_header), unicode_encoded)
942     def testRegistrationConfirmation(self):
943         otk = "Aj4euk4LZSAdwePohj90SME5SpopLETL"
944         self.db.getOTKManager().set(otk, username='johannes')
945         self._handle_mail('''Content-Type: text/plain;
946   charset="iso-8859-1"
947 From: Chef <chef@bork.bork.bork>
948 To: issue_tracker@your.tracker.email.domain.example
949 Cc: richard@test
950 Message-Id: <dummy_test_message_id>
951 Subject: Re: Complete your registration to Roundup issue tracker\r
952  -- key %s
954 This is a test confirmation of registration.
955 ''' % otk)
956         self.db.user.lookup('johannes')
958     def testFollowupOnNonIssue(self):
959         self.db.keyword.create(name='Foo')
960         self._handle_mail('''Content-Type: text/plain;
961   charset="iso-8859-1"
962 From: richard <richard@test>
963 To: issue_tracker@your.tracker.email.domain.example
964 Message-Id: <followup_dummy_id>
965 In-Reply-To: <dummy_test_message_id>
966 Subject: [keyword1] Testing... [name=Bar]
968 ''')        
969         self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
971     def testResentFrom(self):
972         nodeid = self._handle_mail('''Content-Type: text/plain;
973   charset="iso-8859-1"
974 From: Chef <chef@bork.bork.bork>
975 Resent-From: mary <mary@test>
976 To: issue_tracker@your.tracker.email.domain.example
977 Cc: richard@test
978 Message-Id: <dummy_test_message_id>
979 Subject: [issue] Testing...
981 This is a test submission of a new issue.
982 ''')
983         assert not os.path.exists(SENDMAILDEBUG)
984         l = self.db.issue.get(nodeid, 'nosy')
985         l.sort()
986         self.assertEqual(l, [self.richard_id, self.mary_id])
987         return nodeid
990     def testDejaVu(self):
991         self.assertRaises(IgnoreLoop, self._handle_mail,
992             '''Content-Type: text/plain;
993   charset="iso-8859-1"
994 From: Chef <chef@bork.bork.bork>
995 X-Roundup-Loop: hello
996 To: issue_tracker@your.tracker.email.domain.example
997 Cc: richard@test
998 Message-Id: <dummy_test_message_id>
999 Subject: Re: [issue] Testing...
1001 Hi, I've been mis-configured to loop messages back to myself.
1002 ''')
1004     def testItsBulkStupid(self):
1005         self.assertRaises(IgnoreBulk, self._handle_mail,
1006             '''Content-Type: text/plain;
1007   charset="iso-8859-1"
1008 From: Chef <chef@bork.bork.bork>
1009 Precedence: bulk
1010 To: issue_tracker@your.tracker.email.domain.example
1011 Cc: richard@test
1012 Message-Id: <dummy_test_message_id>
1013 Subject: Re: [issue] Testing...
1015 Hi, I'm on holidays, and this is a dumb auto-responder.
1016 ''')
1018 def test_suite():
1019     suite = unittest.TestSuite()
1020     suite.addTest(unittest.makeSuite(MailgwTestCase))
1021     return suite
1023 if __name__ == '__main__':
1024     runner = unittest.TextTestRunner()
1025     unittest.main(testRunner=runner)
1027 # vim: set filetype=python ts=4 sw=4 et si