Code

*** empty log message ***
[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.64 2004-01-20 00:11:51 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, 'anydbm')
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         return handler.main(StringIO(message))
133         
134     def _get_mail(self):
135         f = open(SENDMAILDEBUG)
136         try:
137             return f.read()
138         finally:
139             f.close()
141     def testEmptyMessage(self):
142         nodeid = self._handle_mail('''Content-Type: text/plain;
143   charset="iso-8859-1"
144 From: Chef <chef@bork.bork.bork>
145 To: issue_tracker@your.tracker.email.domain.example
146 Cc: richard@test
147 Reply-To: chef@bork.bork.bork
148 Message-Id: <dummy_test_message_id>
149 Subject: [issue] Testing...
151 ''')
152         assert not os.path.exists(SENDMAILDEBUG)
153         self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
155     def doNewIssue(self):
156         nodeid = self._handle_mail('''Content-Type: text/plain;
157   charset="iso-8859-1"
158 From: Chef <chef@bork.bork.bork>
159 To: issue_tracker@your.tracker.email.domain.example
160 Cc: richard@test
161 Message-Id: <dummy_test_message_id>
162 Subject: [issue] Testing...
164 This is a test submission of a new issue.
165 ''')
166         assert not os.path.exists(SENDMAILDEBUG)
167         l = self.db.issue.get(nodeid, 'nosy')
168         l.sort()
169         self.assertEqual(l, [self.chef_id, self.richard_id])
170         return nodeid
172     def testNewIssue(self):
173         self.doNewIssue()
175     def testNewIssueNosy(self):
176         self.instance.config.ADD_AUTHOR_TO_NOSY = 'yes'
177         nodeid = self._handle_mail('''Content-Type: text/plain;
178   charset="iso-8859-1"
179 From: Chef <chef@bork.bork.bork>
180 To: issue_tracker@your.tracker.email.domain.example
181 Cc: richard@test
182 Message-Id: <dummy_test_message_id>
183 Subject: [issue] Testing...
185 This is a test submission of a new issue.
186 ''')
187         assert not os.path.exists(SENDMAILDEBUG)
188         l = self.db.issue.get(nodeid, 'nosy')
189         l.sort()
190         self.assertEqual(l, [self.chef_id, self.richard_id])
192     def testAlternateAddress(self):
193         self._handle_mail('''Content-Type: text/plain;
194   charset="iso-8859-1"
195 From: John Doe <john.doe@test>
196 To: issue_tracker@your.tracker.email.domain.example
197 Message-Id: <dummy_test_message_id>
198 Subject: [issue] Testing...
200 This is a test submission of a new issue.
201 ''')
202         userlist = self.db.user.list()        
203         assert not os.path.exists(SENDMAILDEBUG)
204         self.assertEqual(userlist, self.db.user.list(),
205             "user created when it shouldn't have been")
207     def testNewIssueNoClass(self):
208         self._handle_mail('''Content-Type: text/plain;
209   charset="iso-8859-1"
210 From: Chef <chef@bork.bork.bork>
211 To: issue_tracker@your.tracker.email.domain.example
212 Cc: richard@test
213 Message-Id: <dummy_test_message_id>
214 Subject: Testing...
216 This is a test submission of a new issue.
217 ''')
218         assert not os.path.exists(SENDMAILDEBUG)
220     def testNewIssueAuthMsg(self):
221         # TODO: fix the damn config - this is apalling
222         self.db.config.MESSAGES_TO_AUTHOR = 'yes'
223         self._handle_mail('''Content-Type: text/plain;
224   charset="iso-8859-1"
225 From: Chef <chef@bork.bork.bork>
226 To: issue_tracker@your.tracker.email.domain.example
227 Message-Id: <dummy_test_message_id>
228 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
230 This is a test submission of a new issue.
231 ''')
232         self.compareMessages(self._get_mail(),
233 '''FROM: roundup-admin@your.tracker.email.domain.example
234 TO: chef@bork.bork.bork, mary@test, richard@test
235 Content-Type: text/plain; charset=utf-8
236 Subject: [issue1] Testing...
237 To: chef@bork.bork.bork, mary@test, richard@test
238 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
239 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
240 MIME-Version: 1.0
241 Message-Id: <dummy_test_message_id>
242 X-Roundup-Name: Roundup issue tracker
243 X-Roundup-Loop: hello
244 Content-Transfer-Encoding: quoted-printable
247 New submission from Bork, Chef <chef@bork.bork.bork>:
249 This is a test submission of a new issue.
251 ----------
252 assignedto: richard
253 messages: 1
254 nosy: Chef, mary, richard
255 status: unread
256 title: Testing...
257 _______________________________________________________________________
258 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
259 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
260 _______________________________________________________________________
261 ''')
263     # BUG
264     # def testMultipart(self):
265     #         '''With more than one part'''
266     #        see MultipartEnc tests: but if there is more than one part
267     #        we return a multipart/mixed and the boundary contains
268     #        the ip address of the test machine. 
270     # BUG should test some binary attamchent too.
272     def testSimpleFollowup(self):
273         self.doNewIssue()
274         self._handle_mail('''Content-Type: text/plain;
275   charset="iso-8859-1"
276 From: mary <mary@test>
277 To: issue_tracker@your.tracker.email.domain.example
278 Message-Id: <followup_dummy_id>
279 In-Reply-To: <dummy_test_message_id>
280 Subject: [issue1] Testing...
282 This is a second followup
283 ''')
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         self._handle_mail('''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         l = self.db.issue.get('1', 'nosy')
326         l.sort()
327         self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
328             self.john_id])
330         self.compareMessages(self._get_mail(),
331 '''FROM: roundup-admin@your.tracker.email.domain.example
332 TO: chef@bork.bork.bork, john@test, mary@test
333 Content-Type: text/plain; charset=utf-8
334 Subject: [issue1] Testing...
335 To: chef@bork.bork.bork, john@test, mary@test
336 From: richard <issue_tracker@your.tracker.email.domain.example>
337 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
338 MIME-Version: 1.0
339 Message-Id: <followup_dummy_id>
340 In-Reply-To: <dummy_test_message_id>
341 X-Roundup-Name: Roundup issue tracker
342 X-Roundup-Loop: hello
343 Content-Transfer-Encoding: quoted-printable
346 richard <richard@test> added the comment:
348 This is a followup
350 ----------
351 assignedto:  -> mary
352 nosy: +john, mary
353 status: unread -> chatting
354 _______________________________________________________________________
355 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
356 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
357 _______________________________________________________________________
358 ''')
360     def testFollowupTitleMatch(self):
361         self.doNewIssue()
362         self._handle_mail('''Content-Type: text/plain;
363   charset="iso-8859-1"
364 From: richard <richard@test>
365 To: issue_tracker@your.tracker.email.domain.example
366 Message-Id: <followup_dummy_id>
367 In-Reply-To: <dummy_test_message_id>
368 Subject: Re: Testing... [assignedto=mary; nosy=+john]
370 This is a followup
371 ''')
372         self.compareMessages(self._get_mail(),
373 '''FROM: roundup-admin@your.tracker.email.domain.example
374 TO: chef@bork.bork.bork, john@test, mary@test
375 Content-Type: text/plain; charset=utf-8
376 Subject: [issue1] Testing...
377 To: chef@bork.bork.bork, john@test, mary@test
378 From: richard <issue_tracker@your.tracker.email.domain.example>
379 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
380 MIME-Version: 1.0
381 Message-Id: <followup_dummy_id>
382 In-Reply-To: <dummy_test_message_id>
383 X-Roundup-Name: Roundup issue tracker
384 X-Roundup-Loop: hello
385 Content-Transfer-Encoding: quoted-printable
388 richard <richard@test> added the comment:
390 This is a followup
392 ----------
393 assignedto:  -> mary
394 nosy: +john, mary
395 status: unread -> chatting
396 _______________________________________________________________________
397 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
398 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
399 _______________________________________________________________________
400 ''')
402     def testFollowupNosyAuthor(self):
403         self.doNewIssue()
404         self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
405         self._handle_mail('''Content-Type: text/plain;
406   charset="iso-8859-1"
407 From: john@test
408 To: issue_tracker@your.tracker.email.domain.example
409 Message-Id: <followup_dummy_id>
410 In-Reply-To: <dummy_test_message_id>
411 Subject: [issue1] Testing...
413 This is a followup
414 ''')
416         self.compareMessages(self._get_mail(),
417 '''FROM: roundup-admin@your.tracker.email.domain.example
418 TO: chef@bork.bork.bork, richard@test
419 Content-Type: text/plain; charset=utf-8
420 Subject: [issue1] Testing...
421 To: chef@bork.bork.bork, richard@test
422 From: John Doe <issue_tracker@your.tracker.email.domain.example>
423 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
424 MIME-Version: 1.0
425 Message-Id: <followup_dummy_id>
426 In-Reply-To: <dummy_test_message_id>
427 X-Roundup-Name: Roundup issue tracker
428 X-Roundup-Loop: hello
429 Content-Transfer-Encoding: quoted-printable
432 John Doe <john@test> added the comment:
434 This is a followup
436 ----------
437 nosy: +john
438 status: unread -> chatting
439 _______________________________________________________________________
440 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
441 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
442 _______________________________________________________________________
444 ''')
446     def testFollowupNosyRecipients(self):
447         self.doNewIssue()
448         self.db.config.ADD_RECIPIENTS_TO_NOSY = 'yes'
449         self._handle_mail('''Content-Type: text/plain;
450   charset="iso-8859-1"
451 From: richard@test
452 To: issue_tracker@your.tracker.email.domain.example
453 Cc: john@test
454 Message-Id: <followup_dummy_id>
455 In-Reply-To: <dummy_test_message_id>
456 Subject: [issue1] Testing...
458 This is a followup
459 ''')
460         self.compareMessages(self._get_mail(),
461 '''FROM: roundup-admin@your.tracker.email.domain.example
462 TO: chef@bork.bork.bork
463 Content-Type: text/plain; charset=utf-8
464 Subject: [issue1] Testing...
465 To: chef@bork.bork.bork
466 From: richard <issue_tracker@your.tracker.email.domain.example>
467 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
468 MIME-Version: 1.0
469 Message-Id: <followup_dummy_id>
470 In-Reply-To: <dummy_test_message_id>
471 X-Roundup-Name: Roundup issue tracker
472 X-Roundup-Loop: hello
473 Content-Transfer-Encoding: quoted-printable
476 richard <richard@test> added the comment:
478 This is a followup
480 ----------
481 nosy: +john
482 status: unread -> chatting
483 _______________________________________________________________________
484 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
485 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
486 _______________________________________________________________________
488 ''')
490     def testFollowupNosyAuthorAndCopy(self):
491         self.doNewIssue()
492         self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
493         self.db.config.MESSAGES_TO_AUTHOR = 'yes'
494         self._handle_mail('''Content-Type: text/plain;
495   charset="iso-8859-1"
496 From: john@test
497 To: issue_tracker@your.tracker.email.domain.example
498 Message-Id: <followup_dummy_id>
499 In-Reply-To: <dummy_test_message_id>
500 Subject: [issue1] Testing...
502 This is a followup
503 ''')
504         self.compareMessages(self._get_mail(),
505 '''FROM: roundup-admin@your.tracker.email.domain.example
506 TO: chef@bork.bork.bork, john@test, richard@test
507 Content-Type: text/plain; charset=utf-8
508 Subject: [issue1] Testing...
509 To: chef@bork.bork.bork, john@test, richard@test
510 From: John Doe <issue_tracker@your.tracker.email.domain.example>
511 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
512 MIME-Version: 1.0
513 Message-Id: <followup_dummy_id>
514 In-Reply-To: <dummy_test_message_id>
515 X-Roundup-Name: Roundup issue tracker
516 X-Roundup-Loop: hello
517 Content-Transfer-Encoding: quoted-printable
520 John Doe <john@test> added the comment:
522 This is a followup
524 ----------
525 nosy: +john
526 status: unread -> chatting
527 _______________________________________________________________________
528 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
529 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
530 _______________________________________________________________________
532 ''')
534     def testFollowupNoNosyAuthor(self):
535         self.doNewIssue()
536         self.instance.config.ADD_AUTHOR_TO_NOSY = 'no'
537         self._handle_mail('''Content-Type: text/plain;
538   charset="iso-8859-1"
539 From: john@test
540 To: issue_tracker@your.tracker.email.domain.example
541 Message-Id: <followup_dummy_id>
542 In-Reply-To: <dummy_test_message_id>
543 Subject: [issue1] Testing...
545 This is a followup
546 ''')
547         self.compareMessages(self._get_mail(),
548 '''FROM: roundup-admin@your.tracker.email.domain.example
549 TO: chef@bork.bork.bork, richard@test
550 Content-Type: text/plain; charset=utf-8
551 Subject: [issue1] Testing...
552 To: chef@bork.bork.bork, richard@test
553 From: John Doe <issue_tracker@your.tracker.email.domain.example>
554 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
555 MIME-Version: 1.0
556 Message-Id: <followup_dummy_id>
557 In-Reply-To: <dummy_test_message_id>
558 X-Roundup-Name: Roundup issue tracker
559 X-Roundup-Loop: hello
560 Content-Transfer-Encoding: quoted-printable
563 John Doe <john@test> added the comment:
565 This is a followup
567 ----------
568 status: unread -> chatting
569 _______________________________________________________________________
570 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
571 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
572 _______________________________________________________________________
574 ''')
576     def testFollowupNoNosyRecipients(self):
577         self.doNewIssue()
578         self.instance.config.ADD_RECIPIENTS_TO_NOSY = 'no'
579         self._handle_mail('''Content-Type: text/plain;
580   charset="iso-8859-1"
581 From: richard@test
582 To: issue_tracker@your.tracker.email.domain.example
583 Cc: john@test
584 Message-Id: <followup_dummy_id>
585 In-Reply-To: <dummy_test_message_id>
586 Subject: [issue1] Testing...
588 This is a followup
589 ''')
590         self.compareMessages(self._get_mail(),
591 '''FROM: roundup-admin@your.tracker.email.domain.example
592 TO: chef@bork.bork.bork
593 Content-Type: text/plain; charset=utf-8
594 Subject: [issue1] Testing...
595 To: chef@bork.bork.bork
596 From: richard <issue_tracker@your.tracker.email.domain.example>
597 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
598 MIME-Version: 1.0
599 Message-Id: <followup_dummy_id>
600 In-Reply-To: <dummy_test_message_id>
601 X-Roundup-Name: Roundup issue tracker
602 X-Roundup-Loop: hello
603 Content-Transfer-Encoding: quoted-printable
606 richard <richard@test> added the comment:
608 This is a followup
610 ----------
611 status: unread -> chatting
612 _______________________________________________________________________
613 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
614 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
615 _______________________________________________________________________
617 ''')
619     def testFollowupEmptyMessage(self):
620         self.doNewIssue()
622         self._handle_mail('''Content-Type: text/plain;
623   charset="iso-8859-1"
624 From: richard <richard@test>
625 To: issue_tracker@your.tracker.email.domain.example
626 Message-Id: <followup_dummy_id>
627 In-Reply-To: <dummy_test_message_id>
628 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
630 ''')
631         l = self.db.issue.get('1', 'nosy')
632         l.sort()
633         self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
634             self.john_id])
636         # should be no file created (ie. no message)
637         assert not os.path.exists(SENDMAILDEBUG)
639     def testNosyRemove(self):
640         self.doNewIssue()
642         self._handle_mail('''Content-Type: text/plain;
643   charset="iso-8859-1"
644 From: richard <richard@test>
645 To: issue_tracker@your.tracker.email.domain.example
646 Message-Id: <followup_dummy_id>
647 In-Reply-To: <dummy_test_message_id>
648 Subject: [issue1] Testing... [nosy=-richard]
650 ''')
651         l = self.db.issue.get('1', 'nosy')
652         l.sort()
653         self.assertEqual(l, [self.chef_id])
655         # NO NOSY MESSAGE SHOULD BE SENT!
656         assert not os.path.exists(SENDMAILDEBUG)
658     def testNewUserAuthor(self):
659         # first without the permission
660         # heh... just ignore the API for a second ;)
661         self.db.security.role['anonymous'].permissions=[]
662         anonid = self.db.user.lookup('anonymous')
663         self.db.user.set(anonid, roles='Anonymous')
665         self.db.security.hasPermission('Email Registration', anonid)
666         l = self.db.user.list()
667         l.sort()
668         message = '''Content-Type: text/plain;
669   charset="iso-8859-1"
670 From: fubar <fubar@bork.bork.bork>
671 To: issue_tracker@your.tracker.email.domain.example
672 Message-Id: <dummy_test_message_id>
673 Subject: [issue] Testing...
675 This is a test submission of a new issue.
676 '''
677         self.assertRaises(Unauthorized, self._handle_mail, message)
678         m = self.db.user.list()
679         m.sort()
680         self.assertEqual(l, m)
682         # now with the permission
683         p = self.db.security.getPermission('Email Registration')
684         self.db.security.role['anonymous'].permissions=[p]
685         self._handle_mail(message)
686         m = self.db.user.list()
687         m.sort()
688         self.assertNotEqual(l, m)
690     def testEnc01(self):
691         self.doNewIssue()
692         self._handle_mail('''Content-Type: text/plain;
693   charset="iso-8859-1"
694 From: mary <mary@test>
695 To: issue_tracker@your.tracker.email.domain.example
696 Message-Id: <followup_dummy_id>
697 In-Reply-To: <dummy_test_message_id>
698 Subject: [issue1] Testing...
699 Content-Type: text/plain;
700         charset="iso-8859-1"
701 Content-Transfer-Encoding: quoted-printable
703 A message with encoding (encoded oe =F6)
705 ''')
706         self.compareMessages(self._get_mail(),
707 '''FROM: roundup-admin@your.tracker.email.domain.example
708 TO: chef@bork.bork.bork, richard@test
709 Content-Type: text/plain; charset=utf-8
710 Subject: [issue1] Testing...
711 To: chef@bork.bork.bork, richard@test
712 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
713 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
714 MIME-Version: 1.0
715 Message-Id: <followup_dummy_id>
716 In-Reply-To: <dummy_test_message_id>
717 X-Roundup-Name: Roundup issue tracker
718 X-Roundup-Loop: hello
719 Content-Transfer-Encoding: quoted-printable
722 Contrary, Mary <mary@test> added the comment:
724 A message with encoding (encoded oe =C3=B6)
726 ----------
727 status: unread -> chatting
728 _______________________________________________________________________
729 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
730 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
731 _______________________________________________________________________
732 ''')
735     def testMultipartEnc01(self):
736         self.doNewIssue()
737         self._handle_mail('''Content-Type: text/plain;
738   charset="iso-8859-1"
739 From: mary <mary@test>
740 To: issue_tracker@your.tracker.email.domain.example
741 Message-Id: <followup_dummy_id>
742 In-Reply-To: <dummy_test_message_id>
743 Subject: [issue1] Testing...
744 Content-Type: multipart/mixed;
745         boundary="----_=_NextPart_000_01"
747 This message is in MIME format. Since your mail reader does not understand
748 this format, some or all of this message may not be legible.
750 ------_=_NextPart_000_01
751 Content-Type: text/plain;
752         charset="iso-8859-1"
753 Content-Transfer-Encoding: quoted-printable
755 A message with first part encoded (encoded oe =F6)
757 ''')
758         self.compareMessages(self._get_mail(),
759 '''FROM: roundup-admin@your.tracker.email.domain.example
760 TO: chef@bork.bork.bork, richard@test
761 Content-Type: text/plain; charset=utf-8
762 Subject: [issue1] Testing...
763 To: chef@bork.bork.bork, richard@test
764 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
765 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
766 MIME-Version: 1.0
767 Message-Id: <followup_dummy_id>
768 In-Reply-To: <dummy_test_message_id>
769 X-Roundup-Name: Roundup issue tracker
770 X-Roundup-Loop: hello
771 Content-Transfer-Encoding: quoted-printable
774 Contrary, Mary <mary@test> added the comment:
776 A message with first part encoded (encoded oe =C3=B6)
778 ----------
779 status: unread -> chatting
780 _______________________________________________________________________
781 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
782 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
783 _______________________________________________________________________
784 ''')
786     def testContentDisposition(self):
787         self.doNewIssue()
788         self._handle_mail('''Content-Type: text/plain;
789   charset="iso-8859-1"
790 From: mary <mary@test>
791 To: issue_tracker@your.tracker.email.domain.example
792 Message-Id: <followup_dummy_id>
793 In-Reply-To: <dummy_test_message_id>
794 Subject: [issue1] Testing...
795 Content-Type: multipart/mixed; boundary="bCsyhTFzCvuiizWE" 
796 Content-Disposition: inline 
797  
798  
799 --bCsyhTFzCvuiizWE 
800 Content-Type: text/plain; charset=us-ascii 
801 Content-Disposition: inline 
803 test attachment binary 
805 --bCsyhTFzCvuiizWE 
806 Content-Type: application/octet-stream 
807 Content-Disposition: attachment; filename="main.dvi" 
809 xxxxxx 
811 --bCsyhTFzCvuiizWE--
812 ''')
813         messages = self.db.issue.get('1', 'messages')
814         messages.sort()
815         file = self.db.msg.get(messages[-1], 'files')[0]
816         self.assertEqual(self.db.file.get(file, 'name'), 'main.dvi')
818     def testFollowupStupidQuoting(self):
819         self.doNewIssue()
821         self._handle_mail('''Content-Type: text/plain;
822   charset="iso-8859-1"
823 From: richard <richard@test>
824 To: issue_tracker@your.tracker.email.domain.example
825 Message-Id: <followup_dummy_id>
826 In-Reply-To: <dummy_test_message_id>
827 Subject: Re: "[issue1] Testing... "
829 This is a followup
830 ''')
831         self.compareMessages(self._get_mail(),
832 '''FROM: roundup-admin@your.tracker.email.domain.example
833 TO: chef@bork.bork.bork
834 Content-Type: text/plain; charset=utf-8
835 Subject: [issue1] Testing...
836 To: chef@bork.bork.bork
837 From: richard <issue_tracker@your.tracker.email.domain.example>
838 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
839 MIME-Version: 1.0
840 Message-Id: <followup_dummy_id>
841 In-Reply-To: <dummy_test_message_id>
842 X-Roundup-Name: Roundup issue tracker
843 X-Roundup-Loop: hello
844 Content-Transfer-Encoding: quoted-printable
847 richard <richard@test> added the comment:
849 This is a followup
851 ----------
852 status: unread -> chatting
853 _______________________________________________________________________
854 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
855 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
856 _______________________________________________________________________
857 ''')
859     def testEmailQuoting(self):
860         self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
861         self.innerTestQuoting('''This is a followup
862 ''')
864     def testEmailQuotingRemove(self):
865         self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
866         self.innerTestQuoting('''Blah blah wrote:
867 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
868 >  skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
871 This is a followup
872 ''')
874     def innerTestQuoting(self, expect):
875         nodeid = self.doNewIssue()
877         messages = self.db.issue.get(nodeid, 'messages')
879         self._handle_mail('''Content-Type: text/plain;
880   charset="iso-8859-1"
881 From: richard <richard@test>
882 To: issue_tracker@your.tracker.email.domain.example
883 Message-Id: <followup_dummy_id>
884 In-Reply-To: <dummy_test_message_id>
885 Subject: Re: [issue1] Testing...
887 Blah blah wrote:
888 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
889 >  skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
892 This is a followup
893 ''')
894         # figure the new message id
895         newmessages = self.db.issue.get(nodeid, 'messages')
896         for msg in messages:
897             newmessages.remove(msg)
898         messageid = newmessages[0]
900         self.compareMessages(self.db.msg.get(messageid, 'content'), expect)
902     def testUserLookup(self):
903         i = self.db.user.create(username='user1', address='user1@foo.com')
904         self.assertEqual(uidFromAddress(self.db, ('', 'user1@foo.com'), 0), i)
905         self.assertEqual(uidFromAddress(self.db, ('', 'USER1@foo.com'), 0), i)
906         i = self.db.user.create(username='user2', address='USER2@foo.com')
907         self.assertEqual(uidFromAddress(self.db, ('', 'USER2@foo.com'), 0), i)
908         self.assertEqual(uidFromAddress(self.db, ('', 'user2@foo.com'), 0), i)
910     def testUserAlternateLookup(self):
911         i = self.db.user.create(username='user1', address='user1@foo.com',
912                                 alternate_addresses='user1@bar.com')
913         self.assertEqual(uidFromAddress(self.db, ('', 'user1@bar.com'), 0), i)
914         self.assertEqual(uidFromAddress(self.db, ('', 'USER1@bar.com'), 0), i)
916     def testUserCreate(self):
917         i = uidFromAddress(self.db, ('', 'user@foo.com'), 1)
918         self.assertNotEqual(uidFromAddress(self.db, ('', 'user@bar.com'), 1), i)
920     def testRFC2822(self):
921         ascii_header = "[issue243] This is a \"test\" - with 'quotation' marks"
922         unicode_header = '[issue244] \xd0\xb0\xd0\xbd\xd0\xb4\xd1\x80\xd0\xb5\xd0\xb9'
923         unicode_encoded = '=?utf-8?q?[issue244]_=D0=B0=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?='
924         self.assertEqual(rfc2822.encode_header(ascii_header), ascii_header)
925         self.assertEqual(rfc2822.encode_header(unicode_header), unicode_encoded)
927     def testRegistrationConfirmation(self):
928         otk = "Aj4euk4LZSAdwePohj90SME5SpopLETL"
929         self.db.otks.set(otk, username='johannes', __time='')
930         self._handle_mail('''Content-Type: text/plain;
931   charset="iso-8859-1"
932 From: Chef <chef@bork.bork.bork>
933 To: issue_tracker@your.tracker.email.domain.example
934 Cc: richard@test
935 Message-Id: <dummy_test_message_id>
936 Subject: Re: Complete your registration to Roundup issue tracker\r
937  -- key %s
939 This is a test confirmation of registration.
940 ''' % otk)
941         self.db.user.lookup('johannes')
943     def testFollowupOnNonIssue(self):
944         self.db.keyword.create(name='Foo')
945         self._handle_mail('''Content-Type: text/plain;
946   charset="iso-8859-1"
947 From: richard <richard@test>
948 To: issue_tracker@your.tracker.email.domain.example
949 Message-Id: <followup_dummy_id>
950 In-Reply-To: <dummy_test_message_id>
951 Subject: [keyword1] Testing... [name=Bar]
953 ''')        
954         self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
956     def testResentFrom(self):
957         nodeid = self._handle_mail('''Content-Type: text/plain;
958   charset="iso-8859-1"
959 From: Chef <chef@bork.bork.bork>
960 Resent-From: mary <mary@test>
961 To: issue_tracker@your.tracker.email.domain.example
962 Cc: richard@test
963 Message-Id: <dummy_test_message_id>
964 Subject: [issue] Testing...
966 This is a test submission of a new issue.
967 ''')
968         assert not os.path.exists(SENDMAILDEBUG)
969         l = self.db.issue.get(nodeid, 'nosy')
970         l.sort()
971         self.assertEqual(l, [self.richard_id, self.mary_id])
972         return nodeid
975     def testDejaVu(self):
976         self.assertRaises(IgnoreLoop, self._handle_mail,
977             '''Content-Type: text/plain;
978   charset="iso-8859-1"
979 From: Chef <chef@bork.bork.bork>
980 X-Roundup-Loop: hello
981 To: issue_tracker@your.tracker.email.domain.example
982 Cc: richard@test
983 Message-Id: <dummy_test_message_id>
984 Subject: Re: [issue] Testing...
986 Hi, I've been mis-configured to loop messages back to myself.
987 ''')
989     def testItsBulkStupid(self):
990         self.assertRaises(IgnoreBulk, self._handle_mail,
991             '''Content-Type: text/plain;
992   charset="iso-8859-1"
993 From: Chef <chef@bork.bork.bork>
994 Precedence: bulk
995 To: issue_tracker@your.tracker.email.domain.example
996 Cc: richard@test
997 Message-Id: <dummy_test_message_id>
998 Subject: Re: [issue] Testing...
1000 Hi, I'm on holidays, and this is a dumb auto-responder.
1001 ''')
1003 def test_suite():
1004     suite = unittest.TestSuite()
1005     suite.addTest(unittest.makeSuite(MailgwTestCase))
1006     return suite
1008 if __name__ == '__main__':
1009     runner = unittest.TextTestRunner()
1010     unittest.main(testRunner=runner)
1012 # vim: set filetype=python ts=4 sw=4 et si