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.startswith('from '):
54 # skip the unix from line
55 continue
56 if key.lower() == 'x-roundup-version':
57 # version changes constantly, so handle it specially
58 if new[key] != __version__:
59 res.append(' %s: %r != %r' % (key, __version__,
60 new[key]))
61 elif new.get(key, '') != old.get(key, ''):
62 res.append(' %s: %r != %r' % (key, old.get(key, ''),
63 new.get(key, '')))
65 body_diff = self.compareStrings(new.fp.read(), old.fp.read())
66 if body_diff:
67 res.append('')
68 res.extend(body_diff)
70 if res:
71 res.insert(0, 'Generated message not correct (diff follows):')
72 raise AssertionError, '\n'.join(res)
74 def compareStrings(self, s2, s1):
75 '''Note the reversal of s2 and s1 - difflib.SequenceMatcher wants
76 the first to be the "original" but in the calls in this file,
77 the second arg is the original. Ho hum.
78 '''
79 l1 = s1.strip().split('\n')
80 l2 = s2.strip().split('\n')
81 if l1 == l2:
82 return
83 s = difflib.SequenceMatcher(None, l1, l2)
84 res = []
85 for value, s1s, s1e, s2s, s2e in s.get_opcodes():
86 if value == 'equal':
87 for i in range(s1s, s1e):
88 res.append(' %s'%l1[i])
89 elif value == 'delete':
90 for i in range(s1s, s1e):
91 res.append('- %s'%l1[i])
92 elif value == 'insert':
93 for i in range(s2s, s2e):
94 res.append('+ %s'%l2[i])
95 elif value == 'replace':
96 for i, j in zip(range(s1s, s1e), range(s2s, s2e)):
97 res.append('- %s'%l1[i])
98 res.append('+ %s'%l2[j])
100 return res
102 class MailgwTestCase(unittest.TestCase, DiffHelper):
103 count = 0
104 schema = 'classic'
105 def setUp(self):
106 MailgwTestCase.count = MailgwTestCase.count + 1
107 self.dirname = '_test_mailgw_%s'%self.count
108 # set up and open a tracker
109 self.instance = db_test_base.setupTracker(self.dirname)
111 # and open the database
112 self.db = self.instance.open('admin')
113 self.chef_id = self.db.user.create(username='Chef',
114 address='chef@bork.bork.bork', realname='Bork, Chef', roles='User')
115 self.richard_id = self.db.user.create(username='richard',
116 address='richard@test.test', roles='User')
117 self.mary_id = self.db.user.create(username='mary', address='mary@test.test',
118 roles='User', realname='Contrary, Mary')
119 self.john_id = self.db.user.create(username='john', address='john@test.test',
120 alternate_addresses='jondoe@test.test\njohn.doe@test.test', roles='User',
121 realname='John Doe')
123 def tearDown(self):
124 if os.path.exists(SENDMAILDEBUG):
125 os.remove(SENDMAILDEBUG)
126 self.db.close()
127 try:
128 shutil.rmtree(self.dirname)
129 except OSError, error:
130 if error.errno not in (errno.ENOENT, errno.ESRCH): raise
132 def _handle_mail(self, message):
133 handler = self.instance.MailGW(self.instance, self.db)
134 handler.trapExceptions = 0
135 ret = handler.main(StringIO(message))
136 # handler can close the db on us and open a new one
137 self.db = handler.db
138 return ret
140 def _get_mail(self):
141 f = open(SENDMAILDEBUG)
142 try:
143 return f.read()
144 finally:
145 f.close()
147 def testEmptyMessage(self):
148 nodeid = self._handle_mail('''Content-Type: text/plain;
149 charset="iso-8859-1"
150 From: Chef <chef@bork.bork.bork>
151 To: issue_tracker@your.tracker.email.domain.example
152 Cc: richard@test.test
153 Reply-To: chef@bork.bork.bork
154 Message-Id: <dummy_test_message_id>
155 Subject: [issue] Testing...
157 ''')
158 assert not os.path.exists(SENDMAILDEBUG)
159 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
161 def doNewIssue(self):
162 nodeid = self._handle_mail('''Content-Type: text/plain;
163 charset="iso-8859-1"
164 From: Chef <chef@bork.bork.bork>
165 To: issue_tracker@your.tracker.email.domain.example
166 Cc: richard@test.test
167 Message-Id: <dummy_test_message_id>
168 Subject: [issue] Testing...
170 This is a test submission of a new issue.
171 ''')
172 assert not os.path.exists(SENDMAILDEBUG)
173 l = self.db.issue.get(nodeid, 'nosy')
174 l.sort()
175 self.assertEqual(l, [self.chef_id, self.richard_id])
176 return nodeid
178 def testNewIssue(self):
179 self.doNewIssue()
181 def testNewIssueNosy(self):
182 self.instance.config.ADD_AUTHOR_TO_NOSY = 'yes'
183 nodeid = self._handle_mail('''Content-Type: text/plain;
184 charset="iso-8859-1"
185 From: Chef <chef@bork.bork.bork>
186 To: issue_tracker@your.tracker.email.domain.example
187 Cc: richard@test.test
188 Message-Id: <dummy_test_message_id>
189 Subject: [issue] Testing...
191 This is a test submission of a new issue.
192 ''')
193 assert not os.path.exists(SENDMAILDEBUG)
194 l = self.db.issue.get(nodeid, 'nosy')
195 l.sort()
196 self.assertEqual(l, [self.chef_id, self.richard_id])
198 def testAlternateAddress(self):
199 self._handle_mail('''Content-Type: text/plain;
200 charset="iso-8859-1"
201 From: John Doe <john.doe@test.test>
202 To: issue_tracker@your.tracker.email.domain.example
203 Message-Id: <dummy_test_message_id>
204 Subject: [issue] Testing...
206 This is a test submission of a new issue.
207 ''')
208 userlist = self.db.user.list()
209 assert not os.path.exists(SENDMAILDEBUG)
210 self.assertEqual(userlist, self.db.user.list(),
211 "user created when it shouldn't have been")
213 def testNewIssueNoClass(self):
214 self._handle_mail('''Content-Type: text/plain;
215 charset="iso-8859-1"
216 From: Chef <chef@bork.bork.bork>
217 To: issue_tracker@your.tracker.email.domain.example
218 Cc: richard@test.test
219 Message-Id: <dummy_test_message_id>
220 Subject: Testing...
222 This is a test submission of a new issue.
223 ''')
224 assert not os.path.exists(SENDMAILDEBUG)
226 def testNewIssueAuthMsg(self):
227 # TODO: fix the damn config - this is apalling
228 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
229 self._handle_mail('''Content-Type: text/plain;
230 charset="iso-8859-1"
231 From: Chef <chef@bork.bork.bork>
232 To: issue_tracker@your.tracker.email.domain.example
233 Message-Id: <dummy_test_message_id>
234 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
236 This is a test submission of a new issue.
237 ''')
238 self.compareMessages(self._get_mail(),
239 '''FROM: roundup-admin@your.tracker.email.domain.example
240 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
241 Content-Type: text/plain; charset="utf-8"
242 Subject: [issue1] Testing...
243 To: chef@bork.bork.bork, mary@test.test, richard@test.test
244 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
245 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
246 MIME-Version: 1.0
247 Message-Id: <dummy_test_message_id>
248 X-Roundup-Name: Roundup issue tracker
249 X-Roundup-Loop: hello
250 X-Roundup-Issue-Status: unread
251 Content-Transfer-Encoding: quoted-printable
254 New submission from Bork, Chef <chef@bork.bork.bork>:
256 This is a test submission of a new issue.
258 ----------
259 assignedto: richard
260 messages: 1
261 nosy: Chef, mary, richard
262 status: unread
263 title: Testing...
265 _______________________________________________________________________
266 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
267 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
268 _______________________________________________________________________
269 ''')
271 def testNewIssueNoAuthorInfo(self):
272 self.db.config.MAIL_ADD_AUTHORINFO = 'no'
273 self._handle_mail('''Content-Type: text/plain;
274 charset="iso-8859-1"
275 From: Chef <chef@bork.bork.bork>
276 To: issue_tracker@your.tracker.email.domain.example
277 Message-Id: <dummy_test_message_id>
278 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
280 This is a test submission of a new issue.
281 ''')
282 self.compareMessages(self._get_mail(),
283 '''FROM: roundup-admin@your.tracker.email.domain.example
284 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
285 Content-Type: text/plain; charset="utf-8"
286 Subject: [issue1] Testing...
287 To: mary@test.test, richard@test.test
288 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
289 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
290 MIME-Version: 1.0
291 Message-Id: <dummy_test_message_id>
292 X-Roundup-Name: Roundup issue tracker
293 X-Roundup-Loop: hello
294 X-Roundup-Issue-Status: unread
295 Content-Transfer-Encoding: quoted-printable
297 This is a test submission of a new issue.
299 ----------
300 assignedto: richard
301 messages: 1
302 nosy: Chef, mary, richard
303 status: unread
304 title: Testing...
306 _______________________________________________________________________
307 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
308 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
309 _______________________________________________________________________
310 ''')
312 def testNewIssueNoAuthorEmail(self):
313 self.db.config.MAIL_ADD_AUTHOREMAIL = 'no'
314 self._handle_mail('''Content-Type: text/plain;
315 charset="iso-8859-1"
316 From: Chef <chef@bork.bork.bork>
317 To: issue_tracker@your.tracker.email.domain.example
318 Message-Id: <dummy_test_message_id>
319 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
321 This is a test submission of a new issue.
322 ''')
323 self.compareMessages(self._get_mail(),
324 '''FROM: roundup-admin@your.tracker.email.domain.example
325 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
326 Content-Type: text/plain; charset="utf-8"
327 Subject: [issue1] Testing...
328 To: mary@test.test, richard@test.test
329 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
330 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
331 MIME-Version: 1.0
332 Message-Id: <dummy_test_message_id>
333 X-Roundup-Name: Roundup issue tracker
334 X-Roundup-Loop: hello
335 X-Roundup-Issue-Status: unread
336 Content-Transfer-Encoding: quoted-printable
338 New submission from Bork, Chef:
340 This is a test submission of a new issue.
342 ----------
343 assignedto: richard
344 messages: 1
345 nosy: Chef, mary, richard
346 status: unread
347 title: Testing...
349 _______________________________________________________________________
350 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
351 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
352 _______________________________________________________________________
353 ''')
355 multipart_msg = '''From: mary <mary@test.test>
356 To: issue_tracker@your.tracker.email.domain.example
357 Message-Id: <followup_dummy_id>
358 In-Reply-To: <dummy_test_message_id>
359 Subject: [issue1] Testing...
360 Content-Type: multipart/mixed; boundary="bxyzzy"
361 Content-Disposition: inline
364 --bxyzzy
365 Content-Type: multipart/alternative; boundary="bCsyhTFzCvuiizWE"
366 Content-Disposition: inline
368 --bCsyhTFzCvuiizWE
369 Content-Type: text/plain; charset=us-ascii
370 Content-Disposition: inline
372 test attachment first text/plain
374 --bCsyhTFzCvuiizWE
375 Content-Type: application/octet-stream
376 Content-Disposition: attachment; filename="first.dvi"
377 Content-Transfer-Encoding: base64
379 SnVzdCBhIHRlc3QgAQo=
381 --bCsyhTFzCvuiizWE
382 Content-Type: text/plain; charset=us-ascii
383 Content-Disposition: inline
385 test attachment second text/plain
387 --bCsyhTFzCvuiizWE
388 Content-Type: text/html
389 Content-Disposition: inline
391 <html>
392 to be ignored.
393 </html>
395 --bCsyhTFzCvuiizWE--
397 --bxyzzy
398 Content-Type: multipart/alternative; boundary="bCsyhTFzCvuiizWF"
399 Content-Disposition: inline
401 --bCsyhTFzCvuiizWF
402 Content-Type: text/plain; charset=us-ascii
403 Content-Disposition: inline
405 test attachment third text/plain
407 --bCsyhTFzCvuiizWF
408 Content-Type: application/octet-stream
409 Content-Disposition: attachment; filename="second.dvi"
410 Content-Transfer-Encoding: base64
412 SnVzdCBhIHRlc3QK
414 --bCsyhTFzCvuiizWF--
416 --bxyzzy--
417 '''
419 def testMultipartKeepAlternatives(self):
420 self.doNewIssue()
421 self._handle_mail(self.multipart_msg)
422 messages = self.db.issue.get('1', 'messages')
423 messages.sort()
424 msg = self.db.msg.getnode (messages[-1])
425 assert(len(msg.files) == 5)
426 names = {0 : 'first.dvi', 4 : 'second.dvi'}
427 content = {3 : 'test attachment third text/plain\n',
428 4 : 'Just a test\n'}
429 for n, id in enumerate (msg.files):
430 f = self.db.file.getnode (id)
431 self.assertEqual(f.name, names.get (n, 'unnamed'))
432 if n in content :
433 self.assertEqual(f.content, content [n])
434 self.assertEqual(msg.content, 'test attachment second text/plain')
436 def testMultipartDropAlternatives(self):
437 self.doNewIssue()
438 self.db.config.MAILGW_IGNORE_ALTERNATIVES = True
439 self._handle_mail(self.multipart_msg)
440 messages = self.db.issue.get('1', 'messages')
441 messages.sort()
442 msg = self.db.msg.getnode (messages[-1])
443 assert(len(msg.files) == 2)
444 names = {1 : 'second.dvi'}
445 content = {0 : 'test attachment third text/plain\n',
446 1 : 'Just a test\n'}
447 for n, id in enumerate (msg.files):
448 f = self.db.file.getnode (id)
449 self.assertEqual(f.name, names.get (n, 'unnamed'))
450 if n in content :
451 self.assertEqual(f.content, content [n])
452 self.assertEqual(msg.content, 'test attachment second text/plain')
454 def testSimpleFollowup(self):
455 self.doNewIssue()
456 self._handle_mail('''Content-Type: text/plain;
457 charset="iso-8859-1"
458 From: mary <mary@test.test>
459 To: issue_tracker@your.tracker.email.domain.example
460 Message-Id: <followup_dummy_id>
461 In-Reply-To: <dummy_test_message_id>
462 Subject: [issue1] Testing...
464 This is a second followup
465 ''')
466 self.compareMessages(self._get_mail(),
467 '''FROM: roundup-admin@your.tracker.email.domain.example
468 TO: chef@bork.bork.bork, richard@test.test
469 Content-Type: text/plain; charset="utf-8"
470 Subject: [issue1] Testing...
471 To: chef@bork.bork.bork, richard@test.test
472 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
473 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
474 MIME-Version: 1.0
475 Message-Id: <followup_dummy_id>
476 In-Reply-To: <dummy_test_message_id>
477 X-Roundup-Name: Roundup issue tracker
478 X-Roundup-Loop: hello
479 X-Roundup-Issue-Status: chatting
480 Content-Transfer-Encoding: quoted-printable
483 Contrary, Mary <mary@test.test> added the comment:
485 This is a second followup
487 ----------
488 status: unread -> chatting
490 _______________________________________________________________________
491 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
492 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
493 _______________________________________________________________________
494 ''')
496 def testFollowup(self):
497 self.doNewIssue()
499 self._handle_mail('''Content-Type: text/plain;
500 charset="iso-8859-1"
501 From: richard <richard@test.test>
502 To: issue_tracker@your.tracker.email.domain.example
503 Message-Id: <followup_dummy_id>
504 In-Reply-To: <dummy_test_message_id>
505 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
507 This is a followup
508 ''')
509 l = self.db.issue.get('1', 'nosy')
510 l.sort()
511 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
512 self.john_id])
514 self.compareMessages(self._get_mail(),
515 '''FROM: roundup-admin@your.tracker.email.domain.example
516 TO: chef@bork.bork.bork, john@test.test, mary@test.test
517 Content-Type: text/plain; charset="utf-8"
518 Subject: [issue1] Testing...
519 To: chef@bork.bork.bork, john@test.test, mary@test.test
520 From: richard <issue_tracker@your.tracker.email.domain.example>
521 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
522 MIME-Version: 1.0
523 Message-Id: <followup_dummy_id>
524 In-Reply-To: <dummy_test_message_id>
525 X-Roundup-Name: Roundup issue tracker
526 X-Roundup-Loop: hello
527 X-Roundup-Issue-Status: chatting
528 Content-Transfer-Encoding: quoted-printable
531 richard <richard@test.test> added the comment:
533 This is a followup
535 ----------
536 assignedto: -> mary
537 nosy: +john, mary
538 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 _______________________________________________________________________
544 ''')
546 def testPropertyChangeOnly(self):
547 self.doNewIssue()
548 oldvalues = self.db.getnode('issue', '1').copy()
549 oldvalues['assignedto'] = None
550 self.db.issue.set('1', assignedto=self.chef_id)
551 self.db.commit()
552 self.db.issue.nosymessage('1', None, oldvalues)
554 new_mail = ""
555 for line in self._get_mail().split("\n"):
556 if "Message-Id: " in line:
557 continue
558 if "Date: " in line:
559 continue
560 new_mail += line+"\n"
562 self.compareMessages(new_mail, """
563 FROM: roundup-admin@your.tracker.email.domain.example
564 TO: chef@bork.bork.bork, richard@test.test
565 Content-Type: text/plain; charset="utf-8"
566 Subject: [issue1] Testing...
567 To: chef@bork.bork.bork, richard@test.test
568 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
569 X-Roundup-Name: Roundup issue tracker
570 X-Roundup-Loop: hello
571 X-Roundup-Issue-Status: unread
572 X-Roundup-Version: 1.3.3
573 MIME-Version: 1.0
574 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
575 Content-Transfer-Encoding: quoted-printable
578 Change by Bork, Chef <chef@bork.bork.bork>:
581 ----------
582 assignedto: -> Chef
584 _______________________________________________________________________
585 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
586 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
587 _______________________________________________________________________
588 """)
591 #
592 # FOLLOWUP TITLE MATCH
593 #
594 def testFollowupTitleMatch(self):
595 self.doNewIssue()
596 self._handle_mail('''Content-Type: text/plain;
597 charset="iso-8859-1"
598 From: richard <richard@test.test>
599 To: issue_tracker@your.tracker.email.domain.example
600 Message-Id: <followup_dummy_id>
601 Subject: Re: Testing... [assignedto=mary; nosy=+john]
603 This is a followup
604 ''')
605 self.compareMessages(self._get_mail(),
606 '''FROM: roundup-admin@your.tracker.email.domain.example
607 TO: chef@bork.bork.bork, john@test.test, mary@test.test
608 Content-Type: text/plain; charset="utf-8"
609 Subject: [issue1] Testing...
610 To: chef@bork.bork.bork, john@test.test, mary@test.test
611 From: richard <issue_tracker@your.tracker.email.domain.example>
612 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
613 MIME-Version: 1.0
614 Message-Id: <followup_dummy_id>
615 In-Reply-To: <dummy_test_message_id>
616 X-Roundup-Name: Roundup issue tracker
617 X-Roundup-Loop: hello
618 X-Roundup-Issue-Status: chatting
619 Content-Transfer-Encoding: quoted-printable
622 richard <richard@test.test> added the comment:
624 This is a followup
626 ----------
627 assignedto: -> mary
628 nosy: +john, mary
629 status: unread -> chatting
631 _______________________________________________________________________
632 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
633 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
634 _______________________________________________________________________
635 ''')
637 def testFollowupTitleMatchMultiRe(self):
638 nodeid1 = self.doNewIssue()
639 nodeid2 = self._handle_mail('''Content-Type: text/plain;
640 charset="iso-8859-1"
641 From: richard <richard@test.test>
642 To: issue_tracker@your.tracker.email.domain.example
643 Message-Id: <followup_dummy_id>
644 Subject: Re: Testing... [assignedto=mary; nosy=+john]
646 This is a followup
647 ''')
649 nodeid3 = self._handle_mail('''Content-Type: text/plain;
650 charset="iso-8859-1"
651 From: richard <richard@test.test>
652 To: issue_tracker@your.tracker.email.domain.example
653 Message-Id: <followup2_dummy_id>
654 Subject: Ang: Re: Testing...
656 This is a followup
657 ''')
658 self.assertEqual(nodeid1, nodeid2)
659 self.assertEqual(nodeid1, nodeid3)
661 def testFollowupTitleMatchNever(self):
662 nodeid = self.doNewIssue()
663 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'never'
664 self.assertNotEqual(self._handle_mail('''Content-Type: text/plain;
665 charset="iso-8859-1"
666 From: richard <richard@test.test>
667 To: issue_tracker@your.tracker.email.domain.example
668 Message-Id: <followup_dummy_id>
669 Subject: Re: Testing...
671 This is a followup
672 '''), nodeid)
674 def testFollowupTitleMatchNeverInterval(self):
675 nodeid = self.doNewIssue()
676 # force failure of the interval
677 time.sleep(2)
678 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation 00:00:01'
679 self.assertNotEqual(self._handle_mail('''Content-Type: text/plain;
680 charset="iso-8859-1"
681 From: richard <richard@test.test>
682 To: issue_tracker@your.tracker.email.domain.example
683 Message-Id: <followup_dummy_id>
684 Subject: Re: Testing...
686 This is a followup
687 '''), nodeid)
690 def testFollowupTitleMatchInterval(self):
691 nodeid = self.doNewIssue()
692 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation +1d'
693 self.assertEqual(self._handle_mail('''Content-Type: text/plain;
694 charset="iso-8859-1"
695 From: richard <richard@test.test>
696 To: issue_tracker@your.tracker.email.domain.example
697 Message-Id: <followup_dummy_id>
698 Subject: Re: Testing...
700 This is a followup
701 '''), nodeid)
704 def testFollowupNosyAuthor(self):
705 self.doNewIssue()
706 self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
707 self._handle_mail('''Content-Type: text/plain;
708 charset="iso-8859-1"
709 From: john@test.test
710 To: issue_tracker@your.tracker.email.domain.example
711 Message-Id: <followup_dummy_id>
712 In-Reply-To: <dummy_test_message_id>
713 Subject: [issue1] Testing...
715 This is a followup
716 ''')
718 self.compareMessages(self._get_mail(),
719 '''FROM: roundup-admin@your.tracker.email.domain.example
720 TO: chef@bork.bork.bork, richard@test.test
721 Content-Type: text/plain; charset="utf-8"
722 Subject: [issue1] Testing...
723 To: chef@bork.bork.bork, richard@test.test
724 From: John Doe <issue_tracker@your.tracker.email.domain.example>
725 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
726 MIME-Version: 1.0
727 Message-Id: <followup_dummy_id>
728 In-Reply-To: <dummy_test_message_id>
729 X-Roundup-Name: Roundup issue tracker
730 X-Roundup-Loop: hello
731 X-Roundup-Issue-Status: chatting
732 Content-Transfer-Encoding: quoted-printable
735 John Doe <john@test.test> added the comment:
737 This is a followup
739 ----------
740 nosy: +john
741 status: unread -> chatting
743 _______________________________________________________________________
744 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
745 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
746 _______________________________________________________________________
748 ''')
750 def testFollowupNosyRecipients(self):
751 self.doNewIssue()
752 self.db.config.ADD_RECIPIENTS_TO_NOSY = 'yes'
753 self._handle_mail('''Content-Type: text/plain;
754 charset="iso-8859-1"
755 From: richard@test.test
756 To: issue_tracker@your.tracker.email.domain.example
757 Cc: john@test.test
758 Message-Id: <followup_dummy_id>
759 In-Reply-To: <dummy_test_message_id>
760 Subject: [issue1] Testing...
762 This is a followup
763 ''')
764 self.compareMessages(self._get_mail(),
765 '''FROM: roundup-admin@your.tracker.email.domain.example
766 TO: chef@bork.bork.bork
767 Content-Type: text/plain; charset="utf-8"
768 Subject: [issue1] Testing...
769 To: chef@bork.bork.bork
770 From: richard <issue_tracker@your.tracker.email.domain.example>
771 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
772 MIME-Version: 1.0
773 Message-Id: <followup_dummy_id>
774 In-Reply-To: <dummy_test_message_id>
775 X-Roundup-Name: Roundup issue tracker
776 X-Roundup-Loop: hello
777 X-Roundup-Issue-Status: chatting
778 Content-Transfer-Encoding: quoted-printable
781 richard <richard@test.test> added the comment:
783 This is a followup
785 ----------
786 nosy: +john
787 status: unread -> chatting
789 _______________________________________________________________________
790 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
791 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
792 _______________________________________________________________________
794 ''')
796 def testFollowupNosyAuthorAndCopy(self):
797 self.doNewIssue()
798 self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
799 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
800 self._handle_mail('''Content-Type: text/plain;
801 charset="iso-8859-1"
802 From: john@test.test
803 To: issue_tracker@your.tracker.email.domain.example
804 Message-Id: <followup_dummy_id>
805 In-Reply-To: <dummy_test_message_id>
806 Subject: [issue1] Testing...
808 This is a followup
809 ''')
810 self.compareMessages(self._get_mail(),
811 '''FROM: roundup-admin@your.tracker.email.domain.example
812 TO: chef@bork.bork.bork, john@test.test, richard@test.test
813 Content-Type: text/plain; charset="utf-8"
814 Subject: [issue1] Testing...
815 To: chef@bork.bork.bork, john@test.test, richard@test.test
816 From: John Doe <issue_tracker@your.tracker.email.domain.example>
817 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
818 MIME-Version: 1.0
819 Message-Id: <followup_dummy_id>
820 In-Reply-To: <dummy_test_message_id>
821 X-Roundup-Name: Roundup issue tracker
822 X-Roundup-Loop: hello
823 X-Roundup-Issue-Status: chatting
824 Content-Transfer-Encoding: quoted-printable
827 John Doe <john@test.test> added the comment:
829 This is a followup
831 ----------
832 nosy: +john
833 status: unread -> chatting
835 _______________________________________________________________________
836 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
837 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
838 _______________________________________________________________________
840 ''')
842 def testFollowupNoNosyAuthor(self):
843 self.doNewIssue()
844 self.instance.config.ADD_AUTHOR_TO_NOSY = 'no'
845 self._handle_mail('''Content-Type: text/plain;
846 charset="iso-8859-1"
847 From: john@test.test
848 To: issue_tracker@your.tracker.email.domain.example
849 Message-Id: <followup_dummy_id>
850 In-Reply-To: <dummy_test_message_id>
851 Subject: [issue1] Testing...
853 This is a followup
854 ''')
855 self.compareMessages(self._get_mail(),
856 '''FROM: roundup-admin@your.tracker.email.domain.example
857 TO: chef@bork.bork.bork, richard@test.test
858 Content-Type: text/plain; charset="utf-8"
859 Subject: [issue1] Testing...
860 To: chef@bork.bork.bork, richard@test.test
861 From: John Doe <issue_tracker@your.tracker.email.domain.example>
862 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
863 MIME-Version: 1.0
864 Message-Id: <followup_dummy_id>
865 In-Reply-To: <dummy_test_message_id>
866 X-Roundup-Name: Roundup issue tracker
867 X-Roundup-Loop: hello
868 X-Roundup-Issue-Status: chatting
869 Content-Transfer-Encoding: quoted-printable
872 John Doe <john@test.test> added the comment:
874 This is a followup
876 ----------
877 status: unread -> chatting
879 _______________________________________________________________________
880 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
881 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
882 _______________________________________________________________________
884 ''')
886 def testFollowupNoNosyRecipients(self):
887 self.doNewIssue()
888 self.instance.config.ADD_RECIPIENTS_TO_NOSY = 'no'
889 self._handle_mail('''Content-Type: text/plain;
890 charset="iso-8859-1"
891 From: richard@test.test
892 To: issue_tracker@your.tracker.email.domain.example
893 Cc: john@test.test
894 Message-Id: <followup_dummy_id>
895 In-Reply-To: <dummy_test_message_id>
896 Subject: [issue1] Testing...
898 This is a followup
899 ''')
900 self.compareMessages(self._get_mail(),
901 '''FROM: roundup-admin@your.tracker.email.domain.example
902 TO: chef@bork.bork.bork
903 Content-Type: text/plain; charset="utf-8"
904 Subject: [issue1] Testing...
905 To: chef@bork.bork.bork
906 From: richard <issue_tracker@your.tracker.email.domain.example>
907 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
908 MIME-Version: 1.0
909 Message-Id: <followup_dummy_id>
910 In-Reply-To: <dummy_test_message_id>
911 X-Roundup-Name: Roundup issue tracker
912 X-Roundup-Loop: hello
913 X-Roundup-Issue-Status: chatting
914 Content-Transfer-Encoding: quoted-printable
917 richard <richard@test.test> added the comment:
919 This is a followup
921 ----------
922 status: unread -> chatting
924 _______________________________________________________________________
925 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
926 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
927 _______________________________________________________________________
929 ''')
931 def testFollowupEmptyMessage(self):
932 self.doNewIssue()
934 self._handle_mail('''Content-Type: text/plain;
935 charset="iso-8859-1"
936 From: richard <richard@test.test>
937 To: issue_tracker@your.tracker.email.domain.example
938 Message-Id: <followup_dummy_id>
939 In-Reply-To: <dummy_test_message_id>
940 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
942 ''')
943 l = self.db.issue.get('1', 'nosy')
944 l.sort()
945 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
946 self.john_id])
948 # should be no file created (ie. no message)
949 assert not os.path.exists(SENDMAILDEBUG)
951 def testFollowupEmptyMessageNoSubject(self):
952 self.doNewIssue()
954 self._handle_mail('''Content-Type: text/plain;
955 charset="iso-8859-1"
956 From: richard <richard@test.test>
957 To: issue_tracker@your.tracker.email.domain.example
958 Message-Id: <followup_dummy_id>
959 In-Reply-To: <dummy_test_message_id>
960 Subject: [issue1] [assignedto=mary; nosy=+john]
962 ''')
963 l = self.db.issue.get('1', 'nosy')
964 l.sort()
965 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
966 self.john_id])
968 # should be no file created (ie. no message)
969 assert not os.path.exists(SENDMAILDEBUG)
971 def testNosyRemove(self):
972 self.doNewIssue()
974 self._handle_mail('''Content-Type: text/plain;
975 charset="iso-8859-1"
976 From: richard <richard@test.test>
977 To: issue_tracker@your.tracker.email.domain.example
978 Message-Id: <followup_dummy_id>
979 In-Reply-To: <dummy_test_message_id>
980 Subject: [issue1] Testing... [nosy=-richard]
982 ''')
983 l = self.db.issue.get('1', 'nosy')
984 l.sort()
985 self.assertEqual(l, [self.chef_id])
987 # NO NOSY MESSAGE SHOULD BE SENT!
988 assert not os.path.exists(SENDMAILDEBUG)
990 def testNewUserAuthor(self):
991 # first without the permission
992 # heh... just ignore the API for a second ;)
993 self.db.security.role['anonymous'].permissions=[]
994 anonid = self.db.user.lookup('anonymous')
995 self.db.user.set(anonid, roles='Anonymous')
997 l = self.db.user.list()
998 l.sort()
999 message = '''Content-Type: text/plain;
1000 charset="iso-8859-1"
1001 From: fubar <fubar@bork.bork.bork>
1002 To: issue_tracker@your.tracker.email.domain.example
1003 Message-Id: <dummy_test_message_id>
1004 Subject: [issue] Testing...
1006 This is a test submission of a new issue.
1007 '''
1008 try:
1009 self._handle_mail(message)
1010 except Unauthorized, value:
1011 body_diff = self.compareMessages(str(value), """
1012 You are not a registered user.
1014 Unknown address: fubar@bork.bork.bork
1015 """)
1017 assert not body_diff, body_diff
1019 else:
1020 raise AssertionError, "Unathorized not raised when handling mail"
1022 # Add Web Access role to anonymous, and try again to make sure
1023 # we get a "please register at:" message this time.
1024 p = [
1025 self.db.security.getPermission('Create', 'user'),
1026 self.db.security.getPermission('Web Access', None),
1027 ]
1029 self.db.security.role['anonymous'].permissions=p
1031 try:
1032 self._handle_mail(message)
1033 except Unauthorized, value:
1034 body_diff = self.compareMessages(str(value), """
1035 You are not a registered user. Please register at:
1037 http://tracker.example/cgi-bin/roundup.cgi/bugs/user?template=register
1039 ...before sending mail to the tracker.
1041 Unknown address: fubar@bork.bork.bork
1042 """)
1044 assert not body_diff, body_diff
1046 else:
1047 raise AssertionError, "Unathorized not raised when handling mail"
1049 # Make sure list of users is the same as before.
1050 m = self.db.user.list()
1051 m.sort()
1052 self.assertEqual(l, m)
1054 # now with the permission
1055 p = [
1056 self.db.security.getPermission('Create', 'user'),
1057 self.db.security.getPermission('Email Access', None),
1058 ]
1059 self.db.security.role['anonymous'].permissions=p
1060 self._handle_mail(message)
1061 m = self.db.user.list()
1062 m.sort()
1063 self.assertNotEqual(l, m)
1065 def testEnc01(self):
1066 self.doNewIssue()
1067 self._handle_mail('''Content-Type: text/plain;
1068 charset="iso-8859-1"
1069 From: mary <mary@test.test>
1070 To: issue_tracker@your.tracker.email.domain.example
1071 Message-Id: <followup_dummy_id>
1072 In-Reply-To: <dummy_test_message_id>
1073 Subject: [issue1] Testing...
1074 Content-Type: text/plain;
1075 charset="iso-8859-1"
1076 Content-Transfer-Encoding: quoted-printable
1078 A message with encoding (encoded oe =F6)
1080 ''')
1081 self.compareMessages(self._get_mail(),
1082 '''FROM: roundup-admin@your.tracker.email.domain.example
1083 TO: chef@bork.bork.bork, richard@test.test
1084 Content-Type: text/plain; charset="utf-8"
1085 Subject: [issue1] Testing...
1086 To: chef@bork.bork.bork, richard@test.test
1087 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
1088 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1089 MIME-Version: 1.0
1090 Message-Id: <followup_dummy_id>
1091 In-Reply-To: <dummy_test_message_id>
1092 X-Roundup-Name: Roundup issue tracker
1093 X-Roundup-Loop: hello
1094 X-Roundup-Issue-Status: chatting
1095 Content-Transfer-Encoding: quoted-printable
1098 Contrary, Mary <mary@test.test> added the comment:
1100 A message with encoding (encoded oe =C3=B6)
1102 ----------
1103 status: unread -> chatting
1105 _______________________________________________________________________
1106 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1107 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1108 _______________________________________________________________________
1109 ''')
1112 def testMultipartEnc01(self):
1113 self.doNewIssue()
1114 self._handle_mail('''Content-Type: text/plain;
1115 charset="iso-8859-1"
1116 From: mary <mary@test.test>
1117 To: issue_tracker@your.tracker.email.domain.example
1118 Message-Id: <followup_dummy_id>
1119 In-Reply-To: <dummy_test_message_id>
1120 Subject: [issue1] Testing...
1121 Content-Type: multipart/mixed;
1122 boundary="----_=_NextPart_000_01"
1124 This message is in MIME format. Since your mail reader does not understand
1125 this format, some or all of this message may not be legible.
1127 ------_=_NextPart_000_01
1128 Content-Type: text/plain;
1129 charset="iso-8859-1"
1130 Content-Transfer-Encoding: quoted-printable
1132 A message with first part encoded (encoded oe =F6)
1134 ''')
1135 self.compareMessages(self._get_mail(),
1136 '''FROM: roundup-admin@your.tracker.email.domain.example
1137 TO: chef@bork.bork.bork, richard@test.test
1138 Content-Type: text/plain; charset="utf-8"
1139 Subject: [issue1] Testing...
1140 To: chef@bork.bork.bork, richard@test.test
1141 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
1142 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1143 MIME-Version: 1.0
1144 Message-Id: <followup_dummy_id>
1145 In-Reply-To: <dummy_test_message_id>
1146 X-Roundup-Name: Roundup issue tracker
1147 X-Roundup-Loop: hello
1148 X-Roundup-Issue-Status: chatting
1149 Content-Transfer-Encoding: quoted-printable
1152 Contrary, Mary <mary@test.test> added the comment:
1154 A message with first part encoded (encoded oe =C3=B6)
1156 ----------
1157 status: unread -> chatting
1159 _______________________________________________________________________
1160 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1161 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1162 _______________________________________________________________________
1163 ''')
1165 def testContentDisposition(self):
1166 self.doNewIssue()
1167 self._handle_mail('''Content-Type: text/plain;
1168 charset="iso-8859-1"
1169 From: mary <mary@test.test>
1170 To: issue_tracker@your.tracker.email.domain.example
1171 Message-Id: <followup_dummy_id>
1172 In-Reply-To: <dummy_test_message_id>
1173 Subject: [issue1] Testing...
1174 Content-Type: multipart/mixed; boundary="bCsyhTFzCvuiizWE"
1175 Content-Disposition: inline
1178 --bCsyhTFzCvuiizWE
1179 Content-Type: text/plain; charset=us-ascii
1180 Content-Disposition: inline
1182 test attachment binary
1184 --bCsyhTFzCvuiizWE
1185 Content-Type: application/octet-stream
1186 Content-Disposition: attachment; filename="main.dvi"
1187 Content-Transfer-Encoding: base64
1189 SnVzdCBhIHRlc3QgAQo=
1191 --bCsyhTFzCvuiizWE--
1192 ''')
1193 messages = self.db.issue.get('1', 'messages')
1194 messages.sort()
1195 file = self.db.file.getnode (self.db.msg.get(messages[-1], 'files')[0])
1196 self.assertEqual(file.name, 'main.dvi')
1197 self.assertEqual(file.content, 'Just a test \001\n')
1199 def testFollowupStupidQuoting(self):
1200 self.doNewIssue()
1202 self._handle_mail('''Content-Type: text/plain;
1203 charset="iso-8859-1"
1204 From: richard <richard@test.test>
1205 To: issue_tracker@your.tracker.email.domain.example
1206 Message-Id: <followup_dummy_id>
1207 In-Reply-To: <dummy_test_message_id>
1208 Subject: Re: "[issue1] Testing... "
1210 This is a followup
1211 ''')
1212 self.compareMessages(self._get_mail(),
1213 '''FROM: roundup-admin@your.tracker.email.domain.example
1214 TO: chef@bork.bork.bork
1215 Content-Type: text/plain; charset="utf-8"
1216 Subject: [issue1] Testing...
1217 To: chef@bork.bork.bork
1218 From: richard <issue_tracker@your.tracker.email.domain.example>
1219 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1220 MIME-Version: 1.0
1221 Message-Id: <followup_dummy_id>
1222 In-Reply-To: <dummy_test_message_id>
1223 X-Roundup-Name: Roundup issue tracker
1224 X-Roundup-Loop: hello
1225 X-Roundup-Issue-Status: chatting
1226 Content-Transfer-Encoding: quoted-printable
1229 richard <richard@test.test> added the comment:
1231 This is a followup
1233 ----------
1234 status: unread -> chatting
1236 _______________________________________________________________________
1237 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1238 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1239 _______________________________________________________________________
1240 ''')
1242 def testEmailQuoting(self):
1243 self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
1244 self.innerTestQuoting('''This is a followup
1245 ''')
1247 def testEmailQuotingRemove(self):
1248 self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
1249 self.innerTestQuoting('''Blah blah wrote:
1250 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
1251 > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
1252 >
1254 This is a followup
1255 ''')
1257 def innerTestQuoting(self, expect):
1258 nodeid = self.doNewIssue()
1260 messages = self.db.issue.get(nodeid, 'messages')
1262 self._handle_mail('''Content-Type: text/plain;
1263 charset="iso-8859-1"
1264 From: richard <richard@test.test>
1265 To: issue_tracker@your.tracker.email.domain.example
1266 Message-Id: <followup_dummy_id>
1267 In-Reply-To: <dummy_test_message_id>
1268 Subject: Re: [issue1] Testing...
1270 Blah blah wrote:
1271 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
1272 > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
1273 >
1275 This is a followup
1276 ''')
1277 # figure the new message id
1278 newmessages = self.db.issue.get(nodeid, 'messages')
1279 for msg in messages:
1280 newmessages.remove(msg)
1281 messageid = newmessages[0]
1283 self.compareMessages(self.db.msg.get(messageid, 'content'), expect)
1285 def testUserLookup(self):
1286 i = self.db.user.create(username='user1', address='user1@foo.com')
1287 self.assertEqual(uidFromAddress(self.db, ('', 'user1@foo.com'), 0), i)
1288 self.assertEqual(uidFromAddress(self.db, ('', 'USER1@foo.com'), 0), i)
1289 i = self.db.user.create(username='user2', address='USER2@foo.com')
1290 self.assertEqual(uidFromAddress(self.db, ('', 'USER2@foo.com'), 0), i)
1291 self.assertEqual(uidFromAddress(self.db, ('', 'user2@foo.com'), 0), i)
1293 def testUserAlternateLookup(self):
1294 i = self.db.user.create(username='user1', address='user1@foo.com',
1295 alternate_addresses='user1@bar.com')
1296 self.assertEqual(uidFromAddress(self.db, ('', 'user1@bar.com'), 0), i)
1297 self.assertEqual(uidFromAddress(self.db, ('', 'USER1@bar.com'), 0), i)
1299 def testUserCreate(self):
1300 i = uidFromAddress(self.db, ('', 'user@foo.com'), 1)
1301 self.assertNotEqual(uidFromAddress(self.db, ('', 'user@bar.com'), 1), i)
1303 def testRFC2822(self):
1304 ascii_header = "[issue243] This is a \"test\" - with 'quotation' marks"
1305 unicode_header = '[issue244] \xd0\xb0\xd0\xbd\xd0\xb4\xd1\x80\xd0\xb5\xd0\xb9'
1306 unicode_encoded = '=?utf-8?q?[issue244]_=D0=B0=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?='
1307 self.assertEqual(rfc2822.encode_header(ascii_header), ascii_header)
1308 self.assertEqual(rfc2822.encode_header(unicode_header), unicode_encoded)
1310 def testRegistrationConfirmation(self):
1311 otk = "Aj4euk4LZSAdwePohj90SME5SpopLETL"
1312 self.db.getOTKManager().set(otk, username='johannes')
1313 self._handle_mail('''Content-Type: text/plain;
1314 charset="iso-8859-1"
1315 From: Chef <chef@bork.bork.bork>
1316 To: issue_tracker@your.tracker.email.domain.example
1317 Cc: richard@test.test
1318 Message-Id: <dummy_test_message_id>
1319 Subject: Re: Complete your registration to Roundup issue tracker
1320 -- key %s
1322 This is a test confirmation of registration.
1323 ''' % otk)
1324 self.db.user.lookup('johannes')
1326 def testFollowupOnNonIssue(self):
1327 self.db.keyword.create(name='Foo')
1328 self._handle_mail('''Content-Type: text/plain;
1329 charset="iso-8859-1"
1330 From: richard <richard@test.test>
1331 To: issue_tracker@your.tracker.email.domain.example
1332 Message-Id: <followup_dummy_id>
1333 In-Reply-To: <dummy_test_message_id>
1334 Subject: [keyword1] Testing... [name=Bar]
1336 ''')
1337 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1339 def testResentFrom(self):
1340 nodeid = self._handle_mail('''Content-Type: text/plain;
1341 charset="iso-8859-1"
1342 From: Chef <chef@bork.bork.bork>
1343 Resent-From: mary <mary@test.test>
1344 To: issue_tracker@your.tracker.email.domain.example
1345 Cc: richard@test.test
1346 Message-Id: <dummy_test_message_id>
1347 Subject: [issue] Testing...
1349 This is a test submission of a new issue.
1350 ''')
1351 assert not os.path.exists(SENDMAILDEBUG)
1352 l = self.db.issue.get(nodeid, 'nosy')
1353 l.sort()
1354 self.assertEqual(l, [self.richard_id, self.mary_id])
1355 return nodeid
1357 def testDejaVu(self):
1358 self.assertRaises(IgnoreLoop, self._handle_mail,
1359 '''Content-Type: text/plain;
1360 charset="iso-8859-1"
1361 From: Chef <chef@bork.bork.bork>
1362 X-Roundup-Loop: hello
1363 To: issue_tracker@your.tracker.email.domain.example
1364 Cc: richard@test.test
1365 Message-Id: <dummy_test_message_id>
1366 Subject: Re: [issue] Testing...
1368 Hi, I've been mis-configured to loop messages back to myself.
1369 ''')
1371 def testItsBulkStupid(self):
1372 self.assertRaises(IgnoreBulk, self._handle_mail,
1373 '''Content-Type: text/plain;
1374 charset="iso-8859-1"
1375 From: Chef <chef@bork.bork.bork>
1376 Precedence: bulk
1377 To: issue_tracker@your.tracker.email.domain.example
1378 Cc: richard@test.test
1379 Message-Id: <dummy_test_message_id>
1380 Subject: Re: [issue] Testing...
1382 Hi, I'm on holidays, and this is a dumb auto-responder.
1383 ''')
1385 def testAutoReplyEmailsAreIgnored(self):
1386 self.assertRaises(IgnoreBulk, self._handle_mail,
1387 '''Content-Type: text/plain;
1388 charset="iso-8859-1"
1389 From: Chef <chef@bork.bork.bork>
1390 To: issue_tracker@your.tracker.email.domain.example
1391 Cc: richard@test.test
1392 Message-Id: <dummy_test_message_id>
1393 Subject: Re: [issue] Out of office AutoReply: Back next week
1395 Hi, I am back in the office next week
1396 ''')
1398 def testNoSubject(self):
1399 self.assertRaises(MailUsageError, self._handle_mail,
1400 '''Content-Type: text/plain;
1401 charset="iso-8859-1"
1402 From: Chef <chef@bork.bork.bork>
1403 To: issue_tracker@your.tracker.email.domain.example
1404 Cc: richard@test.test
1405 Reply-To: chef@bork.bork.bork
1406 Message-Id: <dummy_test_message_id>
1408 ''')
1410 #
1411 # TEST FOR INVALID DESIGNATOR HANDLING
1412 #
1413 def testInvalidDesignator(self):
1414 self.assertRaises(MailUsageError, self._handle_mail,
1415 '''Content-Type: text/plain;
1416 charset="iso-8859-1"
1417 From: Chef <chef@bork.bork.bork>
1418 To: issue_tracker@your.tracker.email.domain.example
1419 Subject: [frobulated] testing
1420 Cc: richard@test.test
1421 Reply-To: chef@bork.bork.bork
1422 Message-Id: <dummy_test_message_id>
1424 ''')
1425 self.assertRaises(MailUsageError, self._handle_mail,
1426 '''Content-Type: text/plain;
1427 charset="iso-8859-1"
1428 From: Chef <chef@bork.bork.bork>
1429 To: issue_tracker@your.tracker.email.domain.example
1430 Subject: [issue12345] testing
1431 Cc: richard@test.test
1432 Reply-To: chef@bork.bork.bork
1433 Message-Id: <dummy_test_message_id>
1435 ''')
1437 def testInvalidClassLoose(self):
1438 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1439 nodeid = self._handle_mail('''Content-Type: text/plain;
1440 charset="iso-8859-1"
1441 From: Chef <chef@bork.bork.bork>
1442 To: issue_tracker@your.tracker.email.domain.example
1443 Subject: [frobulated] testing
1444 Cc: richard@test.test
1445 Reply-To: chef@bork.bork.bork
1446 Message-Id: <dummy_test_message_id>
1448 ''')
1449 assert not os.path.exists(SENDMAILDEBUG)
1450 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1451 '[frobulated] testing')
1453 def testInvalidClassLooseReply(self):
1454 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1455 nodeid = self._handle_mail('''Content-Type: text/plain;
1456 charset="iso-8859-1"
1457 From: Chef <chef@bork.bork.bork>
1458 To: issue_tracker@your.tracker.email.domain.example
1459 Subject: Re: [frobulated] testing
1460 Cc: richard@test.test
1461 Reply-To: chef@bork.bork.bork
1462 Message-Id: <dummy_test_message_id>
1464 ''')
1465 assert not os.path.exists(SENDMAILDEBUG)
1466 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1467 '[frobulated] testing')
1469 def testInvalidClassLoose(self):
1470 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1471 nodeid = self._handle_mail('''Content-Type: text/plain;
1472 charset="iso-8859-1"
1473 From: Chef <chef@bork.bork.bork>
1474 To: issue_tracker@your.tracker.email.domain.example
1475 Subject: [issue1234] testing
1476 Cc: richard@test.test
1477 Reply-To: chef@bork.bork.bork
1478 Message-Id: <dummy_test_message_id>
1480 ''')
1481 assert not os.path.exists(SENDMAILDEBUG)
1482 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1483 '[issue1234] testing')
1485 def testClassLooseOK(self):
1486 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1487 self.db.keyword.create(name='Foo')
1488 nodeid = self._handle_mail('''Content-Type: text/plain;
1489 charset="iso-8859-1"
1490 From: Chef <chef@bork.bork.bork>
1491 To: issue_tracker@your.tracker.email.domain.example
1492 Subject: [keyword1] Testing... [name=Bar]
1493 Cc: richard@test.test
1494 Reply-To: chef@bork.bork.bork
1495 Message-Id: <dummy_test_message_id>
1497 ''')
1498 assert not os.path.exists(SENDMAILDEBUG)
1499 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1501 def testClassStrictInvalid(self):
1502 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'strict'
1503 self.instance.config.MAILGW_DEFAULT_CLASS = ''
1505 message = '''Content-Type: text/plain;
1506 charset="iso-8859-1"
1507 From: Chef <chef@bork.bork.bork>
1508 To: issue_tracker@your.tracker.email.domain.example
1509 Subject: Testing...
1510 Cc: richard@test.test
1511 Reply-To: chef@bork.bork.bork
1512 Message-Id: <dummy_test_message_id>
1514 '''
1515 self.assertRaises(MailUsageError, self._handle_mail, message)
1517 def testClassStrictValid(self):
1518 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'strict'
1519 self.instance.config.MAILGW_DEFAULT_CLASS = ''
1521 nodeid = self._handle_mail('''Content-Type: text/plain;
1522 charset="iso-8859-1"
1523 From: Chef <chef@bork.bork.bork>
1524 To: issue_tracker@your.tracker.email.domain.example
1525 Subject: [issue] Testing...
1526 Cc: richard@test.test
1527 Reply-To: chef@bork.bork.bork
1528 Message-Id: <dummy_test_message_id>
1530 ''')
1532 assert not os.path.exists(SENDMAILDEBUG)
1533 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
1535 #
1536 # TEST FOR INVALID COMMANDS HANDLING
1537 #
1538 def testInvalidCommands(self):
1539 self.assertRaises(MailUsageError, self._handle_mail,
1540 '''Content-Type: text/plain;
1541 charset="iso-8859-1"
1542 From: Chef <chef@bork.bork.bork>
1543 To: issue_tracker@your.tracker.email.domain.example
1544 Subject: testing [frobulated]
1545 Cc: richard@test.test
1546 Reply-To: chef@bork.bork.bork
1547 Message-Id: <dummy_test_message_id>
1549 ''')
1551 def testInvalidCommandPassthrough(self):
1552 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'none'
1553 nodeid = self._handle_mail('''Content-Type: text/plain;
1554 charset="iso-8859-1"
1555 From: Chef <chef@bork.bork.bork>
1556 To: issue_tracker@your.tracker.email.domain.example
1557 Subject: testing [frobulated]
1558 Cc: richard@test.test
1559 Reply-To: chef@bork.bork.bork
1560 Message-Id: <dummy_test_message_id>
1562 ''')
1563 assert not os.path.exists(SENDMAILDEBUG)
1564 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1565 'testing [frobulated]')
1567 def testInvalidCommandPassthroughLoose(self):
1568 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'loose'
1569 nodeid = self._handle_mail('''Content-Type: text/plain;
1570 charset="iso-8859-1"
1571 From: Chef <chef@bork.bork.bork>
1572 To: issue_tracker@your.tracker.email.domain.example
1573 Subject: testing [frobulated]
1574 Cc: richard@test.test
1575 Reply-To: chef@bork.bork.bork
1576 Message-Id: <dummy_test_message_id>
1578 ''')
1579 assert not os.path.exists(SENDMAILDEBUG)
1580 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1581 'testing [frobulated]')
1583 def testInvalidCommandPassthroughLooseOK(self):
1584 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'loose'
1585 nodeid = self._handle_mail('''Content-Type: text/plain;
1586 charset="iso-8859-1"
1587 From: Chef <chef@bork.bork.bork>
1588 To: issue_tracker@your.tracker.email.domain.example
1589 Subject: testing [assignedto=mary]
1590 Cc: richard@test.test
1591 Reply-To: chef@bork.bork.bork
1592 Message-Id: <dummy_test_message_id>
1594 ''')
1595 assert not os.path.exists(SENDMAILDEBUG)
1596 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing')
1597 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), self.mary_id)
1599 def testCommandDelimiters(self):
1600 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
1601 nodeid = self._handle_mail('''Content-Type: text/plain;
1602 charset="iso-8859-1"
1603 From: Chef <chef@bork.bork.bork>
1604 To: issue_tracker@your.tracker.email.domain.example
1605 Subject: testing {assignedto=mary}
1606 Cc: richard@test.test
1607 Reply-To: chef@bork.bork.bork
1608 Message-Id: <dummy_test_message_id>
1610 ''')
1611 assert not os.path.exists(SENDMAILDEBUG)
1612 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing')
1613 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), self.mary_id)
1615 def testPrefixDelimiters(self):
1616 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
1617 self.db.keyword.create(name='Foo')
1618 self._handle_mail('''Content-Type: text/plain;
1619 charset="iso-8859-1"
1620 From: richard <richard@test.test>
1621 To: issue_tracker@your.tracker.email.domain.example
1622 Message-Id: <followup_dummy_id>
1623 In-Reply-To: <dummy_test_message_id>
1624 Subject: {keyword1} Testing... {name=Bar}
1626 ''')
1627 assert not os.path.exists(SENDMAILDEBUG)
1628 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1630 def testCommandDelimitersIgnore(self):
1631 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
1632 nodeid = self._handle_mail('''Content-Type: text/plain;
1633 charset="iso-8859-1"
1634 From: Chef <chef@bork.bork.bork>
1635 To: issue_tracker@your.tracker.email.domain.example
1636 Subject: testing [assignedto=mary]
1637 Cc: richard@test.test
1638 Reply-To: chef@bork.bork.bork
1639 Message-Id: <dummy_test_message_id>
1641 ''')
1642 assert not os.path.exists(SENDMAILDEBUG)
1643 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1644 'testing [assignedto=mary]')
1645 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), None)
1647 def testReplytoMatch(self):
1648 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1649 nodeid = self.doNewIssue()
1650 nodeid2 = self._handle_mail('''Content-Type: text/plain;
1651 charset="iso-8859-1"
1652 From: Chef <chef@bork.bork.bork>
1653 To: issue_tracker@your.tracker.email.domain.example
1654 Message-Id: <dummy_test_message_id2>
1655 In-Reply-To: <dummy_test_message_id>
1656 Subject: Testing...
1658 Followup message.
1659 ''')
1661 nodeid3 = self._handle_mail('''Content-Type: text/plain;
1662 charset="iso-8859-1"
1663 From: Chef <chef@bork.bork.bork>
1664 To: issue_tracker@your.tracker.email.domain.example
1665 Message-Id: <dummy_test_message_id3>
1666 In-Reply-To: <dummy_test_message_id2>
1667 Subject: Testing...
1669 Yet another message in the same thread/issue.
1670 ''')
1672 self.assertEqual(nodeid, nodeid2)
1673 self.assertEqual(nodeid, nodeid3)
1675 def testHelpSubject(self):
1676 message = '''Content-Type: text/plain;
1677 charset="iso-8859-1"
1678 From: Chef <chef@bork.bork.bork>
1679 To: issue_tracker@your.tracker.email.domain.example
1680 Message-Id: <dummy_test_message_id2>
1681 In-Reply-To: <dummy_test_message_id>
1682 Subject: hElp
1685 '''
1686 self.assertRaises(MailUsageHelp, self._handle_mail, message)
1688 def testMaillistSubject(self):
1689 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '[]'
1690 self.db.keyword.create(name='Foo')
1691 self._handle_mail('''Content-Type: text/plain;
1692 charset="iso-8859-1"
1693 From: Chef <chef@bork.bork.bork>
1694 To: issue_tracker@your.tracker.email.domain.example
1695 Subject: [mailinglist-name] [keyword1] Testing.. [name=Bar]
1696 Cc: richard@test.test
1697 Reply-To: chef@bork.bork.bork
1698 Message-Id: <dummy_test_message_id>
1700 ''')
1702 assert not os.path.exists(SENDMAILDEBUG)
1703 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1705 def testUnknownPrefixSubject(self):
1706 self.db.keyword.create(name='Foo')
1707 self._handle_mail('''Content-Type: text/plain;
1708 charset="iso-8859-1"
1709 From: Chef <chef@bork.bork.bork>
1710 To: issue_tracker@your.tracker.email.domain.example
1711 Subject: VeryStrangeRe: [keyword1] Testing.. [name=Bar]
1712 Cc: richard@test.test
1713 Reply-To: chef@bork.bork.bork
1714 Message-Id: <dummy_test_message_id>
1716 ''')
1718 assert not os.path.exists(SENDMAILDEBUG)
1719 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1721 def testIssueidLast(self):
1722 nodeid1 = self.doNewIssue()
1723 nodeid2 = self._handle_mail('''Content-Type: text/plain;
1724 charset="iso-8859-1"
1725 From: mary <mary@test.test>
1726 To: issue_tracker@your.tracker.email.domain.example
1727 Message-Id: <followup_dummy_id>
1728 In-Reply-To: <dummy_test_message_id>
1729 Subject: New title [issue1]
1731 This is a second followup
1732 ''')
1734 assert nodeid1 == nodeid2
1735 self.assertEqual(self.db.issue.get(nodeid2, 'title'), "Testing...")
1738 def test_suite():
1739 suite = unittest.TestSuite()
1740 suite.addTest(unittest.makeSuite(MailgwTestCase))
1741 return suite
1743 if __name__ == '__main__':
1744 runner = unittest.TextTestRunner()
1745 unittest.main(testRunner=runner)
1747 # vim: set filetype=python sts=4 sw=4 et si :