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()))
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)
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
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
914 >
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
935 >
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')
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