Code

137d7a24d2d16e58a4a91abf22b109d8ad655203
[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.58 2003-11-03 18:34:03 jlgijsbers 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, parseContent
22 from roundup import init, instance, rfc2822
25 class Message(rfc822.Message):
26     """String-based Message class with equivalence test."""
27     def __init__(self, s):
28         rfc822.Message.__init__(self, StringIO(s.strip()))
29         
30     def __eq__(self, other):
31         del self['date'], other['date']
33         return (self.dict == other.dict and
34                 self.fp.read() == other.fp.read()) 
36 # TODO: Do a semantic diff instead of a straight text diff when a test fails.
37 class DiffHelper:
38     def compareMessages(self, s2, s1):
39         """Compare messages for semantic equivalence."""
40         if not Message(s2) == Message(s1):    
41             self.compareStrings(s2, s1)
42     
43     def compareStrings(self, s2, s1):
44         '''Note the reversal of s2 and s1 - difflib.SequenceMatcher wants
45            the first to be the "original" but in the calls in this file,
46            the second arg is the original. Ho hum.
47         '''
48         # we have to special-case the Date: header here 'cos we can't test
49         # for it properly
50         l1=s1.strip().split('\n')
51         l2=[x for x in s2.strip().split('\n') if not x.startswith('Date: ')]
52         if l1 == l2:
53             return
55         s = difflib.SequenceMatcher(None, l1, l2)
56         res = ['Generated message not correct (diff follows):']
57         for value, s1s, s1e, s2s, s2e in s.get_opcodes():
58             if value == 'equal':
59                 for i in range(s1s, s1e):
60                     res.append('  %s'%l1[i])
61             elif value == 'delete':
62                 for i in range(s1s, s1e):
63                     res.append('- %s'%l1[i])
64             elif value == 'insert':
65                 for i in range(s2s, s2e):
66                     res.append('+ %s'%l2[i])
67             elif value == 'replace':
68                 for i, j in zip(range(s1s, s1e), range(s2s, s2e)):
69                     res.append('- %s'%l1[i])
70                     res.append('+ %s'%l2[j])
72         raise AssertionError, '\n'.join(res)
74 class MailgwTestCase(unittest.TestCase, DiffHelper):
75     count = 0
76     schema = 'classic'
77     def setUp(self):
78         MailgwTestCase.count = MailgwTestCase.count + 1
79         self.dirname = '_test_mailgw_%s'%self.count
80         try:
81             shutil.rmtree(self.dirname)
82         except OSError, error:
83             if error.errno not in (errno.ENOENT, errno.ESRCH): raise
84         # create the instance
85         init.install(self.dirname, 'templates/classic')
86         init.write_select_db(self.dirname, 'anydbm')
87         init.initialise(self.dirname, 'sekrit')
88         
89         # check we can load the package
90         self.instance = instance.open(self.dirname)
92         # and open the database
93         self.db = self.instance.open('admin')
94         self.db.user.create(username='Chef', address='chef@bork.bork.bork',
95             realname='Bork, Chef', roles='User')
96         self.db.user.create(username='richard', address='richard@test',
97             roles='User')
98         self.db.user.create(username='mary', address='mary@test',
99             roles='User', realname='Contrary, Mary')
100         self.db.user.create(username='john', address='john@test',
101             alternate_addresses='jondoe@test\njohn.doe@test', roles='User',
102             realname='John Doe')
104     def tearDown(self):
105         if os.path.exists(SENDMAILDEBUG):
106             os.remove(SENDMAILDEBUG)
107         self.db.close()
108         try:
109             shutil.rmtree(self.dirname)
110         except OSError, error:
111             if error.errno not in (errno.ENOENT, errno.ESRCH): raise
113     def _get_mail(self):
114         f = open(SENDMAILDEBUG)
115         try:
116             return f.read()
117         finally:
118             f.close()
120     def testEmptyMessage(self):
121         message = StringIO('''Content-Type: text/plain;
122   charset="iso-8859-1"
123 From: Chef <chef@bork.bork.bork>
124 To: issue_tracker@your.tracker.email.domain.example
125 Cc: richard@test
126 Message-Id: <dummy_test_message_id>
127 Subject: [issue] Testing...
129 ''')
130         handler = self.instance.MailGW(self.instance, self.db)
131         handler.trapExceptions = 0
132         nodeid = handler.main(message)
133         assert not os.path.exists(SENDMAILDEBUG)
134         self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
136     def doNewIssue(self):
137         message = StringIO('''Content-Type: text/plain;
138   charset="iso-8859-1"
139 From: Chef <chef@bork.bork.bork>
140 To: issue_tracker@your.tracker.email.domain.example
141 Cc: richard@test
142 Message-Id: <dummy_test_message_id>
143 Subject: [issue] Testing...
145 This is a test submission of a new issue.
146 ''')
147         handler = self.instance.MailGW(self.instance, self.db)
148         handler.trapExceptions = 0
149         nodeid = handler.main(message)
150         assert not os.path.exists(SENDMAILDEBUG)
151         l = self.db.issue.get(nodeid, 'nosy')
152         l.sort()
153         self.assertEqual(l, ['3', '4'])
154         return nodeid
156     def testNewIssue(self):
157         self.doNewIssue()
159     def testNewIssueNosy(self):
160         self.instance.config.ADD_AUTHOR_TO_NOSY = 'yes'
161         message = StringIO('''Content-Type: text/plain;
162   charset="iso-8859-1"
163 From: Chef <chef@bork.bork.bork>
164 To: issue_tracker@your.tracker.email.domain.example
165 Cc: richard@test
166 Message-Id: <dummy_test_message_id>
167 Subject: [issue] Testing...
169 This is a test submission of a new issue.
170 ''')
171         handler = self.instance.MailGW(self.instance, self.db)
172         handler.trapExceptions = 0
173         nodeid = handler.main(message)
174         assert not os.path.exists(SENDMAILDEBUG)
175         l = self.db.issue.get(nodeid, 'nosy')
176         l.sort()
177         self.assertEqual(l, ['3', '4'])
179     def testAlternateAddress(self):
180         message = StringIO('''Content-Type: text/plain;
181   charset="iso-8859-1"
182 From: John Doe <john.doe@test>
183 To: issue_tracker@your.tracker.email.domain.example
184 Message-Id: <dummy_test_message_id>
185 Subject: [issue] Testing...
187 This is a test submission of a new issue.
188 ''')
189         userlist = self.db.user.list()
190         handler = self.instance.MailGW(self.instance, self.db)
191         handler.trapExceptions = 0
192         handler.main(message)
193         assert not os.path.exists(SENDMAILDEBUG)
194         self.assertEqual(userlist, self.db.user.list(),
195             "user created when it shouldn't have been")
197     def testNewIssueNoClass(self):
198         message = StringIO('''Content-Type: text/plain;
199   charset="iso-8859-1"
200 From: Chef <chef@bork.bork.bork>
201 To: issue_tracker@your.tracker.email.domain.example
202 Cc: richard@test
203 Message-Id: <dummy_test_message_id>
204 Subject: Testing...
206 This is a test submission of a new issue.
207 ''')
208         handler = self.instance.MailGW(self.instance, self.db)
209         handler.trapExceptions = 0
210         handler.main(message)
211         assert not os.path.exists(SENDMAILDEBUG)
213     def testNewIssueAuthMsg(self):
214         message = StringIO('''Content-Type: text/plain;
215   charset="iso-8859-1"
216 From: Chef <chef@bork.bork.bork>
217 To: issue_tracker@your.tracker.email.domain.example
218 Message-Id: <dummy_test_message_id>
219 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
221 This is a test submission of a new issue.
222 ''')
223         handler = self.instance.MailGW(self.instance, self.db)
224         handler.trapExceptions = 0
225         # TODO: fix the damn config - this is apalling
226         self.db.config.MESSAGES_TO_AUTHOR = 'yes'
227         handler.main(message)
229         self.compareMessages(self._get_mail(),
230 '''FROM: roundup-admin@your.tracker.email.domain.example
231 TO: chef@bork.bork.bork, mary@test, richard@test
232 Content-Type: text/plain; charset=utf-8
233 Subject: [issue1] Testing...
234 To: chef@bork.bork.bork, mary@test, richard@test
235 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
236 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
237 MIME-Version: 1.0
238 Message-Id: <dummy_test_message_id>
239 X-Roundup-Name: Roundup issue tracker
240 X-Roundup-Loop: hello
241 Content-Transfer-Encoding: quoted-printable
244 New submission from Bork, Chef <chef@bork.bork.bork>:
246 This is a test submission of a new issue.
248 ----------
249 assignedto: richard
250 messages: 1
251 nosy: Chef, mary, richard
252 status: unread
253 title: Testing...
254 _______________________________________________________________________
255 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
256 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
257 _______________________________________________________________________
258 ''')
260     # BUG
261     # def testMultipart(self):
262     #         '''With more than one part'''
263     #        see MultipartEnc tests: but if there is more than one part
264     #        we return a multipart/mixed and the boundary contains
265     #        the ip address of the test machine. 
267     # BUG should test some binary attamchent too.
269     def testSimpleFollowup(self):
270         self.doNewIssue()
271         message = StringIO('''Content-Type: text/plain;
272   charset="iso-8859-1"
273 From: mary <mary@test>
274 To: issue_tracker@your.tracker.email.domain.example
275 Message-Id: <followup_dummy_id>
276 In-Reply-To: <dummy_test_message_id>
277 Subject: [issue1] Testing...
279 This is a second followup
280 ''')
281         handler = self.instance.MailGW(self.instance, self.db)
282         handler.trapExceptions = 0
283         handler.main(message)
284         self.compareMessages(self._get_mail(),
285 '''FROM: roundup-admin@your.tracker.email.domain.example
286 TO: chef@bork.bork.bork, richard@test
287 Content-Type: text/plain; charset=utf-8
288 Subject: [issue1] Testing...
289 To: chef@bork.bork.bork, richard@test
290 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
291 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
292 MIME-Version: 1.0
293 Message-Id: <followup_dummy_id>
294 In-Reply-To: <dummy_test_message_id>
295 X-Roundup-Name: Roundup issue tracker
296 X-Roundup-Loop: hello
297 Content-Transfer-Encoding: quoted-printable
300 Contrary, Mary <mary@test> added the comment:
302 This is a second followup
304 ----------
305 status: unread -> chatting
306 _______________________________________________________________________
307 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
308 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
309 _______________________________________________________________________
310 ''')
312     def testFollowup(self):
313         self.doNewIssue()
315         message = StringIO('''Content-Type: text/plain;
316   charset="iso-8859-1"
317 From: richard <richard@test>
318 To: issue_tracker@your.tracker.email.domain.example
319 Message-Id: <followup_dummy_id>
320 In-Reply-To: <dummy_test_message_id>
321 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
323 This is a followup
324 ''')
325         handler = self.instance.MailGW(self.instance, self.db)
326         handler.trapExceptions = 0
327         handler.main(message)
328         l = self.db.issue.get('1', 'nosy')
329         l.sort()
330         self.assertEqual(l, ['3', '4', '5', '6'])
332         self.compareMessages(self._get_mail(),
333 '''FROM: roundup-admin@your.tracker.email.domain.example
334 TO: chef@bork.bork.bork, john@test, mary@test
335 Content-Type: text/plain; charset=utf-8
336 Subject: [issue1] Testing...
337 To: chef@bork.bork.bork, john@test, mary@test
338 From: richard <issue_tracker@your.tracker.email.domain.example>
339 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
340 MIME-Version: 1.0
341 Message-Id: <followup_dummy_id>
342 In-Reply-To: <dummy_test_message_id>
343 X-Roundup-Name: Roundup issue tracker
344 X-Roundup-Loop: hello
345 Content-Transfer-Encoding: quoted-printable
348 richard <richard@test> added the comment:
350 This is a followup
352 ----------
353 assignedto:  -> mary
354 nosy: +john, mary
355 status: unread -> chatting
356 _______________________________________________________________________
357 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
358 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
359 _______________________________________________________________________
360 ''')
362     def testFollowupTitleMatch(self):
363         self.doNewIssue()
364         message = StringIO('''Content-Type: text/plain;
365   charset="iso-8859-1"
366 From: richard <richard@test>
367 To: issue_tracker@your.tracker.email.domain.example
368 Message-Id: <followup_dummy_id>
369 In-Reply-To: <dummy_test_message_id>
370 Subject: Re: Testing... [assignedto=mary; nosy=+john]
372 This is a followup
373 ''')
374         handler = self.instance.MailGW(self.instance, self.db)
375         handler.trapExceptions = 0
376         handler.main(message)
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
402 _______________________________________________________________________
403 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
404 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
405 _______________________________________________________________________
406 ''')
408     def testFollowupNosyAuthor(self):
409         self.doNewIssue()
410         self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
411         message = StringIO('''Content-Type: text/plain;
412   charset="iso-8859-1"
413 From: john@test
414 To: issue_tracker@your.tracker.email.domain.example
415 Message-Id: <followup_dummy_id>
416 In-Reply-To: <dummy_test_message_id>
417 Subject: [issue1] Testing...
419 This is a followup
420 ''')
421         handler = self.instance.MailGW(self.instance, self.db)
422         handler.trapExceptions = 0
423         handler.main(message)
425         self.compareMessages(self._get_mail(),
426 '''FROM: roundup-admin@your.tracker.email.domain.example
427 TO: chef@bork.bork.bork, richard@test
428 Content-Type: text/plain; charset=utf-8
429 Subject: [issue1] Testing...
430 To: chef@bork.bork.bork, richard@test
431 From: John Doe <issue_tracker@your.tracker.email.domain.example>
432 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
433 MIME-Version: 1.0
434 Message-Id: <followup_dummy_id>
435 In-Reply-To: <dummy_test_message_id>
436 X-Roundup-Name: Roundup issue tracker
437 X-Roundup-Loop: hello
438 Content-Transfer-Encoding: quoted-printable
441 John Doe <john@test> added the comment:
443 This is a followup
445 ----------
446 nosy: +john
447 status: unread -> chatting
448 _______________________________________________________________________
449 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
450 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
451 _______________________________________________________________________
453 ''')
455     def testFollowupNosyRecipients(self):
456         self.doNewIssue()
457         self.db.config.ADD_RECIPIENTS_TO_NOSY = 'yes'
458         message = StringIO('''Content-Type: text/plain;
459   charset="iso-8859-1"
460 From: richard@test
461 To: issue_tracker@your.tracker.email.domain.example
462 Cc: john@test
463 Message-Id: <followup_dummy_id>
464 In-Reply-To: <dummy_test_message_id>
465 Subject: [issue1] Testing...
467 This is a followup
468 ''')
469         handler = self.instance.MailGW(self.instance, self.db)
470         handler.trapExceptions = 0
471         handler.main(message)
473         self.compareMessages(self._get_mail(),
474 '''FROM: roundup-admin@your.tracker.email.domain.example
475 TO: chef@bork.bork.bork
476 Content-Type: text/plain; charset=utf-8
477 Subject: [issue1] Testing...
478 To: chef@bork.bork.bork
479 From: richard <issue_tracker@your.tracker.email.domain.example>
480 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
481 MIME-Version: 1.0
482 Message-Id: <followup_dummy_id>
483 In-Reply-To: <dummy_test_message_id>
484 X-Roundup-Name: Roundup issue tracker
485 X-Roundup-Loop: hello
486 Content-Transfer-Encoding: quoted-printable
489 richard <richard@test> added the comment:
491 This is a followup
493 ----------
494 nosy: +john
495 status: unread -> chatting
496 _______________________________________________________________________
497 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
498 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
499 _______________________________________________________________________
501 ''')
503     def testFollowupNosyAuthorAndCopy(self):
504         self.doNewIssue()
505         self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
506         self.db.config.MESSAGES_TO_AUTHOR = 'yes'
507         message = StringIO('''Content-Type: text/plain;
508   charset="iso-8859-1"
509 From: john@test
510 To: issue_tracker@your.tracker.email.domain.example
511 Message-Id: <followup_dummy_id>
512 In-Reply-To: <dummy_test_message_id>
513 Subject: [issue1] Testing...
515 This is a followup
516 ''')
517         handler = self.instance.MailGW(self.instance, self.db)
518         handler.trapExceptions = 0
519         handler.main(message)
521         self.compareMessages(self._get_mail(),
522 '''FROM: roundup-admin@your.tracker.email.domain.example
523 TO: chef@bork.bork.bork, john@test, richard@test
524 Content-Type: text/plain; charset=utf-8
525 Subject: [issue1] Testing...
526 To: chef@bork.bork.bork, john@test, richard@test
527 From: John Doe <issue_tracker@your.tracker.email.domain.example>
528 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
529 MIME-Version: 1.0
530 Message-Id: <followup_dummy_id>
531 In-Reply-To: <dummy_test_message_id>
532 X-Roundup-Name: Roundup issue tracker
533 X-Roundup-Loop: hello
534 Content-Transfer-Encoding: quoted-printable
537 John Doe <john@test> added the comment:
539 This is a followup
541 ----------
542 nosy: +john
543 status: unread -> chatting
544 _______________________________________________________________________
545 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
546 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
547 _______________________________________________________________________
549 ''')
551     def testFollowupNoNosyAuthor(self):
552         self.doNewIssue()
553         self.instance.config.ADD_AUTHOR_TO_NOSY = 'no'
554         message = StringIO('''Content-Type: text/plain;
555   charset="iso-8859-1"
556 From: john@test
557 To: issue_tracker@your.tracker.email.domain.example
558 Message-Id: <followup_dummy_id>
559 In-Reply-To: <dummy_test_message_id>
560 Subject: [issue1] Testing...
562 This is a followup
563 ''')
564         handler = self.instance.MailGW(self.instance, self.db)
565         handler.trapExceptions = 0
566         handler.main(message)
568         self.compareMessages(self._get_mail(),
569 '''FROM: roundup-admin@your.tracker.email.domain.example
570 TO: chef@bork.bork.bork, richard@test
571 Content-Type: text/plain; charset=utf-8
572 Subject: [issue1] Testing...
573 To: chef@bork.bork.bork, richard@test
574 From: John Doe <issue_tracker@your.tracker.email.domain.example>
575 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
576 MIME-Version: 1.0
577 Message-Id: <followup_dummy_id>
578 In-Reply-To: <dummy_test_message_id>
579 X-Roundup-Name: Roundup issue tracker
580 X-Roundup-Loop: hello
581 Content-Transfer-Encoding: quoted-printable
584 John Doe <john@test> added the comment:
586 This is a followup
588 ----------
589 status: unread -> chatting
590 _______________________________________________________________________
591 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
592 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
593 _______________________________________________________________________
595 ''')
597     def testFollowupNoNosyRecipients(self):
598         self.doNewIssue()
599         self.instance.config.ADD_RECIPIENTS_TO_NOSY = 'no'
600         message = StringIO('''Content-Type: text/plain;
601   charset="iso-8859-1"
602 From: richard@test
603 To: issue_tracker@your.tracker.email.domain.example
604 Cc: john@test
605 Message-Id: <followup_dummy_id>
606 In-Reply-To: <dummy_test_message_id>
607 Subject: [issue1] Testing...
609 This is a followup
610 ''')
611         handler = self.instance.MailGW(self.instance, self.db)
612         handler.trapExceptions = 0
613         handler.main(message)
615         self.compareMessages(self._get_mail(),
616 '''FROM: roundup-admin@your.tracker.email.domain.example
617 TO: chef@bork.bork.bork
618 Content-Type: text/plain; charset=utf-8
619 Subject: [issue1] Testing...
620 To: chef@bork.bork.bork
621 From: richard <issue_tracker@your.tracker.email.domain.example>
622 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
623 MIME-Version: 1.0
624 Message-Id: <followup_dummy_id>
625 In-Reply-To: <dummy_test_message_id>
626 X-Roundup-Name: Roundup issue tracker
627 X-Roundup-Loop: hello
628 Content-Transfer-Encoding: quoted-printable
631 richard <richard@test> added the comment:
633 This is a followup
635 ----------
636 status: unread -> chatting
637 _______________________________________________________________________
638 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
639 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
640 _______________________________________________________________________
642 ''')
644     def testFollowupEmptyMessage(self):
645         self.doNewIssue()
647         message = StringIO('''Content-Type: text/plain;
648   charset="iso-8859-1"
649 From: richard <richard@test>
650 To: issue_tracker@your.tracker.email.domain.example
651 Message-Id: <followup_dummy_id>
652 In-Reply-To: <dummy_test_message_id>
653 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
655 ''')
656         handler = self.instance.MailGW(self.instance, self.db)
657         handler.trapExceptions = 0
658         handler.main(message)
659         l = self.db.issue.get('1', 'nosy')
660         l.sort()
661         self.assertEqual(l, ['3', '4', '5', '6'])
663         # should be no file created (ie. no message)
664         assert not os.path.exists(SENDMAILDEBUG)
666     def testNosyRemove(self):
667         self.doNewIssue()
669         message = StringIO('''Content-Type: text/plain;
670   charset="iso-8859-1"
671 From: richard <richard@test>
672 To: issue_tracker@your.tracker.email.domain.example
673 Message-Id: <followup_dummy_id>
674 In-Reply-To: <dummy_test_message_id>
675 Subject: [issue1] Testing... [nosy=-richard]
677 ''')
678         handler = self.instance.MailGW(self.instance, self.db)
679         handler.trapExceptions = 0
680         handler.main(message)
681         l = self.db.issue.get('1', 'nosy')
682         l.sort()
683         self.assertEqual(l, ['3'])
685         # NO NOSY MESSAGE SHOULD BE SENT!
686         assert not os.path.exists(SENDMAILDEBUG)
688     def testNewUserAuthor(self):
689         # first without the permission
690         # heh... just ignore the API for a second ;)
691         self.db.security.role['anonymous'].permissions=[]
692         anonid = self.db.user.lookup('anonymous')
693         self.db.user.set(anonid, roles='Anonymous')
695         self.db.security.hasPermission('Email Registration', anonid)
696         l = self.db.user.list()
697         l.sort()
698         s = '''Content-Type: text/plain;
699   charset="iso-8859-1"
700 From: fubar <fubar@bork.bork.bork>
701 To: issue_tracker@your.tracker.email.domain.example
702 Message-Id: <dummy_test_message_id>
703 Subject: [issue] Testing...
705 This is a test submission of a new issue.
706 '''
707         message = StringIO(s)
708         handler = self.instance.MailGW(self.instance, self.db)
709         handler.trapExceptions = 0
710         self.assertRaises(Unauthorized, handler.main, message)
711         m = self.db.user.list()
712         m.sort()
713         self.assertEqual(l, m)
715         # now with the permission
716         p = self.db.security.getPermission('Email Registration')
717         self.db.security.role['anonymous'].permissions=[p]
718         handler = self.instance.MailGW(self.instance, self.db)
719         handler.trapExceptions = 0
720         message = StringIO(s)
721         handler.main(message)
722         m = self.db.user.list()
723         m.sort()
724         self.assertNotEqual(l, m)
726     def testEnc01(self):
727         self.doNewIssue()
728         message = StringIO('''Content-Type: text/plain;
729   charset="iso-8859-1"
730 From: mary <mary@test>
731 To: issue_tracker@your.tracker.email.domain.example
732 Message-Id: <followup_dummy_id>
733 In-Reply-To: <dummy_test_message_id>
734 Subject: [issue1] Testing...
735 Content-Type: text/plain;
736         charset="iso-8859-1"
737 Content-Transfer-Encoding: quoted-printable
739 A message with encoding (encoded oe =F6)
741 ''')
742         handler = self.instance.MailGW(self.instance, self.db)
743         handler.trapExceptions = 0
744         handler.main(message)
745         self.compareMessages(self._get_mail(),
746 '''FROM: roundup-admin@your.tracker.email.domain.example
747 TO: chef@bork.bork.bork, richard@test
748 Content-Type: text/plain; charset=utf-8
749 Subject: [issue1] Testing...
750 To: chef@bork.bork.bork, richard@test
751 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
752 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
753 MIME-Version: 1.0
754 Message-Id: <followup_dummy_id>
755 In-Reply-To: <dummy_test_message_id>
756 X-Roundup-Name: Roundup issue tracker
757 X-Roundup-Loop: hello
758 Content-Transfer-Encoding: quoted-printable
761 Contrary, Mary <mary@test> added the comment:
763 A message with encoding (encoded oe =C3=B6)
765 ----------
766 status: unread -> chatting
767 _______________________________________________________________________
768 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
769 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
770 _______________________________________________________________________
771 ''')
774     def testMultipartEnc01(self):
775         self.doNewIssue()
776         message = StringIO('''Content-Type: text/plain;
777   charset="iso-8859-1"
778 From: mary <mary@test>
779 To: issue_tracker@your.tracker.email.domain.example
780 Message-Id: <followup_dummy_id>
781 In-Reply-To: <dummy_test_message_id>
782 Subject: [issue1] Testing...
783 Content-Type: multipart/mixed;
784         boundary="----_=_NextPart_000_01"
786 This message is in MIME format. Since your mail reader does not understand
787 this format, some or all of this message may not be legible.
789 ------_=_NextPart_000_01
790 Content-Type: text/plain;
791         charset="iso-8859-1"
792 Content-Transfer-Encoding: quoted-printable
794 A message with first part encoded (encoded oe =F6)
796 ''')
797         handler = self.instance.MailGW(self.instance, self.db)
798         handler.trapExceptions = 0
799         handler.main(message)
800         self.compareMessages(self._get_mail(),
801 '''FROM: roundup-admin@your.tracker.email.domain.example
802 TO: chef@bork.bork.bork, richard@test
803 Content-Type: text/plain; charset=utf-8
804 Subject: [issue1] Testing...
805 To: chef@bork.bork.bork, richard@test
806 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
807 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
808 MIME-Version: 1.0
809 Message-Id: <followup_dummy_id>
810 In-Reply-To: <dummy_test_message_id>
811 X-Roundup-Name: Roundup issue tracker
812 X-Roundup-Loop: hello
813 Content-Transfer-Encoding: quoted-printable
816 Contrary, Mary <mary@test> added the comment:
818 A message with first part encoded (encoded oe =C3=B6)
820 ----------
821 status: unread -> chatting
822 _______________________________________________________________________
823 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
824 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
825 _______________________________________________________________________
826 ''')
828     def testContentDisposition(self):
829         self.doNewIssue()
830         message = StringIO('''Content-Type: text/plain;
831   charset="iso-8859-1"
832 From: mary <mary@test>
833 To: issue_tracker@your.tracker.email.domain.example
834 Message-Id: <followup_dummy_id>
835 In-Reply-To: <dummy_test_message_id>
836 Subject: [issue1] Testing...
837 Content-Type: multipart/mixed; boundary="bCsyhTFzCvuiizWE" 
838 Content-Disposition: inline 
839  
840  
841 --bCsyhTFzCvuiizWE 
842 Content-Type: text/plain; charset=us-ascii 
843 Content-Disposition: inline 
845 test attachment binary 
847 --bCsyhTFzCvuiizWE 
848 Content-Type: application/octet-stream 
849 Content-Disposition: attachment; filename="main.dvi" 
851 xxxxxx 
853 --bCsyhTFzCvuiizWE--
854 ''')
855         handler = self.instance.MailGW(self.instance, self.db)
856         handler.trapExceptions = 0
857         handler.main(message)
858         messages = self.db.issue.get('1', 'messages')
859         messages.sort()
860         file = self.db.msg.get(messages[-1], 'files')[0]
861         self.assertEqual(self.db.file.get(file, 'name'), 'main.dvi')
863     def testFollowupStupidQuoting(self):
864         self.doNewIssue()
866         message = StringIO('''Content-Type: text/plain;
867   charset="iso-8859-1"
868 From: richard <richard@test>
869 To: issue_tracker@your.tracker.email.domain.example
870 Message-Id: <followup_dummy_id>
871 In-Reply-To: <dummy_test_message_id>
872 Subject: Re: "[issue1] Testing... "
874 This is a followup
875 ''')
876         handler = self.instance.MailGW(self.instance, self.db)
877         handler.trapExceptions = 0
878         handler.main(message)
880         self.compareMessages(self._get_mail(),
881 '''FROM: roundup-admin@your.tracker.email.domain.example
882 TO: chef@bork.bork.bork
883 Content-Type: text/plain; charset=utf-8
884 Subject: [issue1] Testing...
885 To: chef@bork.bork.bork
886 From: richard <issue_tracker@your.tracker.email.domain.example>
887 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
888 MIME-Version: 1.0
889 Message-Id: <followup_dummy_id>
890 In-Reply-To: <dummy_test_message_id>
891 X-Roundup-Name: Roundup issue tracker
892 X-Roundup-Loop: hello
893 Content-Transfer-Encoding: quoted-printable
896 richard <richard@test> added the comment:
898 This is a followup
900 ----------
901 status: unread -> chatting
902 _______________________________________________________________________
903 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
904 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
905 _______________________________________________________________________
906 ''')
908     def testEmailQuoting(self):
909         self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
910         self.innerTestQuoting('''This is a followup
911 ''')
913     def testEmailQuotingRemove(self):
914         self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
915         self.innerTestQuoting('''Blah blah wrote:
916 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
917 >  skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
920 This is a followup
921 ''')
923     def innerTestQuoting(self, expect):
924         nodeid = self.doNewIssue()
926         messages = self.db.issue.get(nodeid, 'messages')
928         message = StringIO('''Content-Type: text/plain;
929   charset="iso-8859-1"
930 From: richard <richard@test>
931 To: issue_tracker@your.tracker.email.domain.example
932 Message-Id: <followup_dummy_id>
933 In-Reply-To: <dummy_test_message_id>
934 Subject: Re: [issue1] Testing...
936 Blah blah wrote:
937 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
938 >  skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
941 This is a followup
942 ''')
943         handler = self.instance.MailGW(self.instance, self.db)
944         handler.trapExceptions = 0
945         handler.main(message)
947         # figure the new message id
948         newmessages = self.db.issue.get(nodeid, 'messages')
949         for msg in messages:
950             newmessages.remove(msg)
951         messageid = newmessages[0]
953         self.compareMessages(self.db.msg.get(messageid, 'content'), expect)
955     def testUserLookup(self):
956         i = self.db.user.create(username='user1', address='user1@foo.com')
957         self.assertEqual(uidFromAddress(self.db, ('', 'user1@foo.com'), 0), i)
958         self.assertEqual(uidFromAddress(self.db, ('', 'USER1@foo.com'), 0), i)
959         i = self.db.user.create(username='user2', address='USER2@foo.com')
960         self.assertEqual(uidFromAddress(self.db, ('', 'USER2@foo.com'), 0), i)
961         self.assertEqual(uidFromAddress(self.db, ('', 'user2@foo.com'), 0), i)
963     def testUserAlternateLookup(self):
964         i = self.db.user.create(username='user1', address='user1@foo.com',
965                                 alternate_addresses='user1@bar.com')
966         self.assertEqual(uidFromAddress(self.db, ('', 'user1@bar.com'), 0), i)
967         self.assertEqual(uidFromAddress(self.db, ('', 'USER1@bar.com'), 0), i)
969     def testUserCreate(self):
970         i = uidFromAddress(self.db, ('', 'user@foo.com'), 1)
971         self.assertNotEqual(uidFromAddress(self.db, ('', 'user@bar.com'), 1), i)
973     def testRFC2822(self):
974         ascii_header = "[issue243] This is a \"test\" - with 'quotation' marks"
975         unicode_header = '[issue244] \xd0\xb0\xd0\xbd\xd0\xb4\xd1\x80\xd0\xb5\xd0\xb9'
976         unicode_encoded = '=?utf-8?q?[issue244]_=D0=B0=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?='
977         self.assertEqual(rfc2822.encode_header(ascii_header), ascii_header)
978         self.assertEqual(rfc2822.encode_header(unicode_header), unicode_encoded)
980     def testRegistrationConfirmation(self):
981         otk = "Aj4euk4LZSAdwePohj90SME5SpopLETL"
982         self.db.otks.set(otk, username='johannes', __time='')
983         message = StringIO('''Content-Type: text/plain;
984   charset="iso-8859-1"
985 From: Chef <chef@bork.bork.bork>
986 To: issue_tracker@your.tracker.email.domain.example
987 Cc: richard@test
988 Message-Id: <dummy_test_message_id>
989 Subject: Re: Complete your registration to Roundup issue tracker\r
990  -- key %s
992 This is a test confirmation of registration.
993 ''' % otk)
994         handler = self.instance.MailGW(self.instance, self.db)
995         handler.trapExceptions = 0
996         handler.main(message)
998         self.db.user.lookup('johannes')
1000     def testFollowupOnNonIssue(self):
1001         self.db.keyword.create(name='Foo')
1002         message = StringIO('''Content-Type: text/plain;
1003   charset="iso-8859-1"
1004 From: richard <richard@test>
1005 To: issue_tracker@your.tracker.email.domain.example
1006 Message-Id: <followup_dummy_id>
1007 In-Reply-To: <dummy_test_message_id>
1008 Subject: [keyword1] Testing... [name=Bar]
1010 ''')
1011         handler = self.instance.MailGW(self.instance, self.db)
1012         handler.trapExceptions = 0
1013         handler.main(message)
1014         
1015         self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1016     
1017 def test_suite():
1018     suite = unittest.TestSuite()
1019     suite.addTest(unittest.makeSuite(MailgwTestCase))
1020     return suite
1022 if __name__ == '__main__':
1023     runner = unittest.TextTestRunner()
1024     unittest.main(testRunner=runner)
1026 # vim: set filetype=python ts=4 sw=4 et si