Code

Simplify Message comparison.
[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.50 2003-09-07 18:27:47 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
18 from roundup import init, instance, rfc2822
20 class Message(rfc822.Message):
21     """String-based Message class with equivalence test."""
22     def __init__(self, s):
23         rfc822.Message.__init__(self, StringIO(s.strip()))
24         
25     def __eq__(self, other):
26         del self['date'], other['date']
28         return (self.dict == other.dict and
29                 self.fp.read() == other.fp.read()) 
31 # TODO: Do a semantic diff instead of a straight text diff when a test fails.
32 class DiffHelper:
33     def compareMessages(self, s2, s1):
34         """Compare messages for semantic equivalence."""
35         if not Message(s2) == Message(s1):    
36             self.compareStrings(s2, s1)
37     
38     def compareStrings(self, s2, s1):
39         '''Note the reversal of s2 and s1 - difflib.SequenceMatcher wants
40            the first to be the "original" but in the calls in this file,
41            the second arg is the original. Ho hum.
42         '''
43         # we have to special-case the Date: header here 'cos we can't test
44         # for it properly
45         l1=s1.strip().split('\n')
46         l2=[x for x in s2.strip().split('\n') if not x.startswith('Date: ')]
47         if l1 == l2:
48             return
50         s = difflib.SequenceMatcher(None, l1, l2)
51         res = ['Generated message not correct (diff follows):']
52         for value, s1s, s1e, s2s, s2e in s.get_opcodes():
53             if value == 'equal':
54                 for i in range(s1s, s1e):
55                     res.append('  %s'%l1[i])
56             elif value == 'delete':
57                 for i in range(s1s, s1e):
58                     res.append('- %s'%l1[i])
59             elif value == 'insert':
60                 for i in range(s2s, s2e):
61                     res.append('+ %s'%l2[i])
62             elif value == 'replace':
63                 for i, j in zip(range(s1s, s1e), range(s2s, s2e)):
64                     res.append('- %s'%l1[i])
65                     res.append('+ %s'%l2[j])
67         raise AssertionError, '\n'.join(res)
69 class MailgwTestCase(unittest.TestCase, DiffHelper):
70     count = 0
71     schema = 'classic'
72     def setUp(self):
73         MailgwTestCase.count = MailgwTestCase.count + 1
74         self.dirname = '_test_mailgw_%s'%self.count
75         try:
76             shutil.rmtree(self.dirname)
77         except OSError, error:
78             if error.errno not in (errno.ENOENT, errno.ESRCH): raise
79         # create the instance
80         init.install(self.dirname, 'templates/classic')
81         init.write_select_db(self.dirname, 'anydbm')
82         init.initialise(self.dirname, 'sekrit')
83         # check we can load the package
84         self.instance = instance.open(self.dirname)
85         # and open the database
86         self.db = self.instance.open('admin')
87         self.db.user.create(username='Chef', address='chef@bork.bork.bork',
88             realname='Bork, Chef', roles='User')
89         self.db.user.create(username='richard', address='richard@test',
90             roles='User')
91         self.db.user.create(username='mary', address='mary@test',
92             roles='User', realname='Contrary, Mary')
93         self.db.user.create(username='john', address='john@test',
94             alternate_addresses='jondoe@test\njohn.doe@test', roles='User',
95             realname='John Doe')
97     def tearDown(self):
98         if os.path.exists(os.environ['SENDMAILDEBUG']):
99             os.remove(os.environ['SENDMAILDEBUG'])
100         self.db.close()
101         try:
102             shutil.rmtree(self.dirname)
103         except OSError, error:
104             if error.errno not in (errno.ENOENT, errno.ESRCH): raise
106     def testEmptyMessage(self):
107         message = StringIO('''Content-Type: text/plain;
108   charset="iso-8859-1"
109 From: Chef <chef@bork.bork.bork>
110 To: issue_tracker@your.tracker.email.domain.example
111 Cc: richard@test
112 Message-Id: <dummy_test_message_id>
113 Subject: [issue] Testing...
115 ''')
116         handler = self.instance.MailGW(self.instance, self.db)
117         handler.trapExceptions = 0
118         nodeid = handler.main(message)
119         if os.path.exists(os.environ['SENDMAILDEBUG']):
120             error = open(os.environ['SENDMAILDEBUG']).read()
121             self.assertEqual('no error', error)
122         self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
124     def doNewIssue(self):
125         message = StringIO('''Content-Type: text/plain;
126   charset="iso-8859-1"
127 From: Chef <chef@bork.bork.bork>
128 To: issue_tracker@your.tracker.email.domain.example
129 Cc: richard@test
130 Message-Id: <dummy_test_message_id>
131 Subject: [issue] Testing...
133 This is a test submission of a new issue.
134 ''')
135         handler = self.instance.MailGW(self.instance, self.db)
136         handler.trapExceptions = 0
137         nodeid = handler.main(message)
138         if os.path.exists(os.environ['SENDMAILDEBUG']):
139             error = open(os.environ['SENDMAILDEBUG']).read()
140             self.assertEqual('no error', error)
141         l = self.db.issue.get(nodeid, 'nosy')
142         l.sort()
143         self.assertEqual(l, ['3', '4'])
144         return nodeid
146     def testNewIssue(self):
147         self.doNewIssue()
149     def testNewIssueNosy(self):
150         self.instance.config.ADD_AUTHOR_TO_NOSY = 'yes'
151         message = StringIO('''Content-Type: text/plain;
152   charset="iso-8859-1"
153 From: Chef <chef@bork.bork.bork>
154 To: issue_tracker@your.tracker.email.domain.example
155 Cc: richard@test
156 Message-Id: <dummy_test_message_id>
157 Subject: [issue] Testing...
159 This is a test submission of a new issue.
160 ''')
161         handler = self.instance.MailGW(self.instance, self.db)
162         handler.trapExceptions = 0
163         nodeid = handler.main(message)
164         if os.path.exists(os.environ['SENDMAILDEBUG']):
165             error = open(os.environ['SENDMAILDEBUG']).read()
166             self.assertEqual('no error', error)
167         l = self.db.issue.get(nodeid, 'nosy')
168         l.sort()
169         self.assertEqual(l, ['3', '4'])
171     def testAlternateAddress(self):
172         message = StringIO('''Content-Type: text/plain;
173   charset="iso-8859-1"
174 From: John Doe <john.doe@test>
175 To: issue_tracker@your.tracker.email.domain.example
176 Message-Id: <dummy_test_message_id>
177 Subject: [issue] Testing...
179 This is a test submission of a new issue.
180 ''')
181         userlist = self.db.user.list()
182         handler = self.instance.MailGW(self.instance, self.db)
183         handler.trapExceptions = 0
184         handler.main(message)
185         if os.path.exists(os.environ['SENDMAILDEBUG']):
186             error = open(os.environ['SENDMAILDEBUG']).read()
187             self.assertEqual('no error', error)
188         self.assertEqual(userlist, self.db.user.list(),
189             "user created when it shouldn't have been")
191     def testNewIssueNoClass(self):
192         message = StringIO('''Content-Type: text/plain;
193   charset="iso-8859-1"
194 From: Chef <chef@bork.bork.bork>
195 To: issue_tracker@your.tracker.email.domain.example
196 Cc: richard@test
197 Message-Id: <dummy_test_message_id>
198 Subject: Testing...
200 This is a test submission of a new issue.
201 ''')
202         handler = self.instance.MailGW(self.instance, self.db)
203         handler.trapExceptions = 0
204         handler.main(message)
205         if os.path.exists(os.environ['SENDMAILDEBUG']):
206             error = open(os.environ['SENDMAILDEBUG']).read()
207             self.assertEqual('no error', error)
209     def testNewIssueAuthMsg(self):
210         message = StringIO('''Content-Type: text/plain;
211   charset="iso-8859-1"
212 From: Chef <chef@bork.bork.bork>
213 To: issue_tracker@your.tracker.email.domain.example
214 Message-Id: <dummy_test_message_id>
215 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
217 This is a test submission of a new issue.
218 ''')
219         handler = self.instance.MailGW(self.instance, self.db)
220         handler.trapExceptions = 0
221         # TODO: fix the damn config - this is apalling
222         self.db.config.MESSAGES_TO_AUTHOR = 'yes'
223         handler.main(message)
225         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
226 '''FROM: roundup-admin@your.tracker.email.domain.example
227 TO: chef@bork.bork.bork, mary@test, richard@test
228 Content-Type: text/plain; charset=utf-8
229 Subject: [issue1] Testing...
230 To: chef@bork.bork.bork, mary@test, richard@test
231 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
232 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
233 MIME-Version: 1.0
234 Message-Id: <dummy_test_message_id>
235 X-Roundup-Name: Roundup issue tracker
236 X-Roundup-Loop: hello
237 Content-Transfer-Encoding: quoted-printable
240 New submission from Bork, Chef <chef@bork.bork.bork>:
242 This is a test submission of a new issue.
244 ----------
245 assignedto: richard
246 messages: 1
247 nosy: Chef, mary, richard
248 status: unread
249 title: Testing...
250 _______________________________________________________________________
251 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
252 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
253 _______________________________________________________________________
254 ''')
256     # BUG
257     # def testMultipart(self):
258     #         '''With more than one part'''
259     #        see MultipartEnc tests: but if there is more than one part
260     #        we return a multipart/mixed and the boundary contains
261     #        the ip address of the test machine. 
263     # BUG should test some binary attamchent too.
265     def testSimpleFollowup(self):
266         self.doNewIssue()
267         message = StringIO('''Content-Type: text/plain;
268   charset="iso-8859-1"
269 From: mary <mary@test>
270 To: issue_tracker@your.tracker.email.domain.example
271 Message-Id: <followup_dummy_id>
272 In-Reply-To: <dummy_test_message_id>
273 Subject: [issue1] Testing...
275 This is a second followup
276 ''')
277         handler = self.instance.MailGW(self.instance, self.db)
278         handler.trapExceptions = 0
279         handler.main(message)
280         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
281 '''FROM: roundup-admin@your.tracker.email.domain.example
282 TO: chef@bork.bork.bork, richard@test
283 Content-Type: text/plain; charset=utf-8
284 Subject: [issue1] Testing...
285 To: chef@bork.bork.bork, richard@test
286 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
287 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
288 MIME-Version: 1.0
289 Message-Id: <followup_dummy_id>
290 In-Reply-To: <dummy_test_message_id>
291 X-Roundup-Name: Roundup issue tracker
292 X-Roundup-Loop: hello
293 Content-Transfer-Encoding: quoted-printable
296 Contrary, Mary <mary@test> added the comment:
298 This is a second followup
300 ----------
301 status: unread -> chatting
302 _______________________________________________________________________
303 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
304 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
305 _______________________________________________________________________
306 ''')
308     def testFollowup(self):
309         self.doNewIssue()
311         message = StringIO('''Content-Type: text/plain;
312   charset="iso-8859-1"
313 From: richard <richard@test>
314 To: issue_tracker@your.tracker.email.domain.example
315 Message-Id: <followup_dummy_id>
316 In-Reply-To: <dummy_test_message_id>
317 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
319 This is a followup
320 ''')
321         handler = self.instance.MailGW(self.instance, self.db)
322         handler.trapExceptions = 0
323         handler.main(message)
324         l = self.db.issue.get('1', 'nosy')
325         l.sort()
326         self.assertEqual(l, ['3', '4', '5', '6'])
328         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
329 '''FROM: roundup-admin@your.tracker.email.domain.example
330 TO: chef@bork.bork.bork, john@test, mary@test
331 Content-Type: text/plain; charset=utf-8
332 Subject: [issue1] Testing...
333 To: chef@bork.bork.bork, john@test, mary@test
334 From: richard <issue_tracker@your.tracker.email.domain.example>
335 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
336 MIME-Version: 1.0
337 Message-Id: <followup_dummy_id>
338 In-Reply-To: <dummy_test_message_id>
339 X-Roundup-Name: Roundup issue tracker
340 X-Roundup-Loop: hello
341 Content-Transfer-Encoding: quoted-printable
344 richard <richard@test> added the comment:
346 This is a followup
348 ----------
349 assignedto:  -> mary
350 nosy: +john, mary
351 status: unread -> chatting
352 _______________________________________________________________________
353 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
354 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
355 _______________________________________________________________________
356 ''')
358     def testFollowupTitleMatch(self):
359         self.doNewIssue()
360         message = StringIO('''Content-Type: text/plain;
361   charset="iso-8859-1"
362 From: richard <richard@test>
363 To: issue_tracker@your.tracker.email.domain.example
364 Message-Id: <followup_dummy_id>
365 In-Reply-To: <dummy_test_message_id>
366 Subject: Re: Testing... [assignedto=mary; nosy=+john]
368 This is a followup
369 ''')
370         handler = self.instance.MailGW(self.instance, self.db)
371         handler.trapExceptions = 0
372         handler.main(message)
374         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
375 '''FROM: roundup-admin@your.tracker.email.domain.example
376 TO: chef@bork.bork.bork, john@test, mary@test
377 Content-Type: text/plain; charset=utf-8
378 Subject: [issue1] Testing...
379 To: chef@bork.bork.bork, john@test, mary@test
380 From: richard <issue_tracker@your.tracker.email.domain.example>
381 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
382 MIME-Version: 1.0
383 Message-Id: <followup_dummy_id>
384 In-Reply-To: <dummy_test_message_id>
385 X-Roundup-Name: Roundup issue tracker
386 X-Roundup-Loop: hello
387 Content-Transfer-Encoding: quoted-printable
390 richard <richard@test> added the comment:
392 This is a followup
394 ----------
395 assignedto:  -> mary
396 nosy: +john, mary
397 status: unread -> chatting
398 _______________________________________________________________________
399 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
400 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
401 _______________________________________________________________________
402 ''')
404     def testFollowupNosyAuthor(self):
405         self.doNewIssue()
406         self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
407         message = StringIO('''Content-Type: text/plain;
408   charset="iso-8859-1"
409 From: john@test
410 To: issue_tracker@your.tracker.email.domain.example
411 Message-Id: <followup_dummy_id>
412 In-Reply-To: <dummy_test_message_id>
413 Subject: [issue1] Testing...
415 This is a followup
416 ''')
417         handler = self.instance.MailGW(self.instance, self.db)
418         handler.trapExceptions = 0
419         handler.main(message)
421         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
422 '''FROM: roundup-admin@your.tracker.email.domain.example
423 TO: chef@bork.bork.bork, richard@test
424 Content-Type: text/plain; charset=utf-8
425 Subject: [issue1] Testing...
426 To: chef@bork.bork.bork, richard@test
427 From: John Doe <issue_tracker@your.tracker.email.domain.example>
428 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
429 MIME-Version: 1.0
430 Message-Id: <followup_dummy_id>
431 In-Reply-To: <dummy_test_message_id>
432 X-Roundup-Name: Roundup issue tracker
433 X-Roundup-Loop: hello
434 Content-Transfer-Encoding: quoted-printable
437 John Doe <john@test> added the comment:
439 This is a followup
441 ----------
442 nosy: +john
443 status: unread -> chatting
444 _______________________________________________________________________
445 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
446 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
447 _______________________________________________________________________
449 ''')
451     def testFollowupNosyRecipients(self):
452         self.doNewIssue()
453         self.db.config.ADD_RECIPIENTS_TO_NOSY = 'yes'
454         message = StringIO('''Content-Type: text/plain;
455   charset="iso-8859-1"
456 From: richard@test
457 To: issue_tracker@your.tracker.email.domain.example
458 Cc: john@test
459 Message-Id: <followup_dummy_id>
460 In-Reply-To: <dummy_test_message_id>
461 Subject: [issue1] Testing...
463 This is a followup
464 ''')
465         handler = self.instance.MailGW(self.instance, self.db)
466         handler.trapExceptions = 0
467         handler.main(message)
469         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
470 '''FROM: roundup-admin@your.tracker.email.domain.example
471 TO: chef@bork.bork.bork
472 Content-Type: text/plain; charset=utf-8
473 Subject: [issue1] Testing...
474 To: chef@bork.bork.bork
475 From: richard <issue_tracker@your.tracker.email.domain.example>
476 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
477 MIME-Version: 1.0
478 Message-Id: <followup_dummy_id>
479 In-Reply-To: <dummy_test_message_id>
480 X-Roundup-Name: Roundup issue tracker
481 X-Roundup-Loop: hello
482 Content-Transfer-Encoding: quoted-printable
485 richard <richard@test> added the comment:
487 This is a followup
489 ----------
490 nosy: +john
491 status: unread -> chatting
492 _______________________________________________________________________
493 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
494 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
495 _______________________________________________________________________
497 ''')
499     def testFollowupNosyAuthorAndCopy(self):
500         self.doNewIssue()
501         self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
502         self.db.config.MESSAGES_TO_AUTHOR = 'yes'
503         message = StringIO('''Content-Type: text/plain;
504   charset="iso-8859-1"
505 From: john@test
506 To: issue_tracker@your.tracker.email.domain.example
507 Message-Id: <followup_dummy_id>
508 In-Reply-To: <dummy_test_message_id>
509 Subject: [issue1] Testing...
511 This is a followup
512 ''')
513         handler = self.instance.MailGW(self.instance, self.db)
514         handler.trapExceptions = 0
515         handler.main(message)
517         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
518 '''FROM: roundup-admin@your.tracker.email.domain.example
519 TO: chef@bork.bork.bork, john@test, richard@test
520 Content-Type: text/plain; charset=utf-8
521 Subject: [issue1] Testing...
522 To: chef@bork.bork.bork, john@test, richard@test
523 From: John Doe <issue_tracker@your.tracker.email.domain.example>
524 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
525 MIME-Version: 1.0
526 Message-Id: <followup_dummy_id>
527 In-Reply-To: <dummy_test_message_id>
528 X-Roundup-Name: Roundup issue tracker
529 X-Roundup-Loop: hello
530 Content-Transfer-Encoding: quoted-printable
533 John Doe <john@test> added the comment:
535 This is a followup
537 ----------
538 nosy: +john
539 status: unread -> chatting
540 _______________________________________________________________________
541 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
542 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
543 _______________________________________________________________________
545 ''')
547     def testFollowupNoNosyAuthor(self):
548         self.doNewIssue()
549         self.instance.config.ADD_AUTHOR_TO_NOSY = 'no'
550         message = StringIO('''Content-Type: text/plain;
551   charset="iso-8859-1"
552 From: john@test
553 To: issue_tracker@your.tracker.email.domain.example
554 Message-Id: <followup_dummy_id>
555 In-Reply-To: <dummy_test_message_id>
556 Subject: [issue1] Testing...
558 This is a followup
559 ''')
560         handler = self.instance.MailGW(self.instance, self.db)
561         handler.trapExceptions = 0
562         handler.main(message)
564         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
565 '''FROM: roundup-admin@your.tracker.email.domain.example
566 TO: chef@bork.bork.bork, richard@test
567 Content-Type: text/plain; charset=utf-8
568 Subject: [issue1] Testing...
569 To: chef@bork.bork.bork, richard@test
570 From: John Doe <issue_tracker@your.tracker.email.domain.example>
571 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
572 MIME-Version: 1.0
573 Message-Id: <followup_dummy_id>
574 In-Reply-To: <dummy_test_message_id>
575 X-Roundup-Name: Roundup issue tracker
576 X-Roundup-Loop: hello
577 Content-Transfer-Encoding: quoted-printable
580 John Doe <john@test> added the comment:
582 This is a followup
584 ----------
585 status: unread -> chatting
586 _______________________________________________________________________
587 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
588 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
589 _______________________________________________________________________
591 ''')
593     def testFollowupNoNosyRecipients(self):
594         self.doNewIssue()
595         self.instance.config.ADD_RECIPIENTS_TO_NOSY = 'no'
596         message = StringIO('''Content-Type: text/plain;
597   charset="iso-8859-1"
598 From: richard@test
599 To: issue_tracker@your.tracker.email.domain.example
600 Cc: john@test
601 Message-Id: <followup_dummy_id>
602 In-Reply-To: <dummy_test_message_id>
603 Subject: [issue1] Testing...
605 This is a followup
606 ''')
607         handler = self.instance.MailGW(self.instance, self.db)
608         handler.trapExceptions = 0
609         handler.main(message)
611         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
612 '''FROM: roundup-admin@your.tracker.email.domain.example
613 TO: chef@bork.bork.bork
614 Content-Type: text/plain; charset=utf-8
615 Subject: [issue1] Testing...
616 To: chef@bork.bork.bork
617 From: richard <issue_tracker@your.tracker.email.domain.example>
618 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
619 MIME-Version: 1.0
620 Message-Id: <followup_dummy_id>
621 In-Reply-To: <dummy_test_message_id>
622 X-Roundup-Name: Roundup issue tracker
623 X-Roundup-Loop: hello
624 Content-Transfer-Encoding: quoted-printable
627 richard <richard@test> added the comment:
629 This is a followup
631 ----------
632 status: unread -> chatting
633 _______________________________________________________________________
634 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
635 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
636 _______________________________________________________________________
638 ''')
640     def testFollowupEmptyMessage(self):
641         self.doNewIssue()
643         message = StringIO('''Content-Type: text/plain;
644   charset="iso-8859-1"
645 From: richard <richard@test>
646 To: issue_tracker@your.tracker.email.domain.example
647 Message-Id: <followup_dummy_id>
648 In-Reply-To: <dummy_test_message_id>
649 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
651 ''')
652         handler = self.instance.MailGW(self.instance, self.db)
653         handler.trapExceptions = 0
654         handler.main(message)
655         l = self.db.issue.get('1', 'nosy')
656         l.sort()
657         self.assertEqual(l, ['3', '4', '5', '6'])
659         # should be no file created (ie. no message)
660         assert not os.path.exists(os.environ['SENDMAILDEBUG'])
662     def testNosyRemove(self):
663         self.doNewIssue()
665         message = StringIO('''Content-Type: text/plain;
666   charset="iso-8859-1"
667 From: richard <richard@test>
668 To: issue_tracker@your.tracker.email.domain.example
669 Message-Id: <followup_dummy_id>
670 In-Reply-To: <dummy_test_message_id>
671 Subject: [issue1] Testing... [nosy=-richard]
673 ''')
674         handler = self.instance.MailGW(self.instance, self.db)
675         handler.trapExceptions = 0
676         handler.main(message)
677         l = self.db.issue.get('1', 'nosy')
678         l.sort()
679         self.assertEqual(l, ['3'])
681         # NO NOSY MESSAGE SHOULD BE SENT!
682         self.assert_(not os.path.exists(os.environ['SENDMAILDEBUG']))
684     def testNewUserAuthor(self):
685         # first without the permission
686         # heh... just ignore the API for a second ;)
687         self.db.security.role['anonymous'].permissions=[]
688         anonid = self.db.user.lookup('anonymous')
689         self.db.user.set(anonid, roles='Anonymous')
691         self.db.security.hasPermission('Email Registration', anonid)
692         l = self.db.user.list()
693         l.sort()
694         s = '''Content-Type: text/plain;
695   charset="iso-8859-1"
696 From: fubar <fubar@bork.bork.bork>
697 To: issue_tracker@your.tracker.email.domain.example
698 Message-Id: <dummy_test_message_id>
699 Subject: [issue] Testing...
701 This is a test submission of a new issue.
702 '''
703         message = StringIO(s)
704         handler = self.instance.MailGW(self.instance, self.db)
705         handler.trapExceptions = 0
706         self.assertRaises(Unauthorized, handler.main, message)
707         m = self.db.user.list()
708         m.sort()
709         self.assertEqual(l, m)
711         # now with the permission
712         p = self.db.security.getPermission('Email Registration')
713         self.db.security.role['anonymous'].permissions=[p]
714         handler = self.instance.MailGW(self.instance, self.db)
715         handler.trapExceptions = 0
716         message = StringIO(s)
717         handler.main(message)
718         m = self.db.user.list()
719         m.sort()
720         self.assertNotEqual(l, m)
722     def testEnc01(self):
723         self.doNewIssue()
724         message = StringIO('''Content-Type: text/plain;
725   charset="iso-8859-1"
726 From: mary <mary@test>
727 To: issue_tracker@your.tracker.email.domain.example
728 Message-Id: <followup_dummy_id>
729 In-Reply-To: <dummy_test_message_id>
730 Subject: [issue1] Testing...
731 Content-Type: text/plain;
732         charset="iso-8859-1"
733 Content-Transfer-Encoding: quoted-printable
735 A message with encoding (encoded oe =F6)
737 ''')
738         handler = self.instance.MailGW(self.instance, self.db)
739         handler.trapExceptions = 0
740         handler.main(message)
741         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
742 '''FROM: roundup-admin@your.tracker.email.domain.example
743 TO: chef@bork.bork.bork, richard@test
744 Content-Type: text/plain; charset=utf-8
745 Subject: [issue1] Testing...
746 To: chef@bork.bork.bork, richard@test
747 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
748 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
749 MIME-Version: 1.0
750 Message-Id: <followup_dummy_id>
751 In-Reply-To: <dummy_test_message_id>
752 X-Roundup-Name: Roundup issue tracker
753 X-Roundup-Loop: hello
754 Content-Transfer-Encoding: quoted-printable
757 Contrary, Mary <mary@test> added the comment:
759 A message with encoding (encoded oe =C3=B6)
761 ----------
762 status: unread -> chatting
763 _______________________________________________________________________
764 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
765 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
766 _______________________________________________________________________
767 ''')
770     def testMultipartEnc01(self):
771         self.doNewIssue()
772         message = StringIO('''Content-Type: text/plain;
773   charset="iso-8859-1"
774 From: mary <mary@test>
775 To: issue_tracker@your.tracker.email.domain.example
776 Message-Id: <followup_dummy_id>
777 In-Reply-To: <dummy_test_message_id>
778 Subject: [issue1] Testing...
779 Content-Type: multipart/mixed;
780         boundary="----_=_NextPart_000_01"
782 This message is in MIME format. Since your mail reader does not understand
783 this format, some or all of this message may not be legible.
785 ------_=_NextPart_000_01
786 Content-Type: text/plain;
787         charset="iso-8859-1"
788 Content-Transfer-Encoding: quoted-printable
790 A message with first part encoded (encoded oe =F6)
792 ''')
793         handler = self.instance.MailGW(self.instance, self.db)
794         handler.trapExceptions = 0
795         handler.main(message)
796         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
797 '''FROM: roundup-admin@your.tracker.email.domain.example
798 TO: chef@bork.bork.bork, richard@test
799 Content-Type: text/plain; charset=utf-8
800 Subject: [issue1] Testing...
801 To: chef@bork.bork.bork, richard@test
802 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
803 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
804 MIME-Version: 1.0
805 Message-Id: <followup_dummy_id>
806 In-Reply-To: <dummy_test_message_id>
807 X-Roundup-Name: Roundup issue tracker
808 X-Roundup-Loop: hello
809 Content-Transfer-Encoding: quoted-printable
812 Contrary, Mary <mary@test> added the comment:
814 A message with first part encoded (encoded oe =C3=B6)
816 ----------
817 status: unread -> chatting
818 _______________________________________________________________________
819 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
820 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
821 _______________________________________________________________________
822 ''')
824     def testContentDisposition(self):
825         self.doNewIssue()
826         message = StringIO('''Content-Type: text/plain;
827   charset="iso-8859-1"
828 From: mary <mary@test>
829 To: issue_tracker@your.tracker.email.domain.example
830 Message-Id: <followup_dummy_id>
831 In-Reply-To: <dummy_test_message_id>
832 Subject: [issue1] Testing...
833 Content-Type: multipart/mixed; boundary="bCsyhTFzCvuiizWE" 
834 Content-Disposition: inline 
835  
836  
837 --bCsyhTFzCvuiizWE 
838 Content-Type: text/plain; charset=us-ascii 
839 Content-Disposition: inline 
841 test attachment binary 
843 --bCsyhTFzCvuiizWE 
844 Content-Type: application/octet-stream 
845 Content-Disposition: attachment; filename="main.dvi" 
847 xxxxxx 
849 --bCsyhTFzCvuiizWE--
850 ''')
851         handler = self.instance.MailGW(self.instance, self.db)
852         handler.trapExceptions = 0
853         handler.main(message)
854         messages = self.db.issue.get('1', 'messages')
855         messages.sort()
856         file = self.db.msg.get(messages[-1], 'files')[0]
857         self.assertEqual(self.db.file.get(file, 'name'), 'main.dvi')
859     def testFollowupStupidQuoting(self):
860         self.doNewIssue()
862         message = StringIO('''Content-Type: text/plain;
863   charset="iso-8859-1"
864 From: richard <richard@test>
865 To: issue_tracker@your.tracker.email.domain.example
866 Message-Id: <followup_dummy_id>
867 In-Reply-To: <dummy_test_message_id>
868 Subject: Re: "[issue1] Testing... "
870 This is a followup
871 ''')
872         handler = self.instance.MailGW(self.instance, self.db)
873         handler.trapExceptions = 0
874         handler.main(message)
876         self.compareMessages(open(os.environ['SENDMAILDEBUG']).read(),
877 '''FROM: roundup-admin@your.tracker.email.domain.example
878 TO: chef@bork.bork.bork
879 Content-Type: text/plain; charset=utf-8
880 Subject: [issue1] Testing...
881 To: chef@bork.bork.bork
882 From: richard <issue_tracker@your.tracker.email.domain.example>
883 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
884 MIME-Version: 1.0
885 Message-Id: <followup_dummy_id>
886 In-Reply-To: <dummy_test_message_id>
887 X-Roundup-Name: Roundup issue tracker
888 X-Roundup-Loop: hello
889 Content-Transfer-Encoding: quoted-printable
892 richard <richard@test> added the comment:
894 This is a followup
896 ----------
897 status: unread -> chatting
898 _______________________________________________________________________
899 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
900 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
901 _______________________________________________________________________
902 ''')
904     def testEmailQuoting(self):
905         self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
906         self.innerTestQuoting('''This is a followup
907 ''')
909     def testEmailQuotingRemove(self):
910         self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
911         self.innerTestQuoting('''Blah blah wrote:
912 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
913 >  skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
916 This is a followup
917 ''')
919     def innerTestQuoting(self, expect):
920         nodeid = self.doNewIssue()
922         messages = self.db.issue.get(nodeid, 'messages')
924         message = StringIO('''Content-Type: text/plain;
925   charset="iso-8859-1"
926 From: richard <richard@test>
927 To: issue_tracker@your.tracker.email.domain.example
928 Message-Id: <followup_dummy_id>
929 In-Reply-To: <dummy_test_message_id>
930 Subject: Re: [issue1] Testing...
932 Blah blah wrote:
933 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
934 >  skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
937 This is a followup
938 ''')
939         handler = self.instance.MailGW(self.instance, self.db)
940         handler.trapExceptions = 0
941         handler.main(message)
943         # figure the new message id
944         newmessages = self.db.issue.get(nodeid, 'messages')
945         for msg in messages:
946             newmessages.remove(msg)
947         messageid = newmessages[0]
949         self.compareMessages(self.db.msg.get(messageid, 'content'), expect)
951     def testUserLookup(self):
952         i = self.db.user.create(username='user1', address='user1@foo.com')
953         self.assertEqual(uidFromAddress(self.db, ('', 'user1@foo.com'), 0), i)
954         self.assertEqual(uidFromAddress(self.db, ('', 'USER1@foo.com'), 0), i)
955         i = self.db.user.create(username='user2', address='USER2@foo.com')
956         self.assertEqual(uidFromAddress(self.db, ('', 'USER2@foo.com'), 0), i)
957         self.assertEqual(uidFromAddress(self.db, ('', 'user2@foo.com'), 0), i)
959     def testUserCreate(self):
960         i = uidFromAddress(self.db, ('', 'user@foo.com'), 1)
961         self.assertNotEqual(uidFromAddress(self.db, ('', 'user@bar.com'), 1), i)
963     def testRFC2822(self):
964         ascii_header = "[issue243] This is a \"test\" - with 'quotation' marks"
965         unicode_header = '[issue244] \xd0\xb0\xd0\xbd\xd0\xb4\xd1\x80\xd0\xb5\xd0\xb9'
966         unicode_encoded = '=?utf-8?q?[issue244]_=D0=B0=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?='
967         self.assertEqual(rfc2822.encode_header(ascii_header), ascii_header)
968         self.assertEqual(rfc2822.encode_header(unicode_header), unicode_encoded)
970     def testRegistrationConfirmation(self):
971         otk = "Aj4euk4LZSAdwePohj90SME5SpopLETL"
972         self.db.otks.set(otk, username='johannes', __time='')
973         message = StringIO('''Content-Type: text/plain;
974   charset="iso-8859-1"
975 From: Chef <chef@bork.bork.bork>
976 To: issue_tracker@your.tracker.email.domain.example
977 Cc: richard@test
978 Message-Id: <dummy_test_message_id>
979 Subject: Re: Complete your registration to Roundup issue tracker\r
980  -- key %s
982 This is a test confirmation of registration.
983 ''' % otk)
984         handler = self.instance.MailGW(self.instance, self.db)
985         handler.trapExceptions = 0
986         handler.main(message)
988         self.db.user.lookup('johannes')
989     
990 def suite():
991     l = [unittest.makeSuite(MailgwTestCase),
992     ]
993     return unittest.TestSuite(l)
996 # vim: set filetype=python ts=4 sw=4 et si