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.96 2008-08-19 01:40:59 richard Exp $
13 # TODO: test bcc
15 import unittest, tempfile, os, shutil, errno, imp, sys, difflib, rfc822, time
17 from cStringIO import StringIO
19 if not os.environ.has_key('SENDMAILDEBUG'):
20 os.environ['SENDMAILDEBUG'] = 'mail-test.log'
21 SENDMAILDEBUG = os.environ['SENDMAILDEBUG']
23 from roundup.mailgw import MailGW, Unauthorized, uidFromAddress, \
24 parseContent, IgnoreLoop, IgnoreBulk, MailUsageError, MailUsageHelp
25 from roundup import init, instance, password, rfc2822, __version__
27 import db_test_base
29 class Message(rfc822.Message):
30 """String-based Message class with equivalence test."""
31 def __init__(self, s):
32 rfc822.Message.__init__(self, StringIO(s.strip()))
34 def __eq__(self, other):
35 return (self.dict == other.dict and
36 self.fp.read() == other.fp.read())
38 class DiffHelper:
39 def compareMessages(self, new, old):
40 """Compare messages for semantic equivalence."""
41 new, old = Message(new), Message(old)
43 # all Roundup-generated messages have "Precedence: bulk"
44 old['Precedence'] = 'bulk'
46 # don't try to compare the date
47 del new['date'], old['date']
49 if not new == old:
50 res = []
52 for key in new.keys():
53 if key.lower() == 'x-roundup-version':
54 # version changes constantly, so handle it specially
55 if new[key] != __version__:
56 res.append(' %s: %r != %r' % (key, __version__,
57 new[key]))
58 elif new.get(key, '') != old.get(key, ''):
59 res.append(' %s: %r != %r' % (key, old.get(key, ''),
60 new.get(key, '')))
62 body_diff = self.compareStrings(new.fp.read(), old.fp.read())
63 if body_diff:
64 res.append('')
65 res.extend(body_diff)
67 if res:
68 res.insert(0, 'Generated message not correct (diff follows):')
69 raise AssertionError, '\n'.join(res)
71 def compareStrings(self, s2, s1):
72 '''Note the reversal of s2 and s1 - difflib.SequenceMatcher wants
73 the first to be the "original" but in the calls in this file,
74 the second arg is the original. Ho hum.
75 '''
76 l1 = s1.strip().split('\n')
77 l2 = s2.strip().split('\n')
78 if l1 == l2:
79 return
80 s = difflib.SequenceMatcher(None, l1, l2)
81 res = []
82 for value, s1s, s1e, s2s, s2e in s.get_opcodes():
83 if value == 'equal':
84 for i in range(s1s, s1e):
85 res.append(' %s'%l1[i])
86 elif value == 'delete':
87 for i in range(s1s, s1e):
88 res.append('- %s'%l1[i])
89 elif value == 'insert':
90 for i in range(s2s, s2e):
91 res.append('+ %s'%l2[i])
92 elif value == 'replace':
93 for i, j in zip(range(s1s, s1e), range(s2s, s2e)):
94 res.append('- %s'%l1[i])
95 res.append('+ %s'%l2[j])
97 return res
99 class MailgwTestCase(unittest.TestCase, DiffHelper):
100 count = 0
101 schema = 'classic'
102 def setUp(self):
103 MailgwTestCase.count = MailgwTestCase.count + 1
104 self.dirname = '_test_mailgw_%s'%self.count
105 # set up and open a tracker
106 self.instance = db_test_base.setupTracker(self.dirname)
108 # and open the database
109 self.db = self.instance.open('admin')
110 self.chef_id = self.db.user.create(username='Chef',
111 address='chef@bork.bork.bork', realname='Bork, Chef', roles='User')
112 self.richard_id = self.db.user.create(username='richard',
113 address='richard@test.test', roles='User')
114 self.mary_id = self.db.user.create(username='mary', address='mary@test.test',
115 roles='User', realname='Contrary, Mary')
116 self.john_id = self.db.user.create(username='john', address='john@test.test',
117 alternate_addresses='jondoe@test.test\njohn.doe@test.test', roles='User',
118 realname='John Doe')
120 def tearDown(self):
121 if os.path.exists(SENDMAILDEBUG):
122 os.remove(SENDMAILDEBUG)
123 self.db.close()
124 try:
125 shutil.rmtree(self.dirname)
126 except OSError, error:
127 if error.errno not in (errno.ENOENT, errno.ESRCH): raise
129 def _handle_mail(self, message):
130 handler = self.instance.MailGW(self.instance, self.db)
131 handler.trapExceptions = 0
132 ret = handler.main(StringIO(message))
133 # handler can close the db on us and open a new one
134 self.db = handler.db
135 return ret
137 def _get_mail(self):
138 f = open(SENDMAILDEBUG)
139 try:
140 return f.read()
141 finally:
142 f.close()
144 def testEmptyMessage(self):
145 nodeid = self._handle_mail('''Content-Type: text/plain;
146 charset="iso-8859-1"
147 From: Chef <chef@bork.bork.bork>
148 To: issue_tracker@your.tracker.email.domain.example
149 Cc: richard@test.test
150 Reply-To: chef@bork.bork.bork
151 Message-Id: <dummy_test_message_id>
152 Subject: [issue] Testing...
154 ''')
155 assert not os.path.exists(SENDMAILDEBUG)
156 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
158 def doNewIssue(self):
159 nodeid = self._handle_mail('''Content-Type: text/plain;
160 charset="iso-8859-1"
161 From: Chef <chef@bork.bork.bork>
162 To: issue_tracker@your.tracker.email.domain.example
163 Cc: richard@test.test
164 Message-Id: <dummy_test_message_id>
165 Subject: [issue] Testing...
167 This is a test submission of a new issue.
168 ''')
169 assert not os.path.exists(SENDMAILDEBUG)
170 l = self.db.issue.get(nodeid, 'nosy')
171 l.sort()
172 self.assertEqual(l, [self.chef_id, self.richard_id])
173 return nodeid
175 def testNewIssue(self):
176 self.doNewIssue()
178 def testNewIssueNosy(self):
179 self.instance.config.ADD_AUTHOR_TO_NOSY = 'yes'
180 nodeid = self._handle_mail('''Content-Type: text/plain;
181 charset="iso-8859-1"
182 From: Chef <chef@bork.bork.bork>
183 To: issue_tracker@your.tracker.email.domain.example
184 Cc: richard@test.test
185 Message-Id: <dummy_test_message_id>
186 Subject: [issue] Testing...
188 This is a test submission of a new issue.
189 ''')
190 assert not os.path.exists(SENDMAILDEBUG)
191 l = self.db.issue.get(nodeid, 'nosy')
192 l.sort()
193 self.assertEqual(l, [self.chef_id, self.richard_id])
195 def testAlternateAddress(self):
196 self._handle_mail('''Content-Type: text/plain;
197 charset="iso-8859-1"
198 From: John Doe <john.doe@test.test>
199 To: issue_tracker@your.tracker.email.domain.example
200 Message-Id: <dummy_test_message_id>
201 Subject: [issue] Testing...
203 This is a test submission of a new issue.
204 ''')
205 userlist = self.db.user.list()
206 assert not os.path.exists(SENDMAILDEBUG)
207 self.assertEqual(userlist, self.db.user.list(),
208 "user created when it shouldn't have been")
210 def testNewIssueNoClass(self):
211 self._handle_mail('''Content-Type: text/plain;
212 charset="iso-8859-1"
213 From: Chef <chef@bork.bork.bork>
214 To: issue_tracker@your.tracker.email.domain.example
215 Cc: richard@test.test
216 Message-Id: <dummy_test_message_id>
217 Subject: Testing...
219 This is a test submission of a new issue.
220 ''')
221 assert not os.path.exists(SENDMAILDEBUG)
223 def testNewIssueAuthMsg(self):
224 # TODO: fix the damn config - this is apalling
225 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
226 self._handle_mail('''Content-Type: text/plain;
227 charset="iso-8859-1"
228 From: Chef <chef@bork.bork.bork>
229 To: issue_tracker@your.tracker.email.domain.example
230 Message-Id: <dummy_test_message_id>
231 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
233 This is a test submission of a new issue.
234 ''')
235 self.compareMessages(self._get_mail(),
236 '''FROM: roundup-admin@your.tracker.email.domain.example
237 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
238 Content-Type: text/plain; charset=utf-8
239 Subject: [issue1] Testing...
240 To: chef@bork.bork.bork, mary@test.test, richard@test.test
241 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
242 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
243 MIME-Version: 1.0
244 Message-Id: <dummy_test_message_id>
245 X-Roundup-Name: Roundup issue tracker
246 X-Roundup-Loop: hello
247 X-Roundup-Issue-Status: unread
248 Content-Transfer-Encoding: quoted-printable
251 New submission from Bork, Chef <chef@bork.bork.bork>:
253 This is a test submission of a new issue.
255 ----------
256 assignedto: richard
257 messages: 1
258 nosy: Chef, mary, richard
259 status: unread
260 title: Testing...
262 _______________________________________________________________________
263 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
264 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
265 _______________________________________________________________________
266 ''')
268 def testNewIssueNoAuthorInfo(self):
269 self.db.config.MAIL_ADD_AUTHORINFO = 'no'
270 self._handle_mail('''Content-Type: text/plain;
271 charset="iso-8859-1"
272 From: Chef <chef@bork.bork.bork>
273 To: issue_tracker@your.tracker.email.domain.example
274 Message-Id: <dummy_test_message_id>
275 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
277 This is a test submission of a new issue.
278 ''')
279 self.compareMessages(self._get_mail(),
280 '''FROM: roundup-admin@your.tracker.email.domain.example
281 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
282 Content-Type: text/plain; charset=utf-8
283 Subject: [issue1] Testing...
284 To: mary@test.test, richard@test.test
285 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
286 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
287 MIME-Version: 1.0
288 Message-Id: <dummy_test_message_id>
289 X-Roundup-Name: Roundup issue tracker
290 X-Roundup-Loop: hello
291 X-Roundup-Issue-Status: unread
292 Content-Transfer-Encoding: quoted-printable
294 This is a test submission of a new issue.
296 ----------
297 assignedto: richard
298 messages: 1
299 nosy: Chef, mary, richard
300 status: unread
301 title: Testing...
303 _______________________________________________________________________
304 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
305 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
306 _______________________________________________________________________
307 ''')
309 def testNewIssueNoAuthorEmail(self):
310 self.db.config.MAIL_ADD_AUTHOREMAIL = 'no'
311 self._handle_mail('''Content-Type: text/plain;
312 charset="iso-8859-1"
313 From: Chef <chef@bork.bork.bork>
314 To: issue_tracker@your.tracker.email.domain.example
315 Message-Id: <dummy_test_message_id>
316 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
318 This is a test submission of a new issue.
319 ''')
320 self.compareMessages(self._get_mail(),
321 '''FROM: roundup-admin@your.tracker.email.domain.example
322 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
323 Content-Type: text/plain; charset=utf-8
324 Subject: [issue1] Testing...
325 To: mary@test.test, richard@test.test
326 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
327 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
328 MIME-Version: 1.0
329 Message-Id: <dummy_test_message_id>
330 X-Roundup-Name: Roundup issue tracker
331 X-Roundup-Loop: hello
332 X-Roundup-Issue-Status: unread
333 Content-Transfer-Encoding: quoted-printable
335 New submission from Bork, Chef:
337 This is a test submission of a new issue.
339 ----------
340 assignedto: richard
341 messages: 1
342 nosy: Chef, mary, richard
343 status: unread
344 title: Testing...
346 _______________________________________________________________________
347 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
348 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
349 _______________________________________________________________________
350 ''')
352 multipart_msg = '''From: mary <mary@test.test>
353 To: issue_tracker@your.tracker.email.domain.example
354 Message-Id: <followup_dummy_id>
355 In-Reply-To: <dummy_test_message_id>
356 Subject: [issue1] Testing...
357 Content-Type: multipart/mixed; boundary="bxyzzy"
358 Content-Disposition: inline
361 --bxyzzy
362 Content-Type: multipart/alternative; boundary="bCsyhTFzCvuiizWE"
363 Content-Disposition: inline
365 --bCsyhTFzCvuiizWE
366 Content-Type: text/plain; charset=us-ascii
367 Content-Disposition: inline
369 test attachment first text/plain
371 --bCsyhTFzCvuiizWE
372 Content-Type: application/octet-stream
373 Content-Disposition: attachment; filename="first.dvi"
374 Content-Transfer-Encoding: base64
376 SnVzdCBhIHRlc3QgAQo=
378 --bCsyhTFzCvuiizWE
379 Content-Type: text/plain; charset=us-ascii
380 Content-Disposition: inline
382 test attachment second text/plain
384 --bCsyhTFzCvuiizWE
385 Content-Type: text/html
386 Content-Disposition: inline
388 <html>
389 to be ignored.
390 </html>
392 --bCsyhTFzCvuiizWE--
394 --bxyzzy
395 Content-Type: multipart/alternative; boundary="bCsyhTFzCvuiizWF"
396 Content-Disposition: inline
398 --bCsyhTFzCvuiizWF
399 Content-Type: text/plain; charset=us-ascii
400 Content-Disposition: inline
402 test attachment third text/plain
404 --bCsyhTFzCvuiizWF
405 Content-Type: application/octet-stream
406 Content-Disposition: attachment; filename="second.dvi"
407 Content-Transfer-Encoding: base64
409 SnVzdCBhIHRlc3QK
411 --bCsyhTFzCvuiizWF--
413 --bxyzzy--
414 '''
416 def testMultipartKeepAlternatives(self):
417 self.doNewIssue()
418 self._handle_mail(self.multipart_msg)
419 messages = self.db.issue.get('1', 'messages')
420 messages.sort()
421 msg = self.db.msg.getnode (messages[-1])
422 assert(len(msg.files) == 5)
423 names = {0 : 'first.dvi', 4 : 'second.dvi'}
424 content = {3 : 'test attachment third text/plain\n',
425 4 : 'Just a test\n'}
426 for n, id in enumerate (msg.files):
427 f = self.db.file.getnode (id)
428 self.assertEqual(f.name, names.get (n, 'unnamed'))
429 if n in content :
430 self.assertEqual(f.content, content [n])
431 self.assertEqual(msg.content, 'test attachment second text/plain')
433 def testMultipartDropAlternatives(self):
434 self.doNewIssue()
435 self.db.config.MAILGW_IGNORE_ALTERNATIVES = True
436 self._handle_mail(self.multipart_msg)
437 messages = self.db.issue.get('1', 'messages')
438 messages.sort()
439 msg = self.db.msg.getnode (messages[-1])
440 assert(len(msg.files) == 2)
441 names = {1 : 'second.dvi'}
442 content = {0 : 'test attachment third text/plain\n',
443 1 : 'Just a test\n'}
444 for n, id in enumerate (msg.files):
445 f = self.db.file.getnode (id)
446 self.assertEqual(f.name, names.get (n, 'unnamed'))
447 if n in content :
448 self.assertEqual(f.content, content [n])
449 self.assertEqual(msg.content, 'test attachment second text/plain')
451 def testSimpleFollowup(self):
452 self.doNewIssue()
453 self._handle_mail('''Content-Type: text/plain;
454 charset="iso-8859-1"
455 From: mary <mary@test.test>
456 To: issue_tracker@your.tracker.email.domain.example
457 Message-Id: <followup_dummy_id>
458 In-Reply-To: <dummy_test_message_id>
459 Subject: [issue1] Testing...
461 This is a second followup
462 ''')
463 self.compareMessages(self._get_mail(),
464 '''FROM: roundup-admin@your.tracker.email.domain.example
465 TO: chef@bork.bork.bork, richard@test.test
466 Content-Type: text/plain; charset=utf-8
467 Subject: [issue1] Testing...
468 To: chef@bork.bork.bork, richard@test.test
469 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
470 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
471 MIME-Version: 1.0
472 Message-Id: <followup_dummy_id>
473 In-Reply-To: <dummy_test_message_id>
474 X-Roundup-Name: Roundup issue tracker
475 X-Roundup-Loop: hello
476 X-Roundup-Issue-Status: chatting
477 Content-Transfer-Encoding: quoted-printable
480 Contrary, Mary <mary@test.test> added the comment:
482 This is a second followup
484 ----------
485 status: unread -> chatting
487 _______________________________________________________________________
488 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
489 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
490 _______________________________________________________________________
491 ''')
493 def testFollowup(self):
494 self.doNewIssue()
496 self._handle_mail('''Content-Type: text/plain;
497 charset="iso-8859-1"
498 From: richard <richard@test.test>
499 To: issue_tracker@your.tracker.email.domain.example
500 Message-Id: <followup_dummy_id>
501 In-Reply-To: <dummy_test_message_id>
502 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
504 This is a followup
505 ''')
506 l = self.db.issue.get('1', 'nosy')
507 l.sort()
508 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
509 self.john_id])
511 self.compareMessages(self._get_mail(),
512 '''FROM: roundup-admin@your.tracker.email.domain.example
513 TO: chef@bork.bork.bork, john@test.test, mary@test.test
514 Content-Type: text/plain; charset=utf-8
515 Subject: [issue1] Testing...
516 To: chef@bork.bork.bork, john@test.test, mary@test.test
517 From: richard <issue_tracker@your.tracker.email.domain.example>
518 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
519 MIME-Version: 1.0
520 Message-Id: <followup_dummy_id>
521 In-Reply-To: <dummy_test_message_id>
522 X-Roundup-Name: Roundup issue tracker
523 X-Roundup-Loop: hello
524 X-Roundup-Issue-Status: chatting
525 Content-Transfer-Encoding: quoted-printable
528 richard <richard@test.test> added the comment:
530 This is a followup
532 ----------
533 assignedto: -> mary
534 nosy: +john, mary
535 status: unread -> chatting
537 _______________________________________________________________________
538 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
539 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
540 _______________________________________________________________________
541 ''')
543 def testPropertyChangeOnly(self):
544 self.doNewIssue()
545 oldvalues = self.db.getnode('issue', '1').copy()
546 oldvalues['assignedto'] = None
547 self.db.issue.set('1', assignedto=self.chef_id)
548 self.db.commit()
549 self.db.issue.nosymessage('1', None, oldvalues)
551 new_mail = ""
552 for line in self._get_mail().split("\n"):
553 if "Message-Id: " in line:
554 continue
555 if "Date: " in line:
556 continue
557 new_mail += line+"\n"
559 self.compareMessages(new_mail, """
560 FROM: roundup-admin@your.tracker.email.domain.example
561 TO: chef@bork.bork.bork, richard@test.test
562 Content-Type: text/plain; charset=utf-8
563 Subject: [issue1] Testing...
564 To: chef@bork.bork.bork, richard@test.test
565 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
566 X-Roundup-Name: Roundup issue tracker
567 X-Roundup-Loop: hello
568 X-Roundup-Issue-Status: unread
569 X-Roundup-Version: 1.3.3
570 MIME-Version: 1.0
571 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
572 Content-Transfer-Encoding: quoted-printable
575 Change by Bork, Chef <chef@bork.bork.bork>:
578 ----------
579 assignedto: -> Chef
581 _______________________________________________________________________
582 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
583 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
584 _______________________________________________________________________
585 """)
588 #
589 # FOLLOWUP TITLE MATCH
590 #
591 def testFollowupTitleMatch(self):
592 self.doNewIssue()
593 self._handle_mail('''Content-Type: text/plain;
594 charset="iso-8859-1"
595 From: richard <richard@test.test>
596 To: issue_tracker@your.tracker.email.domain.example
597 Message-Id: <followup_dummy_id>
598 Subject: Re: Testing... [assignedto=mary; nosy=+john]
600 This is a followup
601 ''')
602 self.compareMessages(self._get_mail(),
603 '''FROM: roundup-admin@your.tracker.email.domain.example
604 TO: chef@bork.bork.bork, john@test.test, mary@test.test
605 Content-Type: text/plain; charset=utf-8
606 Subject: [issue1] Testing...
607 To: chef@bork.bork.bork, john@test.test, mary@test.test
608 From: richard <issue_tracker@your.tracker.email.domain.example>
609 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
610 MIME-Version: 1.0
611 Message-Id: <followup_dummy_id>
612 In-Reply-To: <dummy_test_message_id>
613 X-Roundup-Name: Roundup issue tracker
614 X-Roundup-Loop: hello
615 X-Roundup-Issue-Status: chatting
616 Content-Transfer-Encoding: quoted-printable
619 richard <richard@test.test> added the comment:
621 This is a followup
623 ----------
624 assignedto: -> mary
625 nosy: +john, mary
626 status: unread -> chatting
628 _______________________________________________________________________
629 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
630 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
631 _______________________________________________________________________
632 ''')
634 def testFollowupTitleMatchMultiRe(self):
635 nodeid1 = self.doNewIssue()
636 nodeid2 = self._handle_mail('''Content-Type: text/plain;
637 charset="iso-8859-1"
638 From: richard <richard@test.test>
639 To: issue_tracker@your.tracker.email.domain.example
640 Message-Id: <followup_dummy_id>
641 Subject: Re: Testing... [assignedto=mary; nosy=+john]
643 This is a followup
644 ''')
646 nodeid3 = self._handle_mail('''Content-Type: text/plain;
647 charset="iso-8859-1"
648 From: richard <richard@test.test>
649 To: issue_tracker@your.tracker.email.domain.example
650 Message-Id: <followup2_dummy_id>
651 Subject: Ang: Re: Testing...
653 This is a followup
654 ''')
655 self.assertEqual(nodeid1, nodeid2)
656 self.assertEqual(nodeid1, nodeid3)
658 def testFollowupTitleMatchNever(self):
659 nodeid = self.doNewIssue()
660 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'never'
661 self.assertNotEqual(self._handle_mail('''Content-Type: text/plain;
662 charset="iso-8859-1"
663 From: richard <richard@test.test>
664 To: issue_tracker@your.tracker.email.domain.example
665 Message-Id: <followup_dummy_id>
666 Subject: Re: Testing...
668 This is a followup
669 '''), nodeid)
671 def testFollowupTitleMatchNeverInterval(self):
672 nodeid = self.doNewIssue()
673 # force failure of the interval
674 time.sleep(2)
675 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation 00:00:01'
676 self.assertNotEqual(self._handle_mail('''Content-Type: text/plain;
677 charset="iso-8859-1"
678 From: richard <richard@test.test>
679 To: issue_tracker@your.tracker.email.domain.example
680 Message-Id: <followup_dummy_id>
681 Subject: Re: Testing...
683 This is a followup
684 '''), nodeid)
687 def testFollowupTitleMatchInterval(self):
688 nodeid = self.doNewIssue()
689 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation +1d'
690 self.assertEqual(self._handle_mail('''Content-Type: text/plain;
691 charset="iso-8859-1"
692 From: richard <richard@test.test>
693 To: issue_tracker@your.tracker.email.domain.example
694 Message-Id: <followup_dummy_id>
695 Subject: Re: Testing...
697 This is a followup
698 '''), nodeid)
701 def testFollowupNosyAuthor(self):
702 self.doNewIssue()
703 self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
704 self._handle_mail('''Content-Type: text/plain;
705 charset="iso-8859-1"
706 From: john@test.test
707 To: issue_tracker@your.tracker.email.domain.example
708 Message-Id: <followup_dummy_id>
709 In-Reply-To: <dummy_test_message_id>
710 Subject: [issue1] Testing...
712 This is a followup
713 ''')
715 self.compareMessages(self._get_mail(),
716 '''FROM: roundup-admin@your.tracker.email.domain.example
717 TO: chef@bork.bork.bork, richard@test.test
718 Content-Type: text/plain; charset=utf-8
719 Subject: [issue1] Testing...
720 To: chef@bork.bork.bork, richard@test.test
721 From: John Doe <issue_tracker@your.tracker.email.domain.example>
722 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
723 MIME-Version: 1.0
724 Message-Id: <followup_dummy_id>
725 In-Reply-To: <dummy_test_message_id>
726 X-Roundup-Name: Roundup issue tracker
727 X-Roundup-Loop: hello
728 X-Roundup-Issue-Status: chatting
729 Content-Transfer-Encoding: quoted-printable
732 John Doe <john@test.test> added the comment:
734 This is a followup
736 ----------
737 nosy: +john
738 status: unread -> chatting
740 _______________________________________________________________________
741 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
742 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
743 _______________________________________________________________________
745 ''')
747 def testFollowupNosyRecipients(self):
748 self.doNewIssue()
749 self.db.config.ADD_RECIPIENTS_TO_NOSY = 'yes'
750 self._handle_mail('''Content-Type: text/plain;
751 charset="iso-8859-1"
752 From: richard@test.test
753 To: issue_tracker@your.tracker.email.domain.example
754 Cc: john@test.test
755 Message-Id: <followup_dummy_id>
756 In-Reply-To: <dummy_test_message_id>
757 Subject: [issue1] Testing...
759 This is a followup
760 ''')
761 self.compareMessages(self._get_mail(),
762 '''FROM: roundup-admin@your.tracker.email.domain.example
763 TO: chef@bork.bork.bork
764 Content-Type: text/plain; charset=utf-8
765 Subject: [issue1] Testing...
766 To: chef@bork.bork.bork
767 From: richard <issue_tracker@your.tracker.email.domain.example>
768 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
769 MIME-Version: 1.0
770 Message-Id: <followup_dummy_id>
771 In-Reply-To: <dummy_test_message_id>
772 X-Roundup-Name: Roundup issue tracker
773 X-Roundup-Loop: hello
774 X-Roundup-Issue-Status: chatting
775 Content-Transfer-Encoding: quoted-printable
778 richard <richard@test.test> added the comment:
780 This is a followup
782 ----------
783 nosy: +john
784 status: unread -> chatting
786 _______________________________________________________________________
787 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
788 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
789 _______________________________________________________________________
791 ''')
793 def testFollowupNosyAuthorAndCopy(self):
794 self.doNewIssue()
795 self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
796 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
797 self._handle_mail('''Content-Type: text/plain;
798 charset="iso-8859-1"
799 From: john@test.test
800 To: issue_tracker@your.tracker.email.domain.example
801 Message-Id: <followup_dummy_id>
802 In-Reply-To: <dummy_test_message_id>
803 Subject: [issue1] Testing...
805 This is a followup
806 ''')
807 self.compareMessages(self._get_mail(),
808 '''FROM: roundup-admin@your.tracker.email.domain.example
809 TO: chef@bork.bork.bork, john@test.test, richard@test.test
810 Content-Type: text/plain; charset=utf-8
811 Subject: [issue1] Testing...
812 To: chef@bork.bork.bork, john@test.test, richard@test.test
813 From: John Doe <issue_tracker@your.tracker.email.domain.example>
814 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
815 MIME-Version: 1.0
816 Message-Id: <followup_dummy_id>
817 In-Reply-To: <dummy_test_message_id>
818 X-Roundup-Name: Roundup issue tracker
819 X-Roundup-Loop: hello
820 X-Roundup-Issue-Status: chatting
821 Content-Transfer-Encoding: quoted-printable
824 John Doe <john@test.test> added the comment:
826 This is a followup
828 ----------
829 nosy: +john
830 status: unread -> chatting
832 _______________________________________________________________________
833 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
834 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
835 _______________________________________________________________________
837 ''')
839 def testFollowupNoNosyAuthor(self):
840 self.doNewIssue()
841 self.instance.config.ADD_AUTHOR_TO_NOSY = 'no'
842 self._handle_mail('''Content-Type: text/plain;
843 charset="iso-8859-1"
844 From: john@test.test
845 To: issue_tracker@your.tracker.email.domain.example
846 Message-Id: <followup_dummy_id>
847 In-Reply-To: <dummy_test_message_id>
848 Subject: [issue1] Testing...
850 This is a followup
851 ''')
852 self.compareMessages(self._get_mail(),
853 '''FROM: roundup-admin@your.tracker.email.domain.example
854 TO: chef@bork.bork.bork, richard@test.test
855 Content-Type: text/plain; charset=utf-8
856 Subject: [issue1] Testing...
857 To: chef@bork.bork.bork, richard@test.test
858 From: John Doe <issue_tracker@your.tracker.email.domain.example>
859 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
860 MIME-Version: 1.0
861 Message-Id: <followup_dummy_id>
862 In-Reply-To: <dummy_test_message_id>
863 X-Roundup-Name: Roundup issue tracker
864 X-Roundup-Loop: hello
865 X-Roundup-Issue-Status: chatting
866 Content-Transfer-Encoding: quoted-printable
869 John Doe <john@test.test> added the comment:
871 This is a followup
873 ----------
874 status: unread -> chatting
876 _______________________________________________________________________
877 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
878 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
879 _______________________________________________________________________
881 ''')
883 def testFollowupNoNosyRecipients(self):
884 self.doNewIssue()
885 self.instance.config.ADD_RECIPIENTS_TO_NOSY = 'no'
886 self._handle_mail('''Content-Type: text/plain;
887 charset="iso-8859-1"
888 From: richard@test.test
889 To: issue_tracker@your.tracker.email.domain.example
890 Cc: john@test.test
891 Message-Id: <followup_dummy_id>
892 In-Reply-To: <dummy_test_message_id>
893 Subject: [issue1] Testing...
895 This is a followup
896 ''')
897 self.compareMessages(self._get_mail(),
898 '''FROM: roundup-admin@your.tracker.email.domain.example
899 TO: chef@bork.bork.bork
900 Content-Type: text/plain; charset=utf-8
901 Subject: [issue1] Testing...
902 To: chef@bork.bork.bork
903 From: richard <issue_tracker@your.tracker.email.domain.example>
904 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
905 MIME-Version: 1.0
906 Message-Id: <followup_dummy_id>
907 In-Reply-To: <dummy_test_message_id>
908 X-Roundup-Name: Roundup issue tracker
909 X-Roundup-Loop: hello
910 X-Roundup-Issue-Status: chatting
911 Content-Transfer-Encoding: quoted-printable
914 richard <richard@test.test> added the comment:
916 This is a followup
918 ----------
919 status: unread -> chatting
921 _______________________________________________________________________
922 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
923 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
924 _______________________________________________________________________
926 ''')
928 def testFollowupEmptyMessage(self):
929 self.doNewIssue()
931 self._handle_mail('''Content-Type: text/plain;
932 charset="iso-8859-1"
933 From: richard <richard@test.test>
934 To: issue_tracker@your.tracker.email.domain.example
935 Message-Id: <followup_dummy_id>
936 In-Reply-To: <dummy_test_message_id>
937 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
939 ''')
940 l = self.db.issue.get('1', 'nosy')
941 l.sort()
942 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
943 self.john_id])
945 # should be no file created (ie. no message)
946 assert not os.path.exists(SENDMAILDEBUG)
948 def testFollowupEmptyMessageNoSubject(self):
949 self.doNewIssue()
951 self._handle_mail('''Content-Type: text/plain;
952 charset="iso-8859-1"
953 From: richard <richard@test.test>
954 To: issue_tracker@your.tracker.email.domain.example
955 Message-Id: <followup_dummy_id>
956 In-Reply-To: <dummy_test_message_id>
957 Subject: [issue1] [assignedto=mary; nosy=+john]
959 ''')
960 l = self.db.issue.get('1', 'nosy')
961 l.sort()
962 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
963 self.john_id])
965 # should be no file created (ie. no message)
966 assert not os.path.exists(SENDMAILDEBUG)
968 def testNosyRemove(self):
969 self.doNewIssue()
971 self._handle_mail('''Content-Type: text/plain;
972 charset="iso-8859-1"
973 From: richard <richard@test.test>
974 To: issue_tracker@your.tracker.email.domain.example
975 Message-Id: <followup_dummy_id>
976 In-Reply-To: <dummy_test_message_id>
977 Subject: [issue1] Testing... [nosy=-richard]
979 ''')
980 l = self.db.issue.get('1', 'nosy')
981 l.sort()
982 self.assertEqual(l, [self.chef_id])
984 # NO NOSY MESSAGE SHOULD BE SENT!
985 assert not os.path.exists(SENDMAILDEBUG)
987 def testNewUserAuthor(self):
988 # first without the permission
989 # heh... just ignore the API for a second ;)
990 self.db.security.role['anonymous'].permissions=[]
991 anonid = self.db.user.lookup('anonymous')
992 self.db.user.set(anonid, roles='Anonymous')
994 l = self.db.user.list()
995 l.sort()
996 message = '''Content-Type: text/plain;
997 charset="iso-8859-1"
998 From: fubar <fubar@bork.bork.bork>
999 To: issue_tracker@your.tracker.email.domain.example
1000 Message-Id: <dummy_test_message_id>
1001 Subject: [issue] Testing...
1003 This is a test submission of a new issue.
1004 '''
1005 try:
1006 self._handle_mail(message)
1007 except Unauthorized, value:
1008 body_diff = self.compareMessages(str(value), """
1009 You are not a registered user.
1011 Unknown address: fubar@bork.bork.bork
1012 """)
1014 assert not body_diff, body_diff
1016 else:
1017 raise AssertionError, "Unathorized not raised when handling mail"
1019 # Add Web Access role to anonymous, and try again to make sure
1020 # we get a "please register at:" message this time.
1021 p = [
1022 self.db.security.getPermission('Create', 'user'),
1023 self.db.security.getPermission('Web Access', None),
1024 ]
1026 self.db.security.role['anonymous'].permissions=p
1028 try:
1029 self._handle_mail(message)
1030 except Unauthorized, value:
1031 body_diff = self.compareMessages(str(value), """
1032 You are not a registered user. Please register at:
1034 http://tracker.example/cgi-bin/roundup.cgi/bugs/user?template=register
1036 ...before sending mail to the tracker.
1038 Unknown address: fubar@bork.bork.bork
1039 """)
1041 assert not body_diff, body_diff
1043 else:
1044 raise AssertionError, "Unathorized not raised when handling mail"
1046 # Make sure list of users is the same as before.
1047 m = self.db.user.list()
1048 m.sort()
1049 self.assertEqual(l, m)
1051 # now with the permission
1052 p = [
1053 self.db.security.getPermission('Create', 'user'),
1054 self.db.security.getPermission('Email Access', None),
1055 ]
1056 self.db.security.role['anonymous'].permissions=p
1057 self._handle_mail(message)
1058 m = self.db.user.list()
1059 m.sort()
1060 self.assertNotEqual(l, m)
1062 def testEnc01(self):
1063 self.doNewIssue()
1064 self._handle_mail('''Content-Type: text/plain;
1065 charset="iso-8859-1"
1066 From: mary <mary@test.test>
1067 To: issue_tracker@your.tracker.email.domain.example
1068 Message-Id: <followup_dummy_id>
1069 In-Reply-To: <dummy_test_message_id>
1070 Subject: [issue1] Testing...
1071 Content-Type: text/plain;
1072 charset="iso-8859-1"
1073 Content-Transfer-Encoding: quoted-printable
1075 A message with encoding (encoded oe =F6)
1077 ''')
1078 self.compareMessages(self._get_mail(),
1079 '''FROM: roundup-admin@your.tracker.email.domain.example
1080 TO: chef@bork.bork.bork, richard@test.test
1081 Content-Type: text/plain; charset=utf-8
1082 Subject: [issue1] Testing...
1083 To: chef@bork.bork.bork, richard@test.test
1084 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
1085 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1086 MIME-Version: 1.0
1087 Message-Id: <followup_dummy_id>
1088 In-Reply-To: <dummy_test_message_id>
1089 X-Roundup-Name: Roundup issue tracker
1090 X-Roundup-Loop: hello
1091 X-Roundup-Issue-Status: chatting
1092 Content-Transfer-Encoding: quoted-printable
1095 Contrary, Mary <mary@test.test> added the comment:
1097 A message with encoding (encoded oe =C3=B6)
1099 ----------
1100 status: unread -> chatting
1102 _______________________________________________________________________
1103 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1104 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1105 _______________________________________________________________________
1106 ''')
1109 def testMultipartEnc01(self):
1110 self.doNewIssue()
1111 self._handle_mail('''Content-Type: text/plain;
1112 charset="iso-8859-1"
1113 From: mary <mary@test.test>
1114 To: issue_tracker@your.tracker.email.domain.example
1115 Message-Id: <followup_dummy_id>
1116 In-Reply-To: <dummy_test_message_id>
1117 Subject: [issue1] Testing...
1118 Content-Type: multipart/mixed;
1119 boundary="----_=_NextPart_000_01"
1121 This message is in MIME format. Since your mail reader does not understand
1122 this format, some or all of this message may not be legible.
1124 ------_=_NextPart_000_01
1125 Content-Type: text/plain;
1126 charset="iso-8859-1"
1127 Content-Transfer-Encoding: quoted-printable
1129 A message with first part encoded (encoded oe =F6)
1131 ''')
1132 self.compareMessages(self._get_mail(),
1133 '''FROM: roundup-admin@your.tracker.email.domain.example
1134 TO: chef@bork.bork.bork, richard@test.test
1135 Content-Type: text/plain; charset=utf-8
1136 Subject: [issue1] Testing...
1137 To: chef@bork.bork.bork, richard@test.test
1138 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
1139 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1140 MIME-Version: 1.0
1141 Message-Id: <followup_dummy_id>
1142 In-Reply-To: <dummy_test_message_id>
1143 X-Roundup-Name: Roundup issue tracker
1144 X-Roundup-Loop: hello
1145 X-Roundup-Issue-Status: chatting
1146 Content-Transfer-Encoding: quoted-printable
1149 Contrary, Mary <mary@test.test> added the comment:
1151 A message with first part encoded (encoded oe =C3=B6)
1153 ----------
1154 status: unread -> chatting
1156 _______________________________________________________________________
1157 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1158 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1159 _______________________________________________________________________
1160 ''')
1162 def testContentDisposition(self):
1163 self.doNewIssue()
1164 self._handle_mail('''Content-Type: text/plain;
1165 charset="iso-8859-1"
1166 From: mary <mary@test.test>
1167 To: issue_tracker@your.tracker.email.domain.example
1168 Message-Id: <followup_dummy_id>
1169 In-Reply-To: <dummy_test_message_id>
1170 Subject: [issue1] Testing...
1171 Content-Type: multipart/mixed; boundary="bCsyhTFzCvuiizWE"
1172 Content-Disposition: inline
1175 --bCsyhTFzCvuiizWE
1176 Content-Type: text/plain; charset=us-ascii
1177 Content-Disposition: inline
1179 test attachment binary
1181 --bCsyhTFzCvuiizWE
1182 Content-Type: application/octet-stream
1183 Content-Disposition: attachment; filename="main.dvi"
1184 Content-Transfer-Encoding: base64
1186 SnVzdCBhIHRlc3QgAQo=
1188 --bCsyhTFzCvuiizWE--
1189 ''')
1190 messages = self.db.issue.get('1', 'messages')
1191 messages.sort()
1192 file = self.db.file.getnode (self.db.msg.get(messages[-1], 'files')[0])
1193 self.assertEqual(file.name, 'main.dvi')
1194 self.assertEqual(file.content, 'Just a test \001\n')
1196 def testFollowupStupidQuoting(self):
1197 self.doNewIssue()
1199 self._handle_mail('''Content-Type: text/plain;
1200 charset="iso-8859-1"
1201 From: richard <richard@test.test>
1202 To: issue_tracker@your.tracker.email.domain.example
1203 Message-Id: <followup_dummy_id>
1204 In-Reply-To: <dummy_test_message_id>
1205 Subject: Re: "[issue1] Testing... "
1207 This is a followup
1208 ''')
1209 self.compareMessages(self._get_mail(),
1210 '''FROM: roundup-admin@your.tracker.email.domain.example
1211 TO: chef@bork.bork.bork
1212 Content-Type: text/plain; charset=utf-8
1213 Subject: [issue1] Testing...
1214 To: chef@bork.bork.bork
1215 From: richard <issue_tracker@your.tracker.email.domain.example>
1216 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1217 MIME-Version: 1.0
1218 Message-Id: <followup_dummy_id>
1219 In-Reply-To: <dummy_test_message_id>
1220 X-Roundup-Name: Roundup issue tracker
1221 X-Roundup-Loop: hello
1222 X-Roundup-Issue-Status: chatting
1223 Content-Transfer-Encoding: quoted-printable
1226 richard <richard@test.test> added the comment:
1228 This is a followup
1230 ----------
1231 status: unread -> chatting
1233 _______________________________________________________________________
1234 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1235 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1236 _______________________________________________________________________
1237 ''')
1239 def testEmailQuoting(self):
1240 self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
1241 self.innerTestQuoting('''This is a followup
1242 ''')
1244 def testEmailQuotingRemove(self):
1245 self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
1246 self.innerTestQuoting('''Blah blah wrote:
1247 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
1248 > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
1249 >
1251 This is a followup
1252 ''')
1254 def innerTestQuoting(self, expect):
1255 nodeid = self.doNewIssue()
1257 messages = self.db.issue.get(nodeid, 'messages')
1259 self._handle_mail('''Content-Type: text/plain;
1260 charset="iso-8859-1"
1261 From: richard <richard@test.test>
1262 To: issue_tracker@your.tracker.email.domain.example
1263 Message-Id: <followup_dummy_id>
1264 In-Reply-To: <dummy_test_message_id>
1265 Subject: Re: [issue1] Testing...
1267 Blah blah wrote:
1268 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
1269 > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
1270 >
1272 This is a followup
1273 ''')
1274 # figure the new message id
1275 newmessages = self.db.issue.get(nodeid, 'messages')
1276 for msg in messages:
1277 newmessages.remove(msg)
1278 messageid = newmessages[0]
1280 self.compareMessages(self.db.msg.get(messageid, 'content'), expect)
1282 def testUserLookup(self):
1283 i = self.db.user.create(username='user1', address='user1@foo.com')
1284 self.assertEqual(uidFromAddress(self.db, ('', 'user1@foo.com'), 0), i)
1285 self.assertEqual(uidFromAddress(self.db, ('', 'USER1@foo.com'), 0), i)
1286 i = self.db.user.create(username='user2', address='USER2@foo.com')
1287 self.assertEqual(uidFromAddress(self.db, ('', 'USER2@foo.com'), 0), i)
1288 self.assertEqual(uidFromAddress(self.db, ('', 'user2@foo.com'), 0), i)
1290 def testUserAlternateLookup(self):
1291 i = self.db.user.create(username='user1', address='user1@foo.com',
1292 alternate_addresses='user1@bar.com')
1293 self.assertEqual(uidFromAddress(self.db, ('', 'user1@bar.com'), 0), i)
1294 self.assertEqual(uidFromAddress(self.db, ('', 'USER1@bar.com'), 0), i)
1296 def testUserCreate(self):
1297 i = uidFromAddress(self.db, ('', 'user@foo.com'), 1)
1298 self.assertNotEqual(uidFromAddress(self.db, ('', 'user@bar.com'), 1), i)
1300 def testRFC2822(self):
1301 ascii_header = "[issue243] This is a \"test\" - with 'quotation' marks"
1302 unicode_header = '[issue244] \xd0\xb0\xd0\xbd\xd0\xb4\xd1\x80\xd0\xb5\xd0\xb9'
1303 unicode_encoded = '=?utf-8?q?[issue244]_=D0=B0=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?='
1304 self.assertEqual(rfc2822.encode_header(ascii_header), ascii_header)
1305 self.assertEqual(rfc2822.encode_header(unicode_header), unicode_encoded)
1307 def testRegistrationConfirmation(self):
1308 otk = "Aj4euk4LZSAdwePohj90SME5SpopLETL"
1309 self.db.getOTKManager().set(otk, username='johannes')
1310 self._handle_mail('''Content-Type: text/plain;
1311 charset="iso-8859-1"
1312 From: Chef <chef@bork.bork.bork>
1313 To: issue_tracker@your.tracker.email.domain.example
1314 Cc: richard@test.test
1315 Message-Id: <dummy_test_message_id>
1316 Subject: Re: Complete your registration to Roundup issue tracker
1317 -- key %s
1319 This is a test confirmation of registration.
1320 ''' % otk)
1321 self.db.user.lookup('johannes')
1323 def testFollowupOnNonIssue(self):
1324 self.db.keyword.create(name='Foo')
1325 self._handle_mail('''Content-Type: text/plain;
1326 charset="iso-8859-1"
1327 From: richard <richard@test.test>
1328 To: issue_tracker@your.tracker.email.domain.example
1329 Message-Id: <followup_dummy_id>
1330 In-Reply-To: <dummy_test_message_id>
1331 Subject: [keyword1] Testing... [name=Bar]
1333 ''')
1334 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1336 def testResentFrom(self):
1337 nodeid = self._handle_mail('''Content-Type: text/plain;
1338 charset="iso-8859-1"
1339 From: Chef <chef@bork.bork.bork>
1340 Resent-From: mary <mary@test.test>
1341 To: issue_tracker@your.tracker.email.domain.example
1342 Cc: richard@test.test
1343 Message-Id: <dummy_test_message_id>
1344 Subject: [issue] Testing...
1346 This is a test submission of a new issue.
1347 ''')
1348 assert not os.path.exists(SENDMAILDEBUG)
1349 l = self.db.issue.get(nodeid, 'nosy')
1350 l.sort()
1351 self.assertEqual(l, [self.richard_id, self.mary_id])
1352 return nodeid
1354 def testDejaVu(self):
1355 self.assertRaises(IgnoreLoop, self._handle_mail,
1356 '''Content-Type: text/plain;
1357 charset="iso-8859-1"
1358 From: Chef <chef@bork.bork.bork>
1359 X-Roundup-Loop: hello
1360 To: issue_tracker@your.tracker.email.domain.example
1361 Cc: richard@test.test
1362 Message-Id: <dummy_test_message_id>
1363 Subject: Re: [issue] Testing...
1365 Hi, I've been mis-configured to loop messages back to myself.
1366 ''')
1368 def testItsBulkStupid(self):
1369 self.assertRaises(IgnoreBulk, self._handle_mail,
1370 '''Content-Type: text/plain;
1371 charset="iso-8859-1"
1372 From: Chef <chef@bork.bork.bork>
1373 Precedence: bulk
1374 To: issue_tracker@your.tracker.email.domain.example
1375 Cc: richard@test.test
1376 Message-Id: <dummy_test_message_id>
1377 Subject: Re: [issue] Testing...
1379 Hi, I'm on holidays, and this is a dumb auto-responder.
1380 ''')
1382 def testAutoReplyEmailsAreIgnored(self):
1383 self.assertRaises(IgnoreBulk, self._handle_mail,
1384 '''Content-Type: text/plain;
1385 charset="iso-8859-1"
1386 From: Chef <chef@bork.bork.bork>
1387 To: issue_tracker@your.tracker.email.domain.example
1388 Cc: richard@test.test
1389 Message-Id: <dummy_test_message_id>
1390 Subject: Re: [issue] Out of office AutoReply: Back next week
1392 Hi, I am back in the office next week
1393 ''')
1395 def testNoSubject(self):
1396 self.assertRaises(MailUsageError, self._handle_mail,
1397 '''Content-Type: text/plain;
1398 charset="iso-8859-1"
1399 From: Chef <chef@bork.bork.bork>
1400 To: issue_tracker@your.tracker.email.domain.example
1401 Cc: richard@test.test
1402 Reply-To: chef@bork.bork.bork
1403 Message-Id: <dummy_test_message_id>
1405 ''')
1407 #
1408 # TEST FOR INVALID DESIGNATOR HANDLING
1409 #
1410 def testInvalidDesignator(self):
1411 self.assertRaises(MailUsageError, self._handle_mail,
1412 '''Content-Type: text/plain;
1413 charset="iso-8859-1"
1414 From: Chef <chef@bork.bork.bork>
1415 To: issue_tracker@your.tracker.email.domain.example
1416 Subject: [frobulated] testing
1417 Cc: richard@test.test
1418 Reply-To: chef@bork.bork.bork
1419 Message-Id: <dummy_test_message_id>
1421 ''')
1422 self.assertRaises(MailUsageError, self._handle_mail,
1423 '''Content-Type: text/plain;
1424 charset="iso-8859-1"
1425 From: Chef <chef@bork.bork.bork>
1426 To: issue_tracker@your.tracker.email.domain.example
1427 Subject: [issue12345] testing
1428 Cc: richard@test.test
1429 Reply-To: chef@bork.bork.bork
1430 Message-Id: <dummy_test_message_id>
1432 ''')
1434 def testInvalidClassLoose(self):
1435 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1436 nodeid = self._handle_mail('''Content-Type: text/plain;
1437 charset="iso-8859-1"
1438 From: Chef <chef@bork.bork.bork>
1439 To: issue_tracker@your.tracker.email.domain.example
1440 Subject: [frobulated] testing
1441 Cc: richard@test.test
1442 Reply-To: chef@bork.bork.bork
1443 Message-Id: <dummy_test_message_id>
1445 ''')
1446 assert not os.path.exists(SENDMAILDEBUG)
1447 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1448 '[frobulated] testing')
1450 def testInvalidClassLooseReply(self):
1451 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1452 nodeid = self._handle_mail('''Content-Type: text/plain;
1453 charset="iso-8859-1"
1454 From: Chef <chef@bork.bork.bork>
1455 To: issue_tracker@your.tracker.email.domain.example
1456 Subject: Re: [frobulated] testing
1457 Cc: richard@test.test
1458 Reply-To: chef@bork.bork.bork
1459 Message-Id: <dummy_test_message_id>
1461 ''')
1462 assert not os.path.exists(SENDMAILDEBUG)
1463 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1464 '[frobulated] testing')
1466 def testInvalidClassLoose(self):
1467 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1468 nodeid = self._handle_mail('''Content-Type: text/plain;
1469 charset="iso-8859-1"
1470 From: Chef <chef@bork.bork.bork>
1471 To: issue_tracker@your.tracker.email.domain.example
1472 Subject: [issue1234] testing
1473 Cc: richard@test.test
1474 Reply-To: chef@bork.bork.bork
1475 Message-Id: <dummy_test_message_id>
1477 ''')
1478 assert not os.path.exists(SENDMAILDEBUG)
1479 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1480 '[issue1234] testing')
1482 def testClassLooseOK(self):
1483 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1484 self.db.keyword.create(name='Foo')
1485 nodeid = self._handle_mail('''Content-Type: text/plain;
1486 charset="iso-8859-1"
1487 From: Chef <chef@bork.bork.bork>
1488 To: issue_tracker@your.tracker.email.domain.example
1489 Subject: [keyword1] Testing... [name=Bar]
1490 Cc: richard@test.test
1491 Reply-To: chef@bork.bork.bork
1492 Message-Id: <dummy_test_message_id>
1494 ''')
1495 assert not os.path.exists(SENDMAILDEBUG)
1496 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1498 def testClassStrictInvalid(self):
1499 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'strict'
1500 self.instance.config.MAILGW_DEFAULT_CLASS = ''
1502 message = '''Content-Type: text/plain;
1503 charset="iso-8859-1"
1504 From: Chef <chef@bork.bork.bork>
1505 To: issue_tracker@your.tracker.email.domain.example
1506 Subject: Testing...
1507 Cc: richard@test.test
1508 Reply-To: chef@bork.bork.bork
1509 Message-Id: <dummy_test_message_id>
1511 '''
1512 self.assertRaises(MailUsageError, self._handle_mail, message)
1514 def testClassStrictValid(self):
1515 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'strict'
1516 self.instance.config.MAILGW_DEFAULT_CLASS = ''
1518 nodeid = self._handle_mail('''Content-Type: text/plain;
1519 charset="iso-8859-1"
1520 From: Chef <chef@bork.bork.bork>
1521 To: issue_tracker@your.tracker.email.domain.example
1522 Subject: [issue] Testing...
1523 Cc: richard@test.test
1524 Reply-To: chef@bork.bork.bork
1525 Message-Id: <dummy_test_message_id>
1527 ''')
1529 assert not os.path.exists(SENDMAILDEBUG)
1530 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
1532 #
1533 # TEST FOR INVALID COMMANDS HANDLING
1534 #
1535 def testInvalidCommands(self):
1536 self.assertRaises(MailUsageError, self._handle_mail,
1537 '''Content-Type: text/plain;
1538 charset="iso-8859-1"
1539 From: Chef <chef@bork.bork.bork>
1540 To: issue_tracker@your.tracker.email.domain.example
1541 Subject: testing [frobulated]
1542 Cc: richard@test.test
1543 Reply-To: chef@bork.bork.bork
1544 Message-Id: <dummy_test_message_id>
1546 ''')
1548 def testInvalidCommandPassthrough(self):
1549 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'none'
1550 nodeid = self._handle_mail('''Content-Type: text/plain;
1551 charset="iso-8859-1"
1552 From: Chef <chef@bork.bork.bork>
1553 To: issue_tracker@your.tracker.email.domain.example
1554 Subject: testing [frobulated]
1555 Cc: richard@test.test
1556 Reply-To: chef@bork.bork.bork
1557 Message-Id: <dummy_test_message_id>
1559 ''')
1560 assert not os.path.exists(SENDMAILDEBUG)
1561 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1562 'testing [frobulated]')
1564 def testInvalidCommandPassthroughLoose(self):
1565 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'loose'
1566 nodeid = self._handle_mail('''Content-Type: text/plain;
1567 charset="iso-8859-1"
1568 From: Chef <chef@bork.bork.bork>
1569 To: issue_tracker@your.tracker.email.domain.example
1570 Subject: testing [frobulated]
1571 Cc: richard@test.test
1572 Reply-To: chef@bork.bork.bork
1573 Message-Id: <dummy_test_message_id>
1575 ''')
1576 assert not os.path.exists(SENDMAILDEBUG)
1577 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1578 'testing [frobulated]')
1580 def testInvalidCommandPassthroughLooseOK(self):
1581 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'loose'
1582 nodeid = self._handle_mail('''Content-Type: text/plain;
1583 charset="iso-8859-1"
1584 From: Chef <chef@bork.bork.bork>
1585 To: issue_tracker@your.tracker.email.domain.example
1586 Subject: testing [assignedto=mary]
1587 Cc: richard@test.test
1588 Reply-To: chef@bork.bork.bork
1589 Message-Id: <dummy_test_message_id>
1591 ''')
1592 assert not os.path.exists(SENDMAILDEBUG)
1593 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing')
1594 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), self.mary_id)
1596 def testCommandDelimiters(self):
1597 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
1598 nodeid = self._handle_mail('''Content-Type: text/plain;
1599 charset="iso-8859-1"
1600 From: Chef <chef@bork.bork.bork>
1601 To: issue_tracker@your.tracker.email.domain.example
1602 Subject: testing {assignedto=mary}
1603 Cc: richard@test.test
1604 Reply-To: chef@bork.bork.bork
1605 Message-Id: <dummy_test_message_id>
1607 ''')
1608 assert not os.path.exists(SENDMAILDEBUG)
1609 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing')
1610 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), self.mary_id)
1612 def testPrefixDelimiters(self):
1613 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
1614 self.db.keyword.create(name='Foo')
1615 self._handle_mail('''Content-Type: text/plain;
1616 charset="iso-8859-1"
1617 From: richard <richard@test.test>
1618 To: issue_tracker@your.tracker.email.domain.example
1619 Message-Id: <followup_dummy_id>
1620 In-Reply-To: <dummy_test_message_id>
1621 Subject: {keyword1} Testing... {name=Bar}
1623 ''')
1624 assert not os.path.exists(SENDMAILDEBUG)
1625 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1627 def testCommandDelimitersIgnore(self):
1628 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
1629 nodeid = self._handle_mail('''Content-Type: text/plain;
1630 charset="iso-8859-1"
1631 From: Chef <chef@bork.bork.bork>
1632 To: issue_tracker@your.tracker.email.domain.example
1633 Subject: testing [assignedto=mary]
1634 Cc: richard@test.test
1635 Reply-To: chef@bork.bork.bork
1636 Message-Id: <dummy_test_message_id>
1638 ''')
1639 assert not os.path.exists(SENDMAILDEBUG)
1640 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1641 'testing [assignedto=mary]')
1642 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), None)
1644 def testReplytoMatch(self):
1645 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1646 nodeid = self.doNewIssue()
1647 nodeid2 = self._handle_mail('''Content-Type: text/plain;
1648 charset="iso-8859-1"
1649 From: Chef <chef@bork.bork.bork>
1650 To: issue_tracker@your.tracker.email.domain.example
1651 Message-Id: <dummy_test_message_id2>
1652 In-Reply-To: <dummy_test_message_id>
1653 Subject: Testing...
1655 Followup message.
1656 ''')
1658 nodeid3 = self._handle_mail('''Content-Type: text/plain;
1659 charset="iso-8859-1"
1660 From: Chef <chef@bork.bork.bork>
1661 To: issue_tracker@your.tracker.email.domain.example
1662 Message-Id: <dummy_test_message_id3>
1663 In-Reply-To: <dummy_test_message_id2>
1664 Subject: Testing...
1666 Yet another message in the same thread/issue.
1667 ''')
1669 self.assertEqual(nodeid, nodeid2)
1670 self.assertEqual(nodeid, nodeid3)
1672 def testHelpSubject(self):
1673 message = '''Content-Type: text/plain;
1674 charset="iso-8859-1"
1675 From: Chef <chef@bork.bork.bork>
1676 To: issue_tracker@your.tracker.email.domain.example
1677 Message-Id: <dummy_test_message_id2>
1678 In-Reply-To: <dummy_test_message_id>
1679 Subject: hElp
1682 '''
1683 self.assertRaises(MailUsageHelp, self._handle_mail, message)
1685 def testMaillistSubject(self):
1686 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '[]'
1687 self.db.keyword.create(name='Foo')
1688 self._handle_mail('''Content-Type: text/plain;
1689 charset="iso-8859-1"
1690 From: Chef <chef@bork.bork.bork>
1691 To: issue_tracker@your.tracker.email.domain.example
1692 Subject: [mailinglist-name] [keyword1] Testing.. [name=Bar]
1693 Cc: richard@test.test
1694 Reply-To: chef@bork.bork.bork
1695 Message-Id: <dummy_test_message_id>
1697 ''')
1699 assert not os.path.exists(SENDMAILDEBUG)
1700 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1702 def testUnknownPrefixSubject(self):
1703 self.db.keyword.create(name='Foo')
1704 self._handle_mail('''Content-Type: text/plain;
1705 charset="iso-8859-1"
1706 From: Chef <chef@bork.bork.bork>
1707 To: issue_tracker@your.tracker.email.domain.example
1708 Subject: VeryStrangeRe: [keyword1] Testing.. [name=Bar]
1709 Cc: richard@test.test
1710 Reply-To: chef@bork.bork.bork
1711 Message-Id: <dummy_test_message_id>
1713 ''')
1715 assert not os.path.exists(SENDMAILDEBUG)
1716 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1718 def testIssueidLast(self):
1719 nodeid1 = self.doNewIssue()
1720 nodeid2 = self._handle_mail('''Content-Type: text/plain;
1721 charset="iso-8859-1"
1722 From: mary <mary@test.test>
1723 To: issue_tracker@your.tracker.email.domain.example
1724 Message-Id: <followup_dummy_id>
1725 In-Reply-To: <dummy_test_message_id>
1726 Subject: New title [issue1]
1728 This is a second followup
1729 ''')
1731 assert nodeid1 == nodeid2
1732 self.assertEqual(self.db.issue.get(nodeid2, 'title'), "Testing...")
1735 def test_suite():
1736 suite = unittest.TestSuite()
1737 suite.addTest(unittest.makeSuite(MailgwTestCase))
1738 return suite
1740 if __name__ == '__main__':
1741 runner = unittest.TextTestRunner()
1742 unittest.main(testRunner=runner)
1744 # vim: set filetype=python sts=4 sw=4 et si :