Code

Make signature matching more precise: only match '-- ' (note the
[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.54 2003-10-24 14:59:38 jlgijsbers Exp $
13 import unittest, tempfile, os, shutil, errno, imp, sys, difflib, rfc822
15 from cStringIO import StringIO
17 from roundup.mailgw import MailGW, Unauthorized, uidFromAddress, parseContent
18 from roundup import init, instance, rfc2822
20 NEEDS_INSTANCE = 1
22 class Message(rfc822.Message):
23     """String-based Message class with equivalence test."""
24     def __init__(self, s):
25         rfc822.Message.__init__(self, StringIO(s.strip()))
26         
27     def __eq__(self, other):
28         del self['date'], other['date']
30         return (self.dict == other.dict and
31                 self.fp.read() == other.fp.read()) 
33 # TODO: Do a semantic diff instead of a straight text diff when a test fails.
34 class DiffHelper:
35     def compareMessages(self, s2, s1):
36         """Compare messages for semantic equivalence."""
37         if not Message(s2) == Message(s1):    
38             self.compareStrings(s2, s1)
39     
40     def compareStrings(self, s2, s1):
41         '''Note the reversal of s2 and s1 - difflib.SequenceMatcher wants
42            the first to be the "original" but in the calls in this file,
43            the second arg is the original. Ho hum.
44         '''
45         # we have to special-case the Date: header here 'cos we can't test
46         # for it properly
47         l1=s1.strip().split('\n')
48         l2=[x for x in s2.strip().split('\n') if not x.startswith('Date: ')]
49         if l1 == l2:
50             return
52         s = difflib.SequenceMatcher(None, l1, l2)
53         res = ['Generated message not correct (diff follows):']
54         for value, s1s, s1e, s2s, s2e in s.get_opcodes():
55             if value == 'equal':
56                 for i in range(s1s, s1e):
57                     res.append('  %s'%l1[i])
58             elif value == 'delete':
59                 for i in range(s1s, s1e):
60                     res.append('- %s'%l1[i])
61             elif value == 'insert':
62                 for i in range(s2s, s2e):
63                     res.append('+ %s'%l2[i])
64             elif value == 'replace':
65                 for i, j in zip(range(s1s, s1e), range(s2s, s2e)):
66                     res.append('- %s'%l1[i])
67                     res.append('+ %s'%l2[j])
69         raise AssertionError, '\n'.join(res)
71 class MailgwTestCase(unittest.TestCase, DiffHelper):
72     count = 0
73     schema = 'classic'
74     def setUp(self):
75         MailgwTestCase.count = MailgwTestCase.count + 1
76         self.dirname = '_test_mailgw_%s'%self.count
77         try:
78             shutil.rmtree(self.dirname)
79         except OSError, error:
80             if error.errno not in (errno.ENOENT, errno.ESRCH): raise
81         # create the instance
82         shutil.copytree('_empty_instance', self.dirname)
83         
84         # check we can load the package
85         self.instance = instance.open(self.dirname)
86         # and open the database
87         self.db = self.instance.open('admin')
88         self.db.user.create(username='Chef', address='chef@bork.bork.bork',
89             realname='Bork, Chef', roles='User')
90         self.db.user.create(username='richard', address='richard@test',
91             roles='User')
92         self.db.user.create(username='mary', address='mary@test',
93             roles='User', realname='Contrary, Mary')
94         self.db.user.create(username='john', address='john@test',
95             alternate_addresses='jondoe@test\njohn.doe@test', roles='User',
96             realname='John Doe')
98     def tearDown(self):
99         if os.path.exists(os.environ['SENDMAILDEBUG']):
100             os.remove(os.environ['SENDMAILDEBUG'])
101         self.db.close()
102         try:
103             shutil.rmtree(self.dirname)
104         except OSError, error:
105             if error.errno not in (errno.ENOENT, errno.ESRCH): raise
107     def testEmptyMessage(self):
108         message = StringIO('''Content-Type: text/plain;
109   charset="iso-8859-1"
110 From: Chef <chef@bork.bork.bork>
111 To: issue_tracker@your.tracker.email.domain.example
112 Cc: richard@test
113 Message-Id: <dummy_test_message_id>
114 Subject: [issue] Testing...
116 ''')
117         handler = self.instance.MailGW(self.instance, self.db)
118         handler.trapExceptions = 0
119         nodeid = handler.main(message)
120         if os.path.exists(os.environ['SENDMAILDEBUG']):
121             error = open(os.environ['SENDMAILDEBUG']).read()
122             self.assertEqual('no error', error)
123         self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
125     def doNewIssue(self):
126         message = StringIO('''Content-Type: text/plain;
127   charset="iso-8859-1"
128 From: Chef <chef@bork.bork.bork>
129 To: issue_tracker@your.tracker.email.domain.example
130 Cc: richard@test
131 Message-Id: <dummy_test_message_id>
132 Subject: [issue] Testing...
134 This is a test submission of a new issue.
135 ''')
136         handler = self.instance.MailGW(self.instance, self.db)
137         handler.trapExceptions = 0
138         nodeid = handler.main(message)
139         if os.path.exists(os.environ['SENDMAILDEBUG']):
140             error = open(os.environ['SENDMAILDEBUG']).read()
141             self.assertEqual('no error', error)
142         l = self.db.issue.get(nodeid, 'nosy')
143         l.sort()
144         self.assertEqual(l, ['3', '4'])
145         return nodeid
147     def testNewIssue(self):
148         self.doNewIssue()
150     def testNewIssueNosy(self):
151         self.instance.config.ADD_AUTHOR_TO_NOSY = 'yes'
152         message = StringIO('''Content-Type: text/plain;
153   charset="iso-8859-1"
154 From: Chef <chef@bork.bork.bork>
155 To: issue_tracker@your.tracker.email.domain.example
156 Cc: richard@test
157 Message-Id: <dummy_test_message_id>
158 Subject: [issue] Testing...
160 This is a test submission of a new issue.
161 ''')
162         handler = self.instance.MailGW(self.instance, self.db)
163         handler.trapExceptions = 0
164         nodeid = handler.main(message)
165         if os.path.exists(os.environ['SENDMAILDEBUG']):
166             error = open(os.environ['SENDMAILDEBUG']).read()
167             self.assertEqual('no error', error)
168         l = self.db.issue.get(nodeid, 'nosy')
169         l.sort()
170         self.assertEqual(l, ['3', '4'])
172     def testAlternateAddress(self):
173         message = StringIO('''Content-Type: text/plain;
174   charset="iso-8859-1"
175 From: John Doe <john.doe@test>
176 To: issue_tracker@your.tracker.email.domain.example
177 Message-Id: <dummy_test_message_id>
178 Subject: [issue] Testing...
180 This is a test submission of a new issue.
181 ''')
182         userlist = self.db.user.list()
183         handler = self.instance.MailGW(self.instance, self.db)
184         handler.trapExceptions = 0
185         handler.main(message)
186         if os.path.exists(os.environ['SENDMAILDEBUG']):
187             error = open(os.environ['SENDMAILDEBUG']).read()
188             self.assertEqual('no error', error)
189         self.assertEqual(userlist, self.db.user.list(),
190             "user created when it shouldn't have been")
192     def testNewIssueNoClass(self):
193         message = StringIO('''Content-Type: text/plain;
194   charset="iso-8859-1"
195 From: Chef <chef@bork.bork.bork>
196 To: issue_tracker@your.tracker.email.domain.example
197 Cc: richard@test
198 Message-Id: <dummy_test_message_id>
199 Subject: Testing...
201 This is a test submission of a new issue.
202 ''')
203         handler = self.instance.MailGW(self.instance, self.db)
204         handler.trapExceptions = 0
205         handler.main(message)
206         if os.path.exists(os.environ['SENDMAILDEBUG']):
207             error = open(os.environ['SENDMAILDEBUG']).read()
208             self.assertEqual('no error', error)
210     def testNewIssueAuthMsg(self):
211         message = StringIO('''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 Message-Id: <dummy_test_message_id>
216 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
218 This is a test submission of a new issue.
219 ''')
220         handler = self.instance.MailGW(self.instance, self.db)
221         handler.trapExceptions = 0
222         # TODO: fix the damn config - this is apalling
223         self.db.config.MESSAGES_TO_AUTHOR = 'yes'
224         handler.main(message)
226         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
227 '''FROM: roundup-admin@your.tracker.email.domain.example
228 TO: chef@bork.bork.bork, mary@test, richard@test
229 Content-Type: text/plain; charset=utf-8
230 Subject: [issue1] Testing...
231 To: chef@bork.bork.bork, mary@test, richard@test
232 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
233 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
234 MIME-Version: 1.0
235 Message-Id: <dummy_test_message_id>
236 X-Roundup-Name: Roundup issue tracker
237 X-Roundup-Loop: hello
238 Content-Transfer-Encoding: quoted-printable
241 New submission from Bork, Chef <chef@bork.bork.bork>:
243 This is a test submission of a new issue.
245 ----------
246 assignedto: richard
247 messages: 1
248 nosy: Chef, mary, richard
249 status: unread
250 title: Testing...
251 _______________________________________________________________________
252 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
253 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
254 _______________________________________________________________________
255 ''')
257     # BUG
258     # def testMultipart(self):
259     #         '''With more than one part'''
260     #        see MultipartEnc tests: but if there is more than one part
261     #        we return a multipart/mixed and the boundary contains
262     #        the ip address of the test machine. 
264     # BUG should test some binary attamchent too.
266     def testSimpleFollowup(self):
267         self.doNewIssue()
268         message = StringIO('''Content-Type: text/plain;
269   charset="iso-8859-1"
270 From: mary <mary@test>
271 To: issue_tracker@your.tracker.email.domain.example
272 Message-Id: <followup_dummy_id>
273 In-Reply-To: <dummy_test_message_id>
274 Subject: [issue1] Testing...
276 This is a second followup
277 ''')
278         handler = self.instance.MailGW(self.instance, self.db)
279         handler.trapExceptions = 0
280         handler.main(message)
281         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
282 '''FROM: roundup-admin@your.tracker.email.domain.example
283 TO: chef@bork.bork.bork, richard@test
284 Content-Type: text/plain; charset=utf-8
285 Subject: [issue1] Testing...
286 To: chef@bork.bork.bork, richard@test
287 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
288 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
289 MIME-Version: 1.0
290 Message-Id: <followup_dummy_id>
291 In-Reply-To: <dummy_test_message_id>
292 X-Roundup-Name: Roundup issue tracker
293 X-Roundup-Loop: hello
294 Content-Transfer-Encoding: quoted-printable
297 Contrary, Mary <mary@test> added the comment:
299 This is a second followup
301 ----------
302 status: unread -> chatting
303 _______________________________________________________________________
304 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
305 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
306 _______________________________________________________________________
307 ''')
309     def testFollowup(self):
310         self.doNewIssue()
312         message = StringIO('''Content-Type: text/plain;
313   charset="iso-8859-1"
314 From: richard <richard@test>
315 To: issue_tracker@your.tracker.email.domain.example
316 Message-Id: <followup_dummy_id>
317 In-Reply-To: <dummy_test_message_id>
318 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
320 This is a followup
321 ''')
322         handler = self.instance.MailGW(self.instance, self.db)
323         handler.trapExceptions = 0
324         handler.main(message)
325         l = self.db.issue.get('1', 'nosy')
326         l.sort()
327         self.assertEqual(l, ['3', '4', '5', '6'])
329         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
330 '''FROM: roundup-admin@your.tracker.email.domain.example
331 TO: chef@bork.bork.bork, john@test, mary@test
332 Content-Type: text/plain; charset=utf-8
333 Subject: [issue1] Testing...
334 To: chef@bork.bork.bork, john@test, mary@test
335 From: richard <issue_tracker@your.tracker.email.domain.example>
336 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
337 MIME-Version: 1.0
338 Message-Id: <followup_dummy_id>
339 In-Reply-To: <dummy_test_message_id>
340 X-Roundup-Name: Roundup issue tracker
341 X-Roundup-Loop: hello
342 Content-Transfer-Encoding: quoted-printable
345 richard <richard@test> added the comment:
347 This is a followup
349 ----------
350 assignedto:  -> mary
351 nosy: +john, mary
352 status: unread -> chatting
353 _______________________________________________________________________
354 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
355 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
356 _______________________________________________________________________
357 ''')
359     def testFollowupTitleMatch(self):
360         self.doNewIssue()
361         message = StringIO('''Content-Type: text/plain;
362   charset="iso-8859-1"
363 From: richard <richard@test>
364 To: issue_tracker@your.tracker.email.domain.example
365 Message-Id: <followup_dummy_id>
366 In-Reply-To: <dummy_test_message_id>
367 Subject: Re: Testing... [assignedto=mary; nosy=+john]
369 This is a followup
370 ''')
371         handler = self.instance.MailGW(self.instance, self.db)
372         handler.trapExceptions = 0
373         handler.main(message)
375         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
376 '''FROM: roundup-admin@your.tracker.email.domain.example
377 TO: chef@bork.bork.bork, john@test, mary@test
378 Content-Type: text/plain; charset=utf-8
379 Subject: [issue1] Testing...
380 To: chef@bork.bork.bork, john@test, mary@test
381 From: richard <issue_tracker@your.tracker.email.domain.example>
382 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
383 MIME-Version: 1.0
384 Message-Id: <followup_dummy_id>
385 In-Reply-To: <dummy_test_message_id>
386 X-Roundup-Name: Roundup issue tracker
387 X-Roundup-Loop: hello
388 Content-Transfer-Encoding: quoted-printable
391 richard <richard@test> added the comment:
393 This is a followup
395 ----------
396 assignedto:  -> mary
397 nosy: +john, mary
398 status: unread -> chatting
399 _______________________________________________________________________
400 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
401 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
402 _______________________________________________________________________
403 ''')
405     def testFollowupNosyAuthor(self):
406         self.doNewIssue()
407         self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
408         message = StringIO('''Content-Type: text/plain;
409   charset="iso-8859-1"
410 From: john@test
411 To: issue_tracker@your.tracker.email.domain.example
412 Message-Id: <followup_dummy_id>
413 In-Reply-To: <dummy_test_message_id>
414 Subject: [issue1] Testing...
416 This is a followup
417 ''')
418         handler = self.instance.MailGW(self.instance, self.db)
419         handler.trapExceptions = 0
420         handler.main(message)
422         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
423 '''FROM: roundup-admin@your.tracker.email.domain.example
424 TO: chef@bork.bork.bork, richard@test
425 Content-Type: text/plain; charset=utf-8
426 Subject: [issue1] Testing...
427 To: chef@bork.bork.bork, richard@test
428 From: John Doe <issue_tracker@your.tracker.email.domain.example>
429 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
430 MIME-Version: 1.0
431 Message-Id: <followup_dummy_id>
432 In-Reply-To: <dummy_test_message_id>
433 X-Roundup-Name: Roundup issue tracker
434 X-Roundup-Loop: hello
435 Content-Transfer-Encoding: quoted-printable
438 John Doe <john@test> added the comment:
440 This is a followup
442 ----------
443 nosy: +john
444 status: unread -> chatting
445 _______________________________________________________________________
446 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
447 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
448 _______________________________________________________________________
450 ''')
452     def testFollowupNosyRecipients(self):
453         self.doNewIssue()
454         self.db.config.ADD_RECIPIENTS_TO_NOSY = 'yes'
455         message = StringIO('''Content-Type: text/plain;
456   charset="iso-8859-1"
457 From: richard@test
458 To: issue_tracker@your.tracker.email.domain.example
459 Cc: john@test
460 Message-Id: <followup_dummy_id>
461 In-Reply-To: <dummy_test_message_id>
462 Subject: [issue1] Testing...
464 This is a followup
465 ''')
466         handler = self.instance.MailGW(self.instance, self.db)
467         handler.trapExceptions = 0
468         handler.main(message)
470         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
471 '''FROM: roundup-admin@your.tracker.email.domain.example
472 TO: chef@bork.bork.bork
473 Content-Type: text/plain; charset=utf-8
474 Subject: [issue1] Testing...
475 To: chef@bork.bork.bork
476 From: richard <issue_tracker@your.tracker.email.domain.example>
477 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
478 MIME-Version: 1.0
479 Message-Id: <followup_dummy_id>
480 In-Reply-To: <dummy_test_message_id>
481 X-Roundup-Name: Roundup issue tracker
482 X-Roundup-Loop: hello
483 Content-Transfer-Encoding: quoted-printable
486 richard <richard@test> added the comment:
488 This is a followup
490 ----------
491 nosy: +john
492 status: unread -> chatting
493 _______________________________________________________________________
494 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
495 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
496 _______________________________________________________________________
498 ''')
500     def testFollowupNosyAuthorAndCopy(self):
501         self.doNewIssue()
502         self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
503         self.db.config.MESSAGES_TO_AUTHOR = 'yes'
504         message = StringIO('''Content-Type: text/plain;
505   charset="iso-8859-1"
506 From: john@test
507 To: issue_tracker@your.tracker.email.domain.example
508 Message-Id: <followup_dummy_id>
509 In-Reply-To: <dummy_test_message_id>
510 Subject: [issue1] Testing...
512 This is a followup
513 ''')
514         handler = self.instance.MailGW(self.instance, self.db)
515         handler.trapExceptions = 0
516         handler.main(message)
518         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
519 '''FROM: roundup-admin@your.tracker.email.domain.example
520 TO: chef@bork.bork.bork, john@test, richard@test
521 Content-Type: text/plain; charset=utf-8
522 Subject: [issue1] Testing...
523 To: chef@bork.bork.bork, john@test, richard@test
524 From: John Doe <issue_tracker@your.tracker.email.domain.example>
525 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
526 MIME-Version: 1.0
527 Message-Id: <followup_dummy_id>
528 In-Reply-To: <dummy_test_message_id>
529 X-Roundup-Name: Roundup issue tracker
530 X-Roundup-Loop: hello
531 Content-Transfer-Encoding: quoted-printable
534 John Doe <john@test> added the comment:
536 This is a followup
538 ----------
539 nosy: +john
540 status: unread -> chatting
541 _______________________________________________________________________
542 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
543 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
544 _______________________________________________________________________
546 ''')
548     def testFollowupNoNosyAuthor(self):
549         self.doNewIssue()
550         self.instance.config.ADD_AUTHOR_TO_NOSY = 'no'
551         message = StringIO('''Content-Type: text/plain;
552   charset="iso-8859-1"
553 From: john@test
554 To: issue_tracker@your.tracker.email.domain.example
555 Message-Id: <followup_dummy_id>
556 In-Reply-To: <dummy_test_message_id>
557 Subject: [issue1] Testing...
559 This is a followup
560 ''')
561         handler = self.instance.MailGW(self.instance, self.db)
562         handler.trapExceptions = 0
563         handler.main(message)
565         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
566 '''FROM: roundup-admin@your.tracker.email.domain.example
567 TO: chef@bork.bork.bork, richard@test
568 Content-Type: text/plain; charset=utf-8
569 Subject: [issue1] Testing...
570 To: chef@bork.bork.bork, richard@test
571 From: John Doe <issue_tracker@your.tracker.email.domain.example>
572 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
573 MIME-Version: 1.0
574 Message-Id: <followup_dummy_id>
575 In-Reply-To: <dummy_test_message_id>
576 X-Roundup-Name: Roundup issue tracker
577 X-Roundup-Loop: hello
578 Content-Transfer-Encoding: quoted-printable
581 John Doe <john@test> added the comment:
583 This is a followup
585 ----------
586 status: unread -> chatting
587 _______________________________________________________________________
588 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
589 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
590 _______________________________________________________________________
592 ''')
594     def testFollowupNoNosyRecipients(self):
595         self.doNewIssue()
596         self.instance.config.ADD_RECIPIENTS_TO_NOSY = 'no'
597         message = StringIO('''Content-Type: text/plain;
598   charset="iso-8859-1"
599 From: richard@test
600 To: issue_tracker@your.tracker.email.domain.example
601 Cc: john@test
602 Message-Id: <followup_dummy_id>
603 In-Reply-To: <dummy_test_message_id>
604 Subject: [issue1] Testing...
606 This is a followup
607 ''')
608         handler = self.instance.MailGW(self.instance, self.db)
609         handler.trapExceptions = 0
610         handler.main(message)
612         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
613 '''FROM: roundup-admin@your.tracker.email.domain.example
614 TO: chef@bork.bork.bork
615 Content-Type: text/plain; charset=utf-8
616 Subject: [issue1] Testing...
617 To: chef@bork.bork.bork
618 From: richard <issue_tracker@your.tracker.email.domain.example>
619 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
620 MIME-Version: 1.0
621 Message-Id: <followup_dummy_id>
622 In-Reply-To: <dummy_test_message_id>
623 X-Roundup-Name: Roundup issue tracker
624 X-Roundup-Loop: hello
625 Content-Transfer-Encoding: quoted-printable
628 richard <richard@test> added the comment:
630 This is a followup
632 ----------
633 status: unread -> chatting
634 _______________________________________________________________________
635 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
636 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
637 _______________________________________________________________________
639 ''')
641     def testFollowupEmptyMessage(self):
642         self.doNewIssue()
644         message = StringIO('''Content-Type: text/plain;
645   charset="iso-8859-1"
646 From: richard <richard@test>
647 To: issue_tracker@your.tracker.email.domain.example
648 Message-Id: <followup_dummy_id>
649 In-Reply-To: <dummy_test_message_id>
650 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
652 ''')
653         handler = self.instance.MailGW(self.instance, self.db)
654         handler.trapExceptions = 0
655         handler.main(message)
656         l = self.db.issue.get('1', 'nosy')
657         l.sort()
658         self.assertEqual(l, ['3', '4', '5', '6'])
660         # should be no file created (ie. no message)
661         assert not os.path.exists(os.environ['SENDMAILDEBUG'])
663     def testNosyRemove(self):
664         self.doNewIssue()
666         message = StringIO('''Content-Type: text/plain;
667   charset="iso-8859-1"
668 From: richard <richard@test>
669 To: issue_tracker@your.tracker.email.domain.example
670 Message-Id: <followup_dummy_id>
671 In-Reply-To: <dummy_test_message_id>
672 Subject: [issue1] Testing... [nosy=-richard]
674 ''')
675         handler = self.instance.MailGW(self.instance, self.db)
676         handler.trapExceptions = 0
677         handler.main(message)
678         l = self.db.issue.get('1', 'nosy')
679         l.sort()
680         self.assertEqual(l, ['3'])
682         # NO NOSY MESSAGE SHOULD BE SENT!
683         self.assert_(not os.path.exists(os.environ['SENDMAILDEBUG']))
685     def testNewUserAuthor(self):
686         # first without the permission
687         # heh... just ignore the API for a second ;)
688         self.db.security.role['anonymous'].permissions=[]
689         anonid = self.db.user.lookup('anonymous')
690         self.db.user.set(anonid, roles='Anonymous')
692         self.db.security.hasPermission('Email Registration', anonid)
693         l = self.db.user.list()
694         l.sort()
695         s = '''Content-Type: text/plain;
696   charset="iso-8859-1"
697 From: fubar <fubar@bork.bork.bork>
698 To: issue_tracker@your.tracker.email.domain.example
699 Message-Id: <dummy_test_message_id>
700 Subject: [issue] Testing...
702 This is a test submission of a new issue.
703 '''
704         message = StringIO(s)
705         handler = self.instance.MailGW(self.instance, self.db)
706         handler.trapExceptions = 0
707         self.assertRaises(Unauthorized, handler.main, message)
708         m = self.db.user.list()
709         m.sort()
710         self.assertEqual(l, m)
712         # now with the permission
713         p = self.db.security.getPermission('Email Registration')
714         self.db.security.role['anonymous'].permissions=[p]
715         handler = self.instance.MailGW(self.instance, self.db)
716         handler.trapExceptions = 0
717         message = StringIO(s)
718         handler.main(message)
719         m = self.db.user.list()
720         m.sort()
721         self.assertNotEqual(l, m)
723     def testEnc01(self):
724         self.doNewIssue()
725         message = StringIO('''Content-Type: text/plain;
726   charset="iso-8859-1"
727 From: mary <mary@test>
728 To: issue_tracker@your.tracker.email.domain.example
729 Message-Id: <followup_dummy_id>
730 In-Reply-To: <dummy_test_message_id>
731 Subject: [issue1] Testing...
732 Content-Type: text/plain;
733         charset="iso-8859-1"
734 Content-Transfer-Encoding: quoted-printable
736 A message with encoding (encoded oe =F6)
738 ''')
739         handler = self.instance.MailGW(self.instance, self.db)
740         handler.trapExceptions = 0
741         handler.main(message)
742         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
743 '''FROM: roundup-admin@your.tracker.email.domain.example
744 TO: chef@bork.bork.bork, richard@test
745 Content-Type: text/plain; charset=utf-8
746 Subject: [issue1] Testing...
747 To: chef@bork.bork.bork, richard@test
748 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
749 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
750 MIME-Version: 1.0
751 Message-Id: <followup_dummy_id>
752 In-Reply-To: <dummy_test_message_id>
753 X-Roundup-Name: Roundup issue tracker
754 X-Roundup-Loop: hello
755 Content-Transfer-Encoding: quoted-printable
758 Contrary, Mary <mary@test> added the comment:
760 A message with encoding (encoded oe =C3=B6)
762 ----------
763 status: unread -> chatting
764 _______________________________________________________________________
765 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
766 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
767 _______________________________________________________________________
768 ''')
771     def testMultipartEnc01(self):
772         self.doNewIssue()
773         message = StringIO('''Content-Type: text/plain;
774   charset="iso-8859-1"
775 From: mary <mary@test>
776 To: issue_tracker@your.tracker.email.domain.example
777 Message-Id: <followup_dummy_id>
778 In-Reply-To: <dummy_test_message_id>
779 Subject: [issue1] Testing...
780 Content-Type: multipart/mixed;
781         boundary="----_=_NextPart_000_01"
783 This message is in MIME format. Since your mail reader does not understand
784 this format, some or all of this message may not be legible.
786 ------_=_NextPart_000_01
787 Content-Type: text/plain;
788         charset="iso-8859-1"
789 Content-Transfer-Encoding: quoted-printable
791 A message with first part encoded (encoded oe =F6)
793 ''')
794         handler = self.instance.MailGW(self.instance, self.db)
795         handler.trapExceptions = 0
796         handler.main(message)
797         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
798 '''FROM: roundup-admin@your.tracker.email.domain.example
799 TO: chef@bork.bork.bork, richard@test
800 Content-Type: text/plain; charset=utf-8
801 Subject: [issue1] Testing...
802 To: chef@bork.bork.bork, richard@test
803 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
804 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
805 MIME-Version: 1.0
806 Message-Id: <followup_dummy_id>
807 In-Reply-To: <dummy_test_message_id>
808 X-Roundup-Name: Roundup issue tracker
809 X-Roundup-Loop: hello
810 Content-Transfer-Encoding: quoted-printable
813 Contrary, Mary <mary@test> added the comment:
815 A message with first part encoded (encoded oe =C3=B6)
817 ----------
818 status: unread -> chatting
819 _______________________________________________________________________
820 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
821 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
822 _______________________________________________________________________
823 ''')
825     def testContentDisposition(self):
826         self.doNewIssue()
827         message = StringIO('''Content-Type: text/plain;
828   charset="iso-8859-1"
829 From: mary <mary@test>
830 To: issue_tracker@your.tracker.email.domain.example
831 Message-Id: <followup_dummy_id>
832 In-Reply-To: <dummy_test_message_id>
833 Subject: [issue1] Testing...
834 Content-Type: multipart/mixed; boundary="bCsyhTFzCvuiizWE" 
835 Content-Disposition: inline 
836  
837  
838 --bCsyhTFzCvuiizWE 
839 Content-Type: text/plain; charset=us-ascii 
840 Content-Disposition: inline 
842 test attachment binary 
844 --bCsyhTFzCvuiizWE 
845 Content-Type: application/octet-stream 
846 Content-Disposition: attachment; filename="main.dvi" 
848 xxxxxx 
850 --bCsyhTFzCvuiizWE--
851 ''')
852         handler = self.instance.MailGW(self.instance, self.db)
853         handler.trapExceptions = 0
854         handler.main(message)
855         messages = self.db.issue.get('1', 'messages')
856         messages.sort()
857         file = self.db.msg.get(messages[-1], 'files')[0]
858         self.assertEqual(self.db.file.get(file, 'name'), 'main.dvi')
860     def testFollowupStupidQuoting(self):
861         self.doNewIssue()
863         message = StringIO('''Content-Type: text/plain;
864   charset="iso-8859-1"
865 From: richard <richard@test>
866 To: issue_tracker@your.tracker.email.domain.example
867 Message-Id: <followup_dummy_id>
868 In-Reply-To: <dummy_test_message_id>
869 Subject: Re: "[issue1] Testing... "
871 This is a followup
872 ''')
873         handler = self.instance.MailGW(self.instance, self.db)
874         handler.trapExceptions = 0
875         handler.main(message)
877         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
878 '''FROM: roundup-admin@your.tracker.email.domain.example
879 TO: chef@bork.bork.bork
880 Content-Type: text/plain; charset=utf-8
881 Subject: [issue1] Testing...
882 To: chef@bork.bork.bork
883 From: richard <issue_tracker@your.tracker.email.domain.example>
884 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
885 MIME-Version: 1.0
886 Message-Id: <followup_dummy_id>
887 In-Reply-To: <dummy_test_message_id>
888 X-Roundup-Name: Roundup issue tracker
889 X-Roundup-Loop: hello
890 Content-Transfer-Encoding: quoted-printable
893 richard <richard@test> added the comment:
895 This is a followup
897 ----------
898 status: unread -> chatting
899 _______________________________________________________________________
900 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
901 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
902 _______________________________________________________________________
903 ''')
905     def testEmailQuoting(self):
906         self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
907         self.innerTestQuoting('''This is a followup
908 ''')
910     def testEmailQuotingRemove(self):
911         self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
912         self.innerTestQuoting('''Blah blah wrote:
913 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
914 >  skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
917 This is a followup
918 ''')
920     def innerTestQuoting(self, expect):
921         nodeid = self.doNewIssue()
923         messages = self.db.issue.get(nodeid, 'messages')
925         message = StringIO('''Content-Type: text/plain;
926   charset="iso-8859-1"
927 From: richard <richard@test>
928 To: issue_tracker@your.tracker.email.domain.example
929 Message-Id: <followup_dummy_id>
930 In-Reply-To: <dummy_test_message_id>
931 Subject: Re: [issue1] Testing...
933 Blah blah wrote:
934 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
935 >  skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
938 This is a followup
939 ''')
940         handler = self.instance.MailGW(self.instance, self.db)
941         handler.trapExceptions = 0
942         handler.main(message)
944         # figure the new message id
945         newmessages = self.db.issue.get(nodeid, 'messages')
946         for msg in messages:
947             newmessages.remove(msg)
948         messageid = newmessages[0]
950         self.compareMessages(self.db.msg.get(messageid, 'content'), expect)
952     def testUserLookup(self):
953         i = self.db.user.create(username='user1', address='user1@foo.com')
954         self.assertEqual(uidFromAddress(self.db, ('', 'user1@foo.com'), 0), i)
955         self.assertEqual(uidFromAddress(self.db, ('', 'USER1@foo.com'), 0), i)
956         i = self.db.user.create(username='user2', address='USER2@foo.com')
957         self.assertEqual(uidFromAddress(self.db, ('', 'USER2@foo.com'), 0), i)
958         self.assertEqual(uidFromAddress(self.db, ('', 'user2@foo.com'), 0), i)
960     def testUserAlternateLookup(self):
961         i = self.db.user.create(username='user1', address='user1@foo.com',
962                                 alternate_addresses='user1@bar.com')
963         self.assertEqual(uidFromAddress(self.db, ('', 'user1@bar.com'), 0), i)
964         self.assertEqual(uidFromAddress(self.db, ('', 'USER1@bar.com'), 0), i)
966     def testUserCreate(self):
967         i = uidFromAddress(self.db, ('', 'user@foo.com'), 1)
968         self.assertNotEqual(uidFromAddress(self.db, ('', 'user@bar.com'), 1), i)
970     def testRFC2822(self):
971         ascii_header = "[issue243] This is a \"test\" - with 'quotation' marks"
972         unicode_header = '[issue244] \xd0\xb0\xd0\xbd\xd0\xb4\xd1\x80\xd0\xb5\xd0\xb9'
973         unicode_encoded = '=?utf-8?q?[issue244]_=D0=B0=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?='
974         self.assertEqual(rfc2822.encode_header(ascii_header), ascii_header)
975         self.assertEqual(rfc2822.encode_header(unicode_header), unicode_encoded)
977     def testRegistrationConfirmation(self):
978         otk = "Aj4euk4LZSAdwePohj90SME5SpopLETL"
979         self.db.otks.set(otk, username='johannes', __time='')
980         message = StringIO('''Content-Type: text/plain;
981   charset="iso-8859-1"
982 From: Chef <chef@bork.bork.bork>
983 To: issue_tracker@your.tracker.email.domain.example
984 Cc: richard@test
985 Message-Id: <dummy_test_message_id>
986 Subject: Re: Complete your registration to Roundup issue tracker\r
987  -- key %s
989 This is a test confirmation of registration.
990 ''' % otk)
991         handler = self.instance.MailGW(self.instance, self.db)
992         handler.trapExceptions = 0
993         handler.main(message)
995         self.db.user.lookup('johannes')
998 class ParseContentTestCase(unittest.TestCase):
999     def testSignatureRemoval(self):
1000         summary, content = parseContent('''Testing, testing.
1002 -- 
1003 Signature''', 1, 0)
1004         self.assertEqual(content, 'Testing, testing.')
1006     def testKeepMultipleHyphens(self):
1007         body = '''Testing, testing.
1009 ----
1010 Testing, testing.'''
1011         summary, content = parseContent(body, 1, 0)
1012         self.assertEqual(body, content)
1014 def suite():
1015     l = [#unittest.makeSuite(MailgwTestCase),
1016          unittest.makeSuite(ParseContentTestCase)]
1017     return unittest.TestSuite(l)
1020 # vim: set filetype=python ts=4 sw=4 et si