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.59 2003-11-03 19:08:41 jlgijsbers Exp $
13 import unittest, tempfile, os, shutil, errno, imp, sys, difflib, rfc822
15 from cStringIO import StringIO
17 if not os.environ.has_key('SENDMAILDEBUG'):
18 os.environ['SENDMAILDEBUG'] = 'mail-test.log'
19 SENDMAILDEBUG = os.environ['SENDMAILDEBUG']
21 from roundup.mailgw import MailGW, Unauthorized, uidFromAddress, parseContent
22 from roundup import init, instance, rfc2822
25 class Message(rfc822.Message):
26 """String-based Message class with equivalence test."""
27 def __init__(self, s):
28 rfc822.Message.__init__(self, StringIO(s.strip()))
30 def __eq__(self, other):
31 del self['date'], other['date']
33 return (self.dict == other.dict and
34 self.fp.read() == other.fp.read())
36 # TODO: Do a semantic diff instead of a straight text diff when a test fails.
37 class DiffHelper:
38 def compareMessages(self, s2, s1):
39 """Compare messages for semantic equivalence."""
40 if not Message(s2) == Message(s1):
41 self.compareStrings(s2, s1)
43 def compareStrings(self, s2, s1):
44 '''Note the reversal of s2 and s1 - difflib.SequenceMatcher wants
45 the first to be the "original" but in the calls in this file,
46 the second arg is the original. Ho hum.
47 '''
48 # we have to special-case the Date: header here 'cos we can't test
49 # for it properly
50 l1=s1.strip().split('\n')
51 l2=[x for x in s2.strip().split('\n') if not x.startswith('Date: ')]
52 if l1 == l2:
53 return
55 s = difflib.SequenceMatcher(None, l1, l2)
56 res = ['Generated message not correct (diff follows):']
57 for value, s1s, s1e, s2s, s2e in s.get_opcodes():
58 if value == 'equal':
59 for i in range(s1s, s1e):
60 res.append(' %s'%l1[i])
61 elif value == 'delete':
62 for i in range(s1s, s1e):
63 res.append('- %s'%l1[i])
64 elif value == 'insert':
65 for i in range(s2s, s2e):
66 res.append('+ %s'%l2[i])
67 elif value == 'replace':
68 for i, j in zip(range(s1s, s1e), range(s2s, s2e)):
69 res.append('- %s'%l1[i])
70 res.append('+ %s'%l2[j])
72 raise AssertionError, '\n'.join(res)
74 class MailgwTestCase(unittest.TestCase, DiffHelper):
75 count = 0
76 schema = 'classic'
77 def setUp(self):
78 MailgwTestCase.count = MailgwTestCase.count + 1
79 self.dirname = '_test_mailgw_%s'%self.count
80 try:
81 shutil.rmtree(self.dirname)
82 except OSError, error:
83 if error.errno not in (errno.ENOENT, errno.ESRCH): raise
84 # create the instance
85 init.install(self.dirname, 'templates/classic')
86 init.write_select_db(self.dirname, 'anydbm')
87 init.initialise(self.dirname, 'sekrit')
89 # check we can load the package
90 self.instance = instance.open(self.dirname)
92 # and open the database
93 self.db = self.instance.open('admin')
94 self.db.user.create(username='Chef', address='chef@bork.bork.bork',
95 realname='Bork, Chef', roles='User')
96 self.db.user.create(username='richard', address='richard@test',
97 roles='User')
98 self.db.user.create(username='mary', address='mary@test',
99 roles='User', realname='Contrary, Mary')
100 self.db.user.create(username='john', address='john@test',
101 alternate_addresses='jondoe@test\njohn.doe@test', roles='User',
102 realname='John Doe')
104 def tearDown(self):
105 if os.path.exists(SENDMAILDEBUG):
106 os.remove(SENDMAILDEBUG)
107 self.db.close()
108 try:
109 shutil.rmtree(self.dirname)
110 except OSError, error:
111 if error.errno not in (errno.ENOENT, errno.ESRCH): raise
113 def _send_mail(self, message):
114 handler = self.instance.MailGW(self.instance, self.db)
115 handler.trapExceptions = 0
116 return handler.main(StringIO(message))
118 def _get_mail(self):
119 f = open(SENDMAILDEBUG)
120 try:
121 return f.read()
122 finally:
123 f.close()
125 def testEmptyMessage(self):
126 nodeid = self._send_mail('''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 ''')
135 assert not os.path.exists(SENDMAILDEBUG)
136 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
138 def doNewIssue(self):
139 nodeid = self._send_mail('''Content-Type: text/plain;
140 charset="iso-8859-1"
141 From: Chef <chef@bork.bork.bork>
142 To: issue_tracker@your.tracker.email.domain.example
143 Cc: richard@test
144 Message-Id: <dummy_test_message_id>
145 Subject: [issue] Testing...
147 This is a test submission of a new issue.
148 ''')
149 assert not os.path.exists(SENDMAILDEBUG)
150 l = self.db.issue.get(nodeid, 'nosy')
151 l.sort()
152 self.assertEqual(l, ['3', '4'])
153 return nodeid
155 def testNewIssue(self):
156 self.doNewIssue()
158 def testNewIssueNosy(self):
159 self.instance.config.ADD_AUTHOR_TO_NOSY = 'yes'
160 nodeid = self._send_mail('''Content-Type: text/plain;
161 charset="iso-8859-1"
162 From: Chef <chef@bork.bork.bork>
163 To: issue_tracker@your.tracker.email.domain.example
164 Cc: richard@test
165 Message-Id: <dummy_test_message_id>
166 Subject: [issue] Testing...
168 This is a test submission of a new issue.
169 ''')
170 assert not os.path.exists(SENDMAILDEBUG)
171 l = self.db.issue.get(nodeid, 'nosy')
172 l.sort()
173 self.assertEqual(l, ['3', '4'])
175 def testAlternateAddress(self):
176 self._send_mail('''Content-Type: text/plain;
177 charset="iso-8859-1"
178 From: John Doe <john.doe@test>
179 To: issue_tracker@your.tracker.email.domain.example
180 Message-Id: <dummy_test_message_id>
181 Subject: [issue] Testing...
183 This is a test submission of a new issue.
184 ''')
185 userlist = self.db.user.list()
186 assert not os.path.exists(SENDMAILDEBUG)
187 self.assertEqual(userlist, self.db.user.list(),
188 "user created when it shouldn't have been")
190 def testNewIssueNoClass(self):
191 self._send_mail('''Content-Type: text/plain;
192 charset="iso-8859-1"
193 From: Chef <chef@bork.bork.bork>
194 To: issue_tracker@your.tracker.email.domain.example
195 Cc: richard@test
196 Message-Id: <dummy_test_message_id>
197 Subject: Testing...
199 This is a test submission of a new issue.
200 ''')
201 assert not os.path.exists(SENDMAILDEBUG)
203 def testNewIssueAuthMsg(self):
204 # TODO: fix the damn config - this is apalling
205 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
206 self._send_mail('''Content-Type: text/plain;
207 charset="iso-8859-1"
208 From: Chef <chef@bork.bork.bork>
209 To: issue_tracker@your.tracker.email.domain.example
210 Message-Id: <dummy_test_message_id>
211 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
213 This is a test submission of a new issue.
214 ''')
215 self.compareMessages(self._get_mail(),
216 '''FROM: roundup-admin@your.tracker.email.domain.example
217 TO: chef@bork.bork.bork, mary@test, richard@test
218 Content-Type: text/plain; charset=utf-8
219 Subject: [issue1] Testing...
220 To: chef@bork.bork.bork, mary@test, richard@test
221 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
222 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
223 MIME-Version: 1.0
224 Message-Id: <dummy_test_message_id>
225 X-Roundup-Name: Roundup issue tracker
226 X-Roundup-Loop: hello
227 Content-Transfer-Encoding: quoted-printable
230 New submission from Bork, Chef <chef@bork.bork.bork>:
232 This is a test submission of a new issue.
234 ----------
235 assignedto: richard
236 messages: 1
237 nosy: Chef, mary, richard
238 status: unread
239 title: Testing...
240 _______________________________________________________________________
241 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
242 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
243 _______________________________________________________________________
244 ''')
246 # BUG
247 # def testMultipart(self):
248 # '''With more than one part'''
249 # see MultipartEnc tests: but if there is more than one part
250 # we return a multipart/mixed and the boundary contains
251 # the ip address of the test machine.
253 # BUG should test some binary attamchent too.
255 def testSimpleFollowup(self):
256 self.doNewIssue()
257 self._send_mail('''Content-Type: text/plain;
258 charset="iso-8859-1"
259 From: mary <mary@test>
260 To: issue_tracker@your.tracker.email.domain.example
261 Message-Id: <followup_dummy_id>
262 In-Reply-To: <dummy_test_message_id>
263 Subject: [issue1] Testing...
265 This is a second followup
266 ''')
267 self.compareMessages(self._get_mail(),
268 '''FROM: roundup-admin@your.tracker.email.domain.example
269 TO: chef@bork.bork.bork, richard@test
270 Content-Type: text/plain; charset=utf-8
271 Subject: [issue1] Testing...
272 To: chef@bork.bork.bork, richard@test
273 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
274 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
275 MIME-Version: 1.0
276 Message-Id: <followup_dummy_id>
277 In-Reply-To: <dummy_test_message_id>
278 X-Roundup-Name: Roundup issue tracker
279 X-Roundup-Loop: hello
280 Content-Transfer-Encoding: quoted-printable
283 Contrary, Mary <mary@test> added the comment:
285 This is a second followup
287 ----------
288 status: unread -> chatting
289 _______________________________________________________________________
290 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
291 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
292 _______________________________________________________________________
293 ''')
295 def testFollowup(self):
296 self.doNewIssue()
298 self._send_mail('''Content-Type: text/plain;
299 charset="iso-8859-1"
300 From: richard <richard@test>
301 To: issue_tracker@your.tracker.email.domain.example
302 Message-Id: <followup_dummy_id>
303 In-Reply-To: <dummy_test_message_id>
304 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
306 This is a followup
307 ''')
308 l = self.db.issue.get('1', 'nosy')
309 l.sort()
310 self.assertEqual(l, ['3', '4', '5', '6'])
312 self.compareMessages(self._get_mail(),
313 '''FROM: roundup-admin@your.tracker.email.domain.example
314 TO: chef@bork.bork.bork, john@test, mary@test
315 Content-Type: text/plain; charset=utf-8
316 Subject: [issue1] Testing...
317 To: chef@bork.bork.bork, john@test, mary@test
318 From: richard <issue_tracker@your.tracker.email.domain.example>
319 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
320 MIME-Version: 1.0
321 Message-Id: <followup_dummy_id>
322 In-Reply-To: <dummy_test_message_id>
323 X-Roundup-Name: Roundup issue tracker
324 X-Roundup-Loop: hello
325 Content-Transfer-Encoding: quoted-printable
328 richard <richard@test> added the comment:
330 This is a followup
332 ----------
333 assignedto: -> mary
334 nosy: +john, mary
335 status: unread -> chatting
336 _______________________________________________________________________
337 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
338 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
339 _______________________________________________________________________
340 ''')
342 def testFollowupTitleMatch(self):
343 self.doNewIssue()
344 self._send_mail('''Content-Type: text/plain;
345 charset="iso-8859-1"
346 From: richard <richard@test>
347 To: issue_tracker@your.tracker.email.domain.example
348 Message-Id: <followup_dummy_id>
349 In-Reply-To: <dummy_test_message_id>
350 Subject: Re: Testing... [assignedto=mary; nosy=+john]
352 This is a followup
353 ''')
354 self.compareMessages(self._get_mail(),
355 '''FROM: roundup-admin@your.tracker.email.domain.example
356 TO: chef@bork.bork.bork, john@test, mary@test
357 Content-Type: text/plain; charset=utf-8
358 Subject: [issue1] Testing...
359 To: chef@bork.bork.bork, john@test, mary@test
360 From: richard <issue_tracker@your.tracker.email.domain.example>
361 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
362 MIME-Version: 1.0
363 Message-Id: <followup_dummy_id>
364 In-Reply-To: <dummy_test_message_id>
365 X-Roundup-Name: Roundup issue tracker
366 X-Roundup-Loop: hello
367 Content-Transfer-Encoding: quoted-printable
370 richard <richard@test> added the comment:
372 This is a followup
374 ----------
375 assignedto: -> mary
376 nosy: +john, mary
377 status: unread -> chatting
378 _______________________________________________________________________
379 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
380 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
381 _______________________________________________________________________
382 ''')
384 def testFollowupNosyAuthor(self):
385 self.doNewIssue()
386 self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
387 self._send_mail('''Content-Type: text/plain;
388 charset="iso-8859-1"
389 From: john@test
390 To: issue_tracker@your.tracker.email.domain.example
391 Message-Id: <followup_dummy_id>
392 In-Reply-To: <dummy_test_message_id>
393 Subject: [issue1] Testing...
395 This is a followup
396 ''')
398 self.compareMessages(self._get_mail(),
399 '''FROM: roundup-admin@your.tracker.email.domain.example
400 TO: chef@bork.bork.bork, richard@test
401 Content-Type: text/plain; charset=utf-8
402 Subject: [issue1] Testing...
403 To: chef@bork.bork.bork, richard@test
404 From: John Doe <issue_tracker@your.tracker.email.domain.example>
405 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
406 MIME-Version: 1.0
407 Message-Id: <followup_dummy_id>
408 In-Reply-To: <dummy_test_message_id>
409 X-Roundup-Name: Roundup issue tracker
410 X-Roundup-Loop: hello
411 Content-Transfer-Encoding: quoted-printable
414 John Doe <john@test> added the comment:
416 This is a followup
418 ----------
419 nosy: +john
420 status: unread -> chatting
421 _______________________________________________________________________
422 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
423 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
424 _______________________________________________________________________
426 ''')
428 def testFollowupNosyRecipients(self):
429 self.doNewIssue()
430 self.db.config.ADD_RECIPIENTS_TO_NOSY = 'yes'
431 self._send_mail('''Content-Type: text/plain;
432 charset="iso-8859-1"
433 From: richard@test
434 To: issue_tracker@your.tracker.email.domain.example
435 Cc: john@test
436 Message-Id: <followup_dummy_id>
437 In-Reply-To: <dummy_test_message_id>
438 Subject: [issue1] Testing...
440 This is a followup
441 ''')
442 self.compareMessages(self._get_mail(),
443 '''FROM: roundup-admin@your.tracker.email.domain.example
444 TO: chef@bork.bork.bork
445 Content-Type: text/plain; charset=utf-8
446 Subject: [issue1] Testing...
447 To: chef@bork.bork.bork
448 From: richard <issue_tracker@your.tracker.email.domain.example>
449 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
450 MIME-Version: 1.0
451 Message-Id: <followup_dummy_id>
452 In-Reply-To: <dummy_test_message_id>
453 X-Roundup-Name: Roundup issue tracker
454 X-Roundup-Loop: hello
455 Content-Transfer-Encoding: quoted-printable
458 richard <richard@test> added the comment:
460 This is a followup
462 ----------
463 nosy: +john
464 status: unread -> chatting
465 _______________________________________________________________________
466 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
467 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
468 _______________________________________________________________________
470 ''')
472 def testFollowupNosyAuthorAndCopy(self):
473 self.doNewIssue()
474 self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
475 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
476 self._send_mail('''Content-Type: text/plain;
477 charset="iso-8859-1"
478 From: john@test
479 To: issue_tracker@your.tracker.email.domain.example
480 Message-Id: <followup_dummy_id>
481 In-Reply-To: <dummy_test_message_id>
482 Subject: [issue1] Testing...
484 This is a followup
485 ''')
486 self.compareMessages(self._get_mail(),
487 '''FROM: roundup-admin@your.tracker.email.domain.example
488 TO: chef@bork.bork.bork, john@test, richard@test
489 Content-Type: text/plain; charset=utf-8
490 Subject: [issue1] Testing...
491 To: chef@bork.bork.bork, john@test, richard@test
492 From: John Doe <issue_tracker@your.tracker.email.domain.example>
493 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
494 MIME-Version: 1.0
495 Message-Id: <followup_dummy_id>
496 In-Reply-To: <dummy_test_message_id>
497 X-Roundup-Name: Roundup issue tracker
498 X-Roundup-Loop: hello
499 Content-Transfer-Encoding: quoted-printable
502 John Doe <john@test> added the comment:
504 This is a followup
506 ----------
507 nosy: +john
508 status: unread -> chatting
509 _______________________________________________________________________
510 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
511 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
512 _______________________________________________________________________
514 ''')
516 def testFollowupNoNosyAuthor(self):
517 self.doNewIssue()
518 self.instance.config.ADD_AUTHOR_TO_NOSY = 'no'
519 self._send_mail('''Content-Type: text/plain;
520 charset="iso-8859-1"
521 From: john@test
522 To: issue_tracker@your.tracker.email.domain.example
523 Message-Id: <followup_dummy_id>
524 In-Reply-To: <dummy_test_message_id>
525 Subject: [issue1] Testing...
527 This is a followup
528 ''')
529 self.compareMessages(self._get_mail(),
530 '''FROM: roundup-admin@your.tracker.email.domain.example
531 TO: chef@bork.bork.bork, richard@test
532 Content-Type: text/plain; charset=utf-8
533 Subject: [issue1] Testing...
534 To: chef@bork.bork.bork, richard@test
535 From: John Doe <issue_tracker@your.tracker.email.domain.example>
536 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
537 MIME-Version: 1.0
538 Message-Id: <followup_dummy_id>
539 In-Reply-To: <dummy_test_message_id>
540 X-Roundup-Name: Roundup issue tracker
541 X-Roundup-Loop: hello
542 Content-Transfer-Encoding: quoted-printable
545 John Doe <john@test> added the comment:
547 This is a followup
549 ----------
550 status: unread -> chatting
551 _______________________________________________________________________
552 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
553 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
554 _______________________________________________________________________
556 ''')
558 def testFollowupNoNosyRecipients(self):
559 self.doNewIssue()
560 self.instance.config.ADD_RECIPIENTS_TO_NOSY = 'no'
561 self._send_mail('''Content-Type: text/plain;
562 charset="iso-8859-1"
563 From: richard@test
564 To: issue_tracker@your.tracker.email.domain.example
565 Cc: john@test
566 Message-Id: <followup_dummy_id>
567 In-Reply-To: <dummy_test_message_id>
568 Subject: [issue1] Testing...
570 This is a followup
571 ''')
572 self.compareMessages(self._get_mail(),
573 '''FROM: roundup-admin@your.tracker.email.domain.example
574 TO: chef@bork.bork.bork
575 Content-Type: text/plain; charset=utf-8
576 Subject: [issue1] Testing...
577 To: chef@bork.bork.bork
578 From: richard <issue_tracker@your.tracker.email.domain.example>
579 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
580 MIME-Version: 1.0
581 Message-Id: <followup_dummy_id>
582 In-Reply-To: <dummy_test_message_id>
583 X-Roundup-Name: Roundup issue tracker
584 X-Roundup-Loop: hello
585 Content-Transfer-Encoding: quoted-printable
588 richard <richard@test> added the comment:
590 This is a followup
592 ----------
593 status: unread -> chatting
594 _______________________________________________________________________
595 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
596 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
597 _______________________________________________________________________
599 ''')
601 def testFollowupEmptyMessage(self):
602 self.doNewIssue()
604 self._send_mail('''Content-Type: text/plain;
605 charset="iso-8859-1"
606 From: richard <richard@test>
607 To: issue_tracker@your.tracker.email.domain.example
608 Message-Id: <followup_dummy_id>
609 In-Reply-To: <dummy_test_message_id>
610 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
612 ''')
613 l = self.db.issue.get('1', 'nosy')
614 l.sort()
615 self.assertEqual(l, ['3', '4', '5', '6'])
617 # should be no file created (ie. no message)
618 assert not os.path.exists(SENDMAILDEBUG)
620 def testNosyRemove(self):
621 self.doNewIssue()
623 self._send_mail('''Content-Type: text/plain;
624 charset="iso-8859-1"
625 From: richard <richard@test>
626 To: issue_tracker@your.tracker.email.domain.example
627 Message-Id: <followup_dummy_id>
628 In-Reply-To: <dummy_test_message_id>
629 Subject: [issue1] Testing... [nosy=-richard]
631 ''')
632 l = self.db.issue.get('1', 'nosy')
633 l.sort()
634 self.assertEqual(l, ['3'])
636 # NO NOSY MESSAGE SHOULD BE SENT!
637 assert not os.path.exists(SENDMAILDEBUG)
639 def testNewUserAuthor(self):
640 # first without the permission
641 # heh... just ignore the API for a second ;)
642 self.db.security.role['anonymous'].permissions=[]
643 anonid = self.db.user.lookup('anonymous')
644 self.db.user.set(anonid, roles='Anonymous')
646 self.db.security.hasPermission('Email Registration', anonid)
647 l = self.db.user.list()
648 l.sort()
649 message = '''Content-Type: text/plain;
650 charset="iso-8859-1"
651 From: fubar <fubar@bork.bork.bork>
652 To: issue_tracker@your.tracker.email.domain.example
653 Message-Id: <dummy_test_message_id>
654 Subject: [issue] Testing...
656 This is a test submission of a new issue.
657 '''
658 self.assertRaises(Unauthorized, self._send_mail, message)
659 m = self.db.user.list()
660 m.sort()
661 self.assertEqual(l, m)
663 # now with the permission
664 p = self.db.security.getPermission('Email Registration')
665 self.db.security.role['anonymous'].permissions=[p]
666 self._send_mail(message)
667 m = self.db.user.list()
668 m.sort()
669 self.assertNotEqual(l, m)
671 def testEnc01(self):
672 self.doNewIssue()
673 self._send_mail('''Content-Type: text/plain;
674 charset="iso-8859-1"
675 From: mary <mary@test>
676 To: issue_tracker@your.tracker.email.domain.example
677 Message-Id: <followup_dummy_id>
678 In-Reply-To: <dummy_test_message_id>
679 Subject: [issue1] Testing...
680 Content-Type: text/plain;
681 charset="iso-8859-1"
682 Content-Transfer-Encoding: quoted-printable
684 A message with encoding (encoded oe =F6)
686 ''')
687 self.compareMessages(self._get_mail(),
688 '''FROM: roundup-admin@your.tracker.email.domain.example
689 TO: chef@bork.bork.bork, richard@test
690 Content-Type: text/plain; charset=utf-8
691 Subject: [issue1] Testing...
692 To: chef@bork.bork.bork, richard@test
693 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
694 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
695 MIME-Version: 1.0
696 Message-Id: <followup_dummy_id>
697 In-Reply-To: <dummy_test_message_id>
698 X-Roundup-Name: Roundup issue tracker
699 X-Roundup-Loop: hello
700 Content-Transfer-Encoding: quoted-printable
703 Contrary, Mary <mary@test> added the comment:
705 A message with encoding (encoded oe =C3=B6)
707 ----------
708 status: unread -> chatting
709 _______________________________________________________________________
710 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
711 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
712 _______________________________________________________________________
713 ''')
716 def testMultipartEnc01(self):
717 self.doNewIssue()
718 self._send_mail('''Content-Type: text/plain;
719 charset="iso-8859-1"
720 From: mary <mary@test>
721 To: issue_tracker@your.tracker.email.domain.example
722 Message-Id: <followup_dummy_id>
723 In-Reply-To: <dummy_test_message_id>
724 Subject: [issue1] Testing...
725 Content-Type: multipart/mixed;
726 boundary="----_=_NextPart_000_01"
728 This message is in MIME format. Since your mail reader does not understand
729 this format, some or all of this message may not be legible.
731 ------_=_NextPart_000_01
732 Content-Type: text/plain;
733 charset="iso-8859-1"
734 Content-Transfer-Encoding: quoted-printable
736 A message with first part encoded (encoded oe =F6)
738 ''')
739 self.compareMessages(self._get_mail(),
740 '''FROM: roundup-admin@your.tracker.email.domain.example
741 TO: chef@bork.bork.bork, richard@test
742 Content-Type: text/plain; charset=utf-8
743 Subject: [issue1] Testing...
744 To: chef@bork.bork.bork, richard@test
745 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
746 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
747 MIME-Version: 1.0
748 Message-Id: <followup_dummy_id>
749 In-Reply-To: <dummy_test_message_id>
750 X-Roundup-Name: Roundup issue tracker
751 X-Roundup-Loop: hello
752 Content-Transfer-Encoding: quoted-printable
755 Contrary, Mary <mary@test> added the comment:
757 A message with first part encoded (encoded oe =C3=B6)
759 ----------
760 status: unread -> chatting
761 _______________________________________________________________________
762 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
763 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
764 _______________________________________________________________________
765 ''')
767 def testContentDisposition(self):
768 self.doNewIssue()
769 self._send_mail('''Content-Type: text/plain;
770 charset="iso-8859-1"
771 From: mary <mary@test>
772 To: issue_tracker@your.tracker.email.domain.example
773 Message-Id: <followup_dummy_id>
774 In-Reply-To: <dummy_test_message_id>
775 Subject: [issue1] Testing...
776 Content-Type: multipart/mixed; boundary="bCsyhTFzCvuiizWE"
777 Content-Disposition: inline
780 --bCsyhTFzCvuiizWE
781 Content-Type: text/plain; charset=us-ascii
782 Content-Disposition: inline
784 test attachment binary
786 --bCsyhTFzCvuiizWE
787 Content-Type: application/octet-stream
788 Content-Disposition: attachment; filename="main.dvi"
790 xxxxxx
792 --bCsyhTFzCvuiizWE--
793 ''')
794 messages = self.db.issue.get('1', 'messages')
795 messages.sort()
796 file = self.db.msg.get(messages[-1], 'files')[0]
797 self.assertEqual(self.db.file.get(file, 'name'), 'main.dvi')
799 def testFollowupStupidQuoting(self):
800 self.doNewIssue()
802 self._send_mail('''Content-Type: text/plain;
803 charset="iso-8859-1"
804 From: richard <richard@test>
805 To: issue_tracker@your.tracker.email.domain.example
806 Message-Id: <followup_dummy_id>
807 In-Reply-To: <dummy_test_message_id>
808 Subject: Re: "[issue1] Testing... "
810 This is a followup
811 ''')
812 self.compareMessages(self._get_mail(),
813 '''FROM: roundup-admin@your.tracker.email.domain.example
814 TO: chef@bork.bork.bork
815 Content-Type: text/plain; charset=utf-8
816 Subject: [issue1] Testing...
817 To: chef@bork.bork.bork
818 From: richard <issue_tracker@your.tracker.email.domain.example>
819 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
820 MIME-Version: 1.0
821 Message-Id: <followup_dummy_id>
822 In-Reply-To: <dummy_test_message_id>
823 X-Roundup-Name: Roundup issue tracker
824 X-Roundup-Loop: hello
825 Content-Transfer-Encoding: quoted-printable
828 richard <richard@test> added the comment:
830 This is a followup
832 ----------
833 status: unread -> chatting
834 _______________________________________________________________________
835 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
836 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
837 _______________________________________________________________________
838 ''')
840 def testEmailQuoting(self):
841 self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
842 self.innerTestQuoting('''This is a followup
843 ''')
845 def testEmailQuotingRemove(self):
846 self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
847 self.innerTestQuoting('''Blah blah wrote:
848 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
849 > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
850 >
852 This is a followup
853 ''')
855 def innerTestQuoting(self, expect):
856 nodeid = self.doNewIssue()
858 messages = self.db.issue.get(nodeid, 'messages')
860 self._send_mail('''Content-Type: text/plain;
861 charset="iso-8859-1"
862 From: richard <richard@test>
863 To: issue_tracker@your.tracker.email.domain.example
864 Message-Id: <followup_dummy_id>
865 In-Reply-To: <dummy_test_message_id>
866 Subject: Re: [issue1] Testing...
868 Blah blah wrote:
869 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
870 > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
871 >
873 This is a followup
874 ''')
875 # figure the new message id
876 newmessages = self.db.issue.get(nodeid, 'messages')
877 for msg in messages:
878 newmessages.remove(msg)
879 messageid = newmessages[0]
881 self.compareMessages(self.db.msg.get(messageid, 'content'), expect)
883 def testUserLookup(self):
884 i = self.db.user.create(username='user1', address='user1@foo.com')
885 self.assertEqual(uidFromAddress(self.db, ('', 'user1@foo.com'), 0), i)
886 self.assertEqual(uidFromAddress(self.db, ('', 'USER1@foo.com'), 0), i)
887 i = self.db.user.create(username='user2', address='USER2@foo.com')
888 self.assertEqual(uidFromAddress(self.db, ('', 'USER2@foo.com'), 0), i)
889 self.assertEqual(uidFromAddress(self.db, ('', 'user2@foo.com'), 0), i)
891 def testUserAlternateLookup(self):
892 i = self.db.user.create(username='user1', address='user1@foo.com',
893 alternate_addresses='user1@bar.com')
894 self.assertEqual(uidFromAddress(self.db, ('', 'user1@bar.com'), 0), i)
895 self.assertEqual(uidFromAddress(self.db, ('', 'USER1@bar.com'), 0), i)
897 def testUserCreate(self):
898 i = uidFromAddress(self.db, ('', 'user@foo.com'), 1)
899 self.assertNotEqual(uidFromAddress(self.db, ('', 'user@bar.com'), 1), i)
901 def testRFC2822(self):
902 ascii_header = "[issue243] This is a \"test\" - with 'quotation' marks"
903 unicode_header = '[issue244] \xd0\xb0\xd0\xbd\xd0\xb4\xd1\x80\xd0\xb5\xd0\xb9'
904 unicode_encoded = '=?utf-8?q?[issue244]_=D0=B0=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?='
905 self.assertEqual(rfc2822.encode_header(ascii_header), ascii_header)
906 self.assertEqual(rfc2822.encode_header(unicode_header), unicode_encoded)
908 def testRegistrationConfirmation(self):
909 otk = "Aj4euk4LZSAdwePohj90SME5SpopLETL"
910 self.db.otks.set(otk, username='johannes', __time='')
911 self._send_mail('''Content-Type: text/plain;
912 charset="iso-8859-1"
913 From: Chef <chef@bork.bork.bork>
914 To: issue_tracker@your.tracker.email.domain.example
915 Cc: richard@test
916 Message-Id: <dummy_test_message_id>
917 Subject: Re: Complete your registration to Roundup issue tracker\r
918 -- key %s
920 This is a test confirmation of registration.
921 ''' % otk)
922 self.db.user.lookup('johannes')
924 def testFollowupOnNonIssue(self):
925 self.db.keyword.create(name='Foo')
926 self._send_mail('''Content-Type: text/plain;
927 charset="iso-8859-1"
928 From: richard <richard@test>
929 To: issue_tracker@your.tracker.email.domain.example
930 Message-Id: <followup_dummy_id>
931 In-Reply-To: <dummy_test_message_id>
932 Subject: [keyword1] Testing... [name=Bar]
934 ''')
935 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
937 def test_suite():
938 suite = unittest.TestSuite()
939 suite.addTest(unittest.makeSuite(MailgwTestCase))
940 return suite
942 if __name__ == '__main__':
943 runner = unittest.TextTestRunner()
944 unittest.main(testRunner=runner)
946 # vim: set filetype=python ts=4 sw=4 et si