1 # -*- encoding: utf-8 -*-
2 #
3 # Copyright (c) 2001 Richard Jones, richard@bofh.asn.au.
4 # This module is free software, and you may redistribute it and/or modify
5 # under the same terms as Python, so long as this copyright message and
6 # disclaimer are retained in their original form.
7 #
8 # This module is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 #
12 # $Id: test_mailgw.py,v 1.96 2008-08-19 01:40:59 richard Exp $
14 # TODO: test bcc
16 import unittest, tempfile, os, shutil, errno, imp, sys, difflib, rfc822, time
18 from cStringIO import StringIO
20 if not os.environ.has_key('SENDMAILDEBUG'):
21 os.environ['SENDMAILDEBUG'] = 'mail-test.log'
22 SENDMAILDEBUG = os.environ['SENDMAILDEBUG']
24 from roundup.mailgw import MailGW, Unauthorized, uidFromAddress, \
25 parseContent, IgnoreLoop, IgnoreBulk, MailUsageError, MailUsageHelp
26 from roundup import init, instance, password, rfc2822, __version__
27 from roundup.anypy.sets_ import set
29 import db_test_base
31 class Message(rfc822.Message):
32 """String-based Message class with equivalence test."""
33 def __init__(self, s):
34 rfc822.Message.__init__(self, StringIO(s.strip()))
36 def __eq__(self, other):
37 return (self.dict == other.dict and
38 self.fp.read() == other.fp.read())
40 class DiffHelper:
41 def compareMessages(self, new, old):
42 """Compare messages for semantic equivalence."""
43 new, old = Message(new), Message(old)
45 # all Roundup-generated messages have "Precedence: bulk"
46 old['Precedence'] = 'bulk'
48 # don't try to compare the date
49 del new['date'], old['date']
51 if not new == old:
52 res = []
54 replace = {}
55 for key in new.keys():
56 if key.startswith('from '):
57 # skip the unix from line
58 continue
59 if key.lower() == 'x-roundup-version':
60 # version changes constantly, so handle it specially
61 if new[key] != __version__:
62 res.append(' %s: %r != %r' % (key, __version__,
63 new[key]))
64 elif key.lower() == 'content-type' and 'boundary=' in new[key]:
65 # handle mime messages
66 newmime = new[key].split('=',1)[-1].strip('"')
67 oldmime = old.get(key, '').split('=',1)[-1].strip('"')
68 replace ['--' + newmime] = '--' + oldmime
69 replace ['--' + newmime + '--'] = '--' + oldmime + '--'
70 elif new.get(key, '') != old.get(key, ''):
71 res.append(' %s: %r != %r' % (key, old.get(key, ''),
72 new.get(key, '')))
74 body_diff = self.compareStrings(new.fp.read(), old.fp.read(),
75 replace=replace)
76 if body_diff:
77 res.append('')
78 res.extend(body_diff)
80 if res:
81 res.insert(0, 'Generated message not correct (diff follows):')
82 raise AssertionError, '\n'.join(res)
84 def compareStrings(self, s2, s1, replace={}):
85 '''Note the reversal of s2 and s1 - difflib.SequenceMatcher wants
86 the first to be the "original" but in the calls in this file,
87 the second arg is the original. Ho hum.
88 Do replacements over the replace dict -- used for mime boundary
89 '''
90 l1 = s1.strip().split('\n')
91 l2 = [replace.get(i,i) for i in s2.strip().split('\n')]
92 if l1 == l2:
93 return
94 s = difflib.SequenceMatcher(None, l1, l2)
95 res = []
96 for value, s1s, s1e, s2s, s2e in s.get_opcodes():
97 if value == 'equal':
98 for i in range(s1s, s1e):
99 res.append(' %s'%l1[i])
100 elif value == 'delete':
101 for i in range(s1s, s1e):
102 res.append('- %s'%l1[i])
103 elif value == 'insert':
104 for i in range(s2s, s2e):
105 res.append('+ %s'%l2[i])
106 elif value == 'replace':
107 for i, j in zip(range(s1s, s1e), range(s2s, s2e)):
108 res.append('- %s'%l1[i])
109 res.append('+ %s'%l2[j])
111 return res
113 class MailgwTestCase(unittest.TestCase, DiffHelper):
114 count = 0
115 schema = 'classic'
116 def setUp(self):
117 MailgwTestCase.count = MailgwTestCase.count + 1
118 self.dirname = '_test_mailgw_%s'%self.count
119 # set up and open a tracker
120 self.instance = db_test_base.setupTracker(self.dirname)
122 # and open the database
123 self.db = self.instance.open('admin')
124 self.chef_id = self.db.user.create(username='Chef',
125 address='chef@bork.bork.bork', realname='Bork, Chef', roles='User')
126 self.richard_id = self.db.user.create(username='richard',
127 address='richard@test.test', roles='User')
128 self.mary_id = self.db.user.create(username='mary',
129 address='mary@test.test', roles='User', realname='Contrary, Mary')
130 self.john_id = self.db.user.create(username='john',
131 address='john@test.test', roles='User', realname='John Doe',
132 alternate_addresses='jondoe@test.test\njohn.doe@test.test')
134 def tearDown(self):
135 if os.path.exists(SENDMAILDEBUG):
136 os.remove(SENDMAILDEBUG)
137 self.db.close()
138 try:
139 shutil.rmtree(self.dirname)
140 except OSError, error:
141 if error.errno not in (errno.ENOENT, errno.ESRCH): raise
143 def _handle_mail(self, message):
144 # handler will open a new db handle. On single-threaded
145 # databases we'll have to close our current connection
146 self.db.commit()
147 self.db.close()
148 handler = self.instance.MailGW(self.instance)
149 handler.trapExceptions = 0
150 ret = handler.main(StringIO(message))
151 # handler had its own database, open new connection
152 self.db = self.instance.open('admin')
153 return ret
155 def _get_mail(self):
156 f = open(SENDMAILDEBUG)
157 try:
158 return f.read()
159 finally:
160 f.close()
162 def testEmptyMessage(self):
163 nodeid = self._handle_mail('''Content-Type: text/plain;
164 charset="iso-8859-1"
165 From: Chef <chef@bork.bork.bork>
166 To: issue_tracker@your.tracker.email.domain.example
167 Cc: richard@test.test
168 Reply-To: chef@bork.bork.bork
169 Message-Id: <dummy_test_message_id>
170 Subject: [issue] Testing...
172 ''')
173 assert not os.path.exists(SENDMAILDEBUG)
174 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
176 def doNewIssue(self):
177 nodeid = self._handle_mail('''Content-Type: text/plain;
178 charset="iso-8859-1"
179 From: Chef <chef@bork.bork.bork>
180 To: issue_tracker@your.tracker.email.domain.example
181 Cc: richard@test.test
182 Message-Id: <dummy_test_message_id>
183 Subject: [issue] Testing...
185 This is a test submission of a new issue.
186 ''')
187 assert not os.path.exists(SENDMAILDEBUG)
188 l = self.db.issue.get(nodeid, 'nosy')
189 l.sort()
190 self.assertEqual(l, [self.chef_id, self.richard_id])
191 return nodeid
193 def testNewIssue(self):
194 self.doNewIssue()
196 def testNewIssueNosy(self):
197 self.instance.config.ADD_AUTHOR_TO_NOSY = 'yes'
198 nodeid = self._handle_mail('''Content-Type: text/plain;
199 charset="iso-8859-1"
200 From: Chef <chef@bork.bork.bork>
201 To: issue_tracker@your.tracker.email.domain.example
202 Cc: richard@test.test
203 Message-Id: <dummy_test_message_id>
204 Subject: [issue] Testing...
206 This is a test submission of a new issue.
207 ''')
208 assert not os.path.exists(SENDMAILDEBUG)
209 l = self.db.issue.get(nodeid, 'nosy')
210 l.sort()
211 self.assertEqual(l, [self.chef_id, self.richard_id])
213 def testAlternateAddress(self):
214 self._handle_mail('''Content-Type: text/plain;
215 charset="iso-8859-1"
216 From: John Doe <john.doe@test.test>
217 To: issue_tracker@your.tracker.email.domain.example
218 Message-Id: <dummy_test_message_id>
219 Subject: [issue] Testing...
221 This is a test submission of a new issue.
222 ''')
223 userlist = self.db.user.list()
224 assert not os.path.exists(SENDMAILDEBUG)
225 self.assertEqual(userlist, self.db.user.list(),
226 "user created when it shouldn't have been")
228 def testNewIssueNoClass(self):
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 Cc: richard@test.test
234 Message-Id: <dummy_test_message_id>
235 Subject: Testing...
237 This is a test submission of a new issue.
238 ''')
239 assert not os.path.exists(SENDMAILDEBUG)
241 def testNewIssueAuthMsg(self):
242 # TODO: fix the damn config - this is apalling
243 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
244 self._handle_mail('''Content-Type: text/plain;
245 charset="iso-8859-1"
246 From: Chef <chef@bork.bork.bork>
247 To: issue_tracker@your.tracker.email.domain.example
248 Message-Id: <dummy_test_message_id>
249 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
251 This is a test submission of a new issue.
252 ''')
253 self.compareMessages(self._get_mail(),
254 '''FROM: roundup-admin@your.tracker.email.domain.example
255 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
256 Content-Type: text/plain; charset="utf-8"
257 Subject: [issue1] Testing...
258 To: chef@bork.bork.bork, mary@test.test, richard@test.test
259 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
260 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
261 MIME-Version: 1.0
262 Message-Id: <dummy_test_message_id>
263 X-Roundup-Name: Roundup issue tracker
264 X-Roundup-Loop: hello
265 X-Roundup-Issue-Status: unread
266 Content-Transfer-Encoding: quoted-printable
269 New submission from Bork, Chef <chef@bork.bork.bork>:
271 This is a test submission of a new issue.
273 ----------
274 assignedto: richard
275 messages: 1
276 nosy: Chef, mary, richard
277 status: unread
278 title: Testing...
280 _______________________________________________________________________
281 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
282 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
283 _______________________________________________________________________
284 ''')
286 def testNewIssueNoAuthorInfo(self):
287 self.db.config.MAIL_ADD_AUTHORINFO = 'no'
288 self._handle_mail('''Content-Type: text/plain;
289 charset="iso-8859-1"
290 From: Chef <chef@bork.bork.bork>
291 To: issue_tracker@your.tracker.email.domain.example
292 Message-Id: <dummy_test_message_id>
293 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
295 This is a test submission of a new issue.
296 ''')
297 self.compareMessages(self._get_mail(),
298 '''FROM: roundup-admin@your.tracker.email.domain.example
299 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
300 Content-Type: text/plain; charset="utf-8"
301 Subject: [issue1] Testing...
302 To: mary@test.test, richard@test.test
303 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
304 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
305 MIME-Version: 1.0
306 Message-Id: <dummy_test_message_id>
307 X-Roundup-Name: Roundup issue tracker
308 X-Roundup-Loop: hello
309 X-Roundup-Issue-Status: unread
310 Content-Transfer-Encoding: quoted-printable
312 This is a test submission of a new issue.
314 ----------
315 assignedto: richard
316 messages: 1
317 nosy: Chef, mary, richard
318 status: unread
319 title: Testing...
321 _______________________________________________________________________
322 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
323 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
324 _______________________________________________________________________
325 ''')
327 def testNewIssueNoAuthorEmail(self):
328 self.db.config.MAIL_ADD_AUTHOREMAIL = 'no'
329 self._handle_mail('''Content-Type: text/plain;
330 charset="iso-8859-1"
331 From: Chef <chef@bork.bork.bork>
332 To: issue_tracker@your.tracker.email.domain.example
333 Message-Id: <dummy_test_message_id>
334 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
336 This is a test submission of a new issue.
337 ''')
338 self.compareMessages(self._get_mail(),
339 '''FROM: roundup-admin@your.tracker.email.domain.example
340 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
341 Content-Type: text/plain; charset="utf-8"
342 Subject: [issue1] Testing...
343 To: mary@test.test, richard@test.test
344 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
345 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
346 MIME-Version: 1.0
347 Message-Id: <dummy_test_message_id>
348 X-Roundup-Name: Roundup issue tracker
349 X-Roundup-Loop: hello
350 X-Roundup-Issue-Status: unread
351 Content-Transfer-Encoding: quoted-printable
353 New submission from Bork, Chef:
355 This is a test submission of a new issue.
357 ----------
358 assignedto: richard
359 messages: 1
360 nosy: Chef, mary, richard
361 status: unread
362 title: Testing...
364 _______________________________________________________________________
365 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
366 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
367 _______________________________________________________________________
368 ''')
370 multipart_msg = '''From: mary <mary@test.test>
371 To: issue_tracker@your.tracker.email.domain.example
372 Message-Id: <followup_dummy_id>
373 In-Reply-To: <dummy_test_message_id>
374 Subject: [issue1] Testing...
375 Content-Type: multipart/mixed; boundary="bxyzzy"
376 Content-Disposition: inline
379 --bxyzzy
380 Content-Type: multipart/alternative; boundary="bCsyhTFzCvuiizWE"
381 Content-Disposition: inline
383 --bCsyhTFzCvuiizWE
384 Content-Type: text/plain; charset=us-ascii
385 Content-Disposition: inline
387 test attachment first text/plain
389 --bCsyhTFzCvuiizWE
390 Content-Type: application/octet-stream
391 Content-Disposition: attachment; filename="first.dvi"
392 Content-Transfer-Encoding: base64
394 SnVzdCBhIHRlc3QgAQo=
396 --bCsyhTFzCvuiizWE
397 Content-Type: text/plain; charset=us-ascii
398 Content-Disposition: inline
400 test attachment second text/plain
402 --bCsyhTFzCvuiizWE
403 Content-Type: text/html
404 Content-Disposition: inline
406 <html>
407 to be ignored.
408 </html>
410 --bCsyhTFzCvuiizWE--
412 --bxyzzy
413 Content-Type: multipart/alternative; boundary="bCsyhTFzCvuiizWF"
414 Content-Disposition: inline
416 --bCsyhTFzCvuiizWF
417 Content-Type: text/plain; charset=us-ascii
418 Content-Disposition: inline
420 test attachment third text/plain
422 --bCsyhTFzCvuiizWF
423 Content-Type: application/octet-stream
424 Content-Disposition: attachment; filename="second.dvi"
425 Content-Transfer-Encoding: base64
427 SnVzdCBhIHRlc3QK
429 --bCsyhTFzCvuiizWF--
431 --bxyzzy--
432 '''
434 def testMultipartKeepAlternatives(self):
435 self.doNewIssue()
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) == 5)
441 names = {0 : 'first.dvi', 4 : 'second.dvi'}
442 content = {3 : 'test attachment third text/plain\n',
443 4 : '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 testMultipartDropAlternatives(self):
452 self.doNewIssue()
453 self.db.config.MAILGW_IGNORE_ALTERNATIVES = True
454 self._handle_mail(self.multipart_msg)
455 messages = self.db.issue.get('1', 'messages')
456 messages.sort()
457 msg = self.db.msg.getnode (messages[-1])
458 assert(len(msg.files) == 2)
459 names = {1 : 'second.dvi'}
460 content = {0 : 'test attachment third text/plain\n',
461 1 : 'Just a test\n'}
462 for n, id in enumerate (msg.files):
463 f = self.db.file.getnode (id)
464 self.assertEqual(f.name, names.get (n, 'unnamed'))
465 if n in content :
466 self.assertEqual(f.content, content [n])
467 self.assertEqual(msg.content, 'test attachment second text/plain')
469 def testSimpleFollowup(self):
470 self.doNewIssue()
471 self._handle_mail('''Content-Type: text/plain;
472 charset="iso-8859-1"
473 From: mary <mary@test.test>
474 To: issue_tracker@your.tracker.email.domain.example
475 Message-Id: <followup_dummy_id>
476 In-Reply-To: <dummy_test_message_id>
477 Subject: [issue1] Testing...
479 This is a second followup
480 ''')
481 self.compareMessages(self._get_mail(),
482 '''FROM: roundup-admin@your.tracker.email.domain.example
483 TO: chef@bork.bork.bork, richard@test.test
484 Content-Type: text/plain; charset="utf-8"
485 Subject: [issue1] Testing...
486 To: chef@bork.bork.bork, richard@test.test
487 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
488 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
489 MIME-Version: 1.0
490 Message-Id: <followup_dummy_id>
491 In-Reply-To: <dummy_test_message_id>
492 X-Roundup-Name: Roundup issue tracker
493 X-Roundup-Loop: hello
494 X-Roundup-Issue-Status: chatting
495 Content-Transfer-Encoding: quoted-printable
498 Contrary, Mary <mary@test.test> added the comment:
500 This is a second followup
502 ----------
503 status: unread -> chatting
505 _______________________________________________________________________
506 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
507 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
508 _______________________________________________________________________
509 ''')
511 def testFollowup(self):
512 self.doNewIssue()
514 self._handle_mail('''Content-Type: text/plain;
515 charset="iso-8859-1"
516 From: richard <richard@test.test>
517 To: issue_tracker@your.tracker.email.domain.example
518 Message-Id: <followup_dummy_id>
519 In-Reply-To: <dummy_test_message_id>
520 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
522 This is a followup
523 ''')
524 l = self.db.issue.get('1', 'nosy')
525 l.sort()
526 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
527 self.john_id])
529 self.compareMessages(self._get_mail(),
530 '''FROM: roundup-admin@your.tracker.email.domain.example
531 TO: chef@bork.bork.bork, john@test.test, mary@test.test
532 Content-Type: text/plain; charset="utf-8"
533 Subject: [issue1] Testing...
534 To: chef@bork.bork.bork, john@test.test, mary@test.test
535 From: richard <issue_tracker@your.tracker.email.domain.example>
536 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
537 MIME-Version: 1.0
538 Message-Id: <followup_dummy_id>
539 In-Reply-To: <dummy_test_message_id>
540 X-Roundup-Name: Roundup issue tracker
541 X-Roundup-Loop: hello
542 X-Roundup-Issue-Status: chatting
543 Content-Transfer-Encoding: quoted-printable
546 richard <richard@test.test> added the comment:
548 This is a followup
550 ----------
551 assignedto: -> mary
552 nosy: +john, mary
553 status: unread -> chatting
555 _______________________________________________________________________
556 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
557 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
558 _______________________________________________________________________
559 ''')
561 def testPropertyChangeOnly(self):
562 self.doNewIssue()
563 oldvalues = self.db.getnode('issue', '1').copy()
564 oldvalues['assignedto'] = None
565 # reconstruct old behaviour: This would reuse the
566 # database-handle from the doNewIssue above which has committed
567 # as user "Chef". So we close and reopen the db as that user.
568 self.db.close()
569 self.db = self.instance.open('Chef')
570 self.db.issue.set('1', assignedto=self.chef_id)
571 self.db.commit()
572 self.db.issue.nosymessage('1', None, oldvalues)
574 new_mail = ""
575 for line in self._get_mail().split("\n"):
576 if "Message-Id: " in line:
577 continue
578 if "Date: " in line:
579 continue
580 new_mail += line+"\n"
582 self.compareMessages(new_mail, """
583 FROM: roundup-admin@your.tracker.email.domain.example
584 TO: chef@bork.bork.bork, richard@test.test
585 Content-Type: text/plain; charset="utf-8"
586 Subject: [issue1] Testing...
587 To: chef@bork.bork.bork, richard@test.test
588 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
589 X-Roundup-Name: Roundup issue tracker
590 X-Roundup-Loop: hello
591 X-Roundup-Issue-Status: unread
592 X-Roundup-Version: 1.3.3
593 MIME-Version: 1.0
594 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
595 Content-Transfer-Encoding: quoted-printable
598 Change by Bork, Chef <chef@bork.bork.bork>:
601 ----------
602 assignedto: -> Chef
604 _______________________________________________________________________
605 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
606 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
607 _______________________________________________________________________
608 """)
611 #
612 # FOLLOWUP TITLE MATCH
613 #
614 def testFollowupTitleMatch(self):
615 self.doNewIssue()
616 self._handle_mail('''Content-Type: text/plain;
617 charset="iso-8859-1"
618 From: richard <richard@test.test>
619 To: issue_tracker@your.tracker.email.domain.example
620 Message-Id: <followup_dummy_id>
621 Subject: Re: Testing... [assignedto=mary; nosy=+john]
623 This is a followup
624 ''')
625 self.compareMessages(self._get_mail(),
626 '''FROM: roundup-admin@your.tracker.email.domain.example
627 TO: chef@bork.bork.bork, john@test.test, mary@test.test
628 Content-Type: text/plain; charset="utf-8"
629 Subject: [issue1] Testing...
630 To: chef@bork.bork.bork, john@test.test, mary@test.test
631 From: richard <issue_tracker@your.tracker.email.domain.example>
632 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
633 MIME-Version: 1.0
634 Message-Id: <followup_dummy_id>
635 In-Reply-To: <dummy_test_message_id>
636 X-Roundup-Name: Roundup issue tracker
637 X-Roundup-Loop: hello
638 X-Roundup-Issue-Status: chatting
639 Content-Transfer-Encoding: quoted-printable
642 richard <richard@test.test> added the comment:
644 This is a followup
646 ----------
647 assignedto: -> mary
648 nosy: +john, mary
649 status: unread -> chatting
651 _______________________________________________________________________
652 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
653 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
654 _______________________________________________________________________
655 ''')
657 def testFollowupTitleMatchMultiRe(self):
658 nodeid1 = self.doNewIssue()
659 nodeid2 = self._handle_mail('''Content-Type: text/plain;
660 charset="iso-8859-1"
661 From: richard <richard@test.test>
662 To: issue_tracker@your.tracker.email.domain.example
663 Message-Id: <followup_dummy_id>
664 Subject: Re: Testing... [assignedto=mary; nosy=+john]
666 This is a followup
667 ''')
669 nodeid3 = self._handle_mail('''Content-Type: text/plain;
670 charset="iso-8859-1"
671 From: richard <richard@test.test>
672 To: issue_tracker@your.tracker.email.domain.example
673 Message-Id: <followup2_dummy_id>
674 Subject: Ang: Re: Testing...
676 This is a followup
677 ''')
678 self.assertEqual(nodeid1, nodeid2)
679 self.assertEqual(nodeid1, nodeid3)
681 def testFollowupTitleMatchNever(self):
682 nodeid = self.doNewIssue()
683 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'never'
684 self.assertNotEqual(self._handle_mail('''Content-Type: text/plain;
685 charset="iso-8859-1"
686 From: richard <richard@test.test>
687 To: issue_tracker@your.tracker.email.domain.example
688 Message-Id: <followup_dummy_id>
689 Subject: Re: Testing...
691 This is a followup
692 '''), nodeid)
694 def testFollowupTitleMatchNeverInterval(self):
695 nodeid = self.doNewIssue()
696 # force failure of the interval
697 time.sleep(2)
698 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation 00:00:01'
699 self.assertNotEqual(self._handle_mail('''Content-Type: text/plain;
700 charset="iso-8859-1"
701 From: richard <richard@test.test>
702 To: issue_tracker@your.tracker.email.domain.example
703 Message-Id: <followup_dummy_id>
704 Subject: Re: Testing...
706 This is a followup
707 '''), nodeid)
710 def testFollowupTitleMatchInterval(self):
711 nodeid = self.doNewIssue()
712 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation +1d'
713 self.assertEqual(self._handle_mail('''Content-Type: text/plain;
714 charset="iso-8859-1"
715 From: richard <richard@test.test>
716 To: issue_tracker@your.tracker.email.domain.example
717 Message-Id: <followup_dummy_id>
718 Subject: Re: Testing...
720 This is a followup
721 '''), nodeid)
724 def testFollowupNosyAuthor(self):
725 self.doNewIssue()
726 self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
727 self._handle_mail('''Content-Type: text/plain;
728 charset="iso-8859-1"
729 From: john@test.test
730 To: issue_tracker@your.tracker.email.domain.example
731 Message-Id: <followup_dummy_id>
732 In-Reply-To: <dummy_test_message_id>
733 Subject: [issue1] Testing...
735 This is a followup
736 ''')
738 self.compareMessages(self._get_mail(),
739 '''FROM: roundup-admin@your.tracker.email.domain.example
740 TO: chef@bork.bork.bork, richard@test.test
741 Content-Type: text/plain; charset="utf-8"
742 Subject: [issue1] Testing...
743 To: chef@bork.bork.bork, richard@test.test
744 From: John Doe <issue_tracker@your.tracker.email.domain.example>
745 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
746 MIME-Version: 1.0
747 Message-Id: <followup_dummy_id>
748 In-Reply-To: <dummy_test_message_id>
749 X-Roundup-Name: Roundup issue tracker
750 X-Roundup-Loop: hello
751 X-Roundup-Issue-Status: chatting
752 Content-Transfer-Encoding: quoted-printable
755 John Doe <john@test.test> added the comment:
757 This is a followup
759 ----------
760 nosy: +john
761 status: unread -> chatting
763 _______________________________________________________________________
764 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
765 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
766 _______________________________________________________________________
768 ''')
770 def testFollowupNosyRecipients(self):
771 self.doNewIssue()
772 self.db.config.ADD_RECIPIENTS_TO_NOSY = 'yes'
773 self._handle_mail('''Content-Type: text/plain;
774 charset="iso-8859-1"
775 From: richard@test.test
776 To: issue_tracker@your.tracker.email.domain.example
777 Cc: john@test.test
778 Message-Id: <followup_dummy_id>
779 In-Reply-To: <dummy_test_message_id>
780 Subject: [issue1] Testing...
782 This is a followup
783 ''')
784 self.compareMessages(self._get_mail(),
785 '''FROM: roundup-admin@your.tracker.email.domain.example
786 TO: chef@bork.bork.bork
787 Content-Type: text/plain; charset="utf-8"
788 Subject: [issue1] Testing...
789 To: chef@bork.bork.bork
790 From: richard <issue_tracker@your.tracker.email.domain.example>
791 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
792 MIME-Version: 1.0
793 Message-Id: <followup_dummy_id>
794 In-Reply-To: <dummy_test_message_id>
795 X-Roundup-Name: Roundup issue tracker
796 X-Roundup-Loop: hello
797 X-Roundup-Issue-Status: chatting
798 Content-Transfer-Encoding: quoted-printable
801 richard <richard@test.test> added the comment:
803 This is a followup
805 ----------
806 nosy: +john
807 status: unread -> chatting
809 _______________________________________________________________________
810 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
811 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
812 _______________________________________________________________________
814 ''')
816 def testFollowupNosyAuthorAndCopy(self):
817 self.doNewIssue()
818 self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
819 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
820 self._handle_mail('''Content-Type: text/plain;
821 charset="iso-8859-1"
822 From: john@test.test
823 To: issue_tracker@your.tracker.email.domain.example
824 Message-Id: <followup_dummy_id>
825 In-Reply-To: <dummy_test_message_id>
826 Subject: [issue1] Testing...
828 This is a followup
829 ''')
830 self.compareMessages(self._get_mail(),
831 '''FROM: roundup-admin@your.tracker.email.domain.example
832 TO: chef@bork.bork.bork, john@test.test, richard@test.test
833 Content-Type: text/plain; charset="utf-8"
834 Subject: [issue1] Testing...
835 To: chef@bork.bork.bork, john@test.test, richard@test.test
836 From: John Doe <issue_tracker@your.tracker.email.domain.example>
837 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
838 MIME-Version: 1.0
839 Message-Id: <followup_dummy_id>
840 In-Reply-To: <dummy_test_message_id>
841 X-Roundup-Name: Roundup issue tracker
842 X-Roundup-Loop: hello
843 X-Roundup-Issue-Status: chatting
844 Content-Transfer-Encoding: quoted-printable
847 John Doe <john@test.test> added the comment:
849 This is a followup
851 ----------
852 nosy: +john
853 status: unread -> chatting
855 _______________________________________________________________________
856 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
857 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
858 _______________________________________________________________________
860 ''')
862 def testFollowupNoNosyAuthor(self):
863 self.doNewIssue()
864 self.instance.config.ADD_AUTHOR_TO_NOSY = 'no'
865 self._handle_mail('''Content-Type: text/plain;
866 charset="iso-8859-1"
867 From: john@test.test
868 To: issue_tracker@your.tracker.email.domain.example
869 Message-Id: <followup_dummy_id>
870 In-Reply-To: <dummy_test_message_id>
871 Subject: [issue1] Testing...
873 This is a followup
874 ''')
875 self.compareMessages(self._get_mail(),
876 '''FROM: roundup-admin@your.tracker.email.domain.example
877 TO: chef@bork.bork.bork, richard@test.test
878 Content-Type: text/plain; charset="utf-8"
879 Subject: [issue1] Testing...
880 To: chef@bork.bork.bork, richard@test.test
881 From: John Doe <issue_tracker@your.tracker.email.domain.example>
882 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
883 MIME-Version: 1.0
884 Message-Id: <followup_dummy_id>
885 In-Reply-To: <dummy_test_message_id>
886 X-Roundup-Name: Roundup issue tracker
887 X-Roundup-Loop: hello
888 X-Roundup-Issue-Status: chatting
889 Content-Transfer-Encoding: quoted-printable
892 John Doe <john@test.test> added the comment:
894 This is a followup
896 ----------
897 status: unread -> chatting
899 _______________________________________________________________________
900 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
901 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
902 _______________________________________________________________________
904 ''')
906 def testFollowupNoNosyRecipients(self):
907 self.doNewIssue()
908 self.instance.config.ADD_RECIPIENTS_TO_NOSY = 'no'
909 self._handle_mail('''Content-Type: text/plain;
910 charset="iso-8859-1"
911 From: richard@test.test
912 To: issue_tracker@your.tracker.email.domain.example
913 Cc: john@test.test
914 Message-Id: <followup_dummy_id>
915 In-Reply-To: <dummy_test_message_id>
916 Subject: [issue1] Testing...
918 This is a followup
919 ''')
920 self.compareMessages(self._get_mail(),
921 '''FROM: roundup-admin@your.tracker.email.domain.example
922 TO: chef@bork.bork.bork
923 Content-Type: text/plain; charset="utf-8"
924 Subject: [issue1] Testing...
925 To: chef@bork.bork.bork
926 From: richard <issue_tracker@your.tracker.email.domain.example>
927 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
928 MIME-Version: 1.0
929 Message-Id: <followup_dummy_id>
930 In-Reply-To: <dummy_test_message_id>
931 X-Roundup-Name: Roundup issue tracker
932 X-Roundup-Loop: hello
933 X-Roundup-Issue-Status: chatting
934 Content-Transfer-Encoding: quoted-printable
937 richard <richard@test.test> added the comment:
939 This is a followup
941 ----------
942 status: unread -> chatting
944 _______________________________________________________________________
945 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
946 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
947 _______________________________________________________________________
949 ''')
951 def testFollowupEmptyMessage(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] Testing... [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 testFollowupEmptyMessageNoSubject(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] [assignedto=mary; nosy=+john]
982 ''')
983 l = self.db.issue.get('1', 'nosy')
984 l.sort()
985 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
986 self.john_id])
988 # should be no file created (ie. no message)
989 assert not os.path.exists(SENDMAILDEBUG)
991 def testNosyRemove(self):
992 self.doNewIssue()
994 self._handle_mail('''Content-Type: text/plain;
995 charset="iso-8859-1"
996 From: richard <richard@test.test>
997 To: issue_tracker@your.tracker.email.domain.example
998 Message-Id: <followup_dummy_id>
999 In-Reply-To: <dummy_test_message_id>
1000 Subject: [issue1] Testing... [nosy=-richard]
1002 ''')
1003 l = self.db.issue.get('1', 'nosy')
1004 l.sort()
1005 self.assertEqual(l, [self.chef_id])
1007 # NO NOSY MESSAGE SHOULD BE SENT!
1008 assert not os.path.exists(SENDMAILDEBUG)
1010 def testNewUserAuthor(self):
1012 l = self.db.user.list()
1013 l.sort()
1014 message = '''Content-Type: text/plain;
1015 charset="iso-8859-1"
1016 From: fubar <fubar@bork.bork.bork>
1017 To: issue_tracker@your.tracker.email.domain.example
1018 Message-Id: <dummy_test_message_id>
1019 Subject: [issue] Testing...
1021 This is a test submission of a new issue.
1022 '''
1023 def hook (db, **kw):
1024 ''' set up callback for db open '''
1025 db.security.role['anonymous'].permissions=[]
1026 anonid = db.user.lookup('anonymous')
1027 db.user.set(anonid, roles='Anonymous')
1028 self.instance.schema_hook = hook
1029 try:
1030 self._handle_mail(message)
1031 except Unauthorized, value:
1032 body_diff = self.compareMessages(str(value), """
1033 You are not a registered user.
1035 Unknown address: fubar@bork.bork.bork
1036 """)
1038 assert not body_diff, body_diff
1040 else:
1041 raise AssertionError, "Unathorized not raised when handling mail"
1044 def hook (db, **kw):
1045 ''' set up callback for db open '''
1046 # Add Web Access role to anonymous, and try again to make sure
1047 # we get a "please register at:" message this time.
1048 p = [
1049 db.security.getPermission('Register', 'user'),
1050 db.security.getPermission('Web Access', None),
1051 ]
1052 db.security.role['anonymous'].permissions=p
1053 self.instance.schema_hook = hook
1054 try:
1055 self._handle_mail(message)
1056 except Unauthorized, value:
1057 body_diff = self.compareMessages(str(value), """
1058 You are not a registered user. Please register at:
1060 http://tracker.example/cgi-bin/roundup.cgi/bugs/user?template=register
1062 ...before sending mail to the tracker.
1064 Unknown address: fubar@bork.bork.bork
1065 """)
1067 assert not body_diff, body_diff
1069 else:
1070 raise AssertionError, "Unathorized not raised when handling mail"
1072 # Make sure list of users is the same as before.
1073 m = self.db.user.list()
1074 m.sort()
1075 self.assertEqual(l, m)
1077 def hook (db, **kw):
1078 ''' set up callback for db open '''
1079 # now with the permission
1080 p = [
1081 db.security.getPermission('Register', 'user'),
1082 db.security.getPermission('Email Access', None),
1083 ]
1084 db.security.role['anonymous'].permissions=p
1085 self.instance.schema_hook = hook
1086 self._handle_mail(message)
1087 m = self.db.user.list()
1088 m.sort()
1089 self.assertNotEqual(l, m)
1091 def testNewUserAuthorEncodedName(self):
1092 l = set(self.db.user.list())
1093 # From: name has Euro symbol in it
1094 message = '''Content-Type: text/plain;
1095 charset="iso-8859-1"
1096 From: =?utf8?b?SOKCrGxsbw==?= <fubar@bork.bork.bork>
1097 To: issue_tracker@your.tracker.email.domain.example
1098 Message-Id: <dummy_test_message_id>
1099 Subject: [issue] Testing...
1101 This is a test submission of a new issue.
1102 '''
1103 def hook (db, **kw):
1104 ''' set up callback for db open '''
1105 p = [
1106 db.security.getPermission('Register', 'user'),
1107 db.security.getPermission('Email Access', None),
1108 db.security.getPermission('Create', 'issue'),
1109 db.security.getPermission('Create', 'msg'),
1110 ]
1111 db.security.role['anonymous'].permissions = p
1112 self.instance.schema_hook = hook
1113 self._handle_mail(message)
1114 m = set(self.db.user.list())
1115 new = list(m - l)[0]
1116 name = self.db.user.get(new, 'realname')
1117 self.assertEquals(name, 'H€llo')
1119 def testUnknownUser(self):
1120 l = set(self.db.user.list())
1121 message = '''Content-Type: text/plain;
1122 charset="iso-8859-1"
1123 From: Nonexisting User <nonexisting@bork.bork.bork>
1124 To: issue_tracker@your.tracker.email.domain.example
1125 Message-Id: <dummy_test_message_id>
1126 Subject: [issue] Testing nonexisting user...
1128 This is a test submission of a new issue.
1129 '''
1130 self.db.close()
1131 handler = self.instance.MailGW(self.instance)
1132 # we want a bounce message:
1133 handler.trapExceptions = 1
1134 ret = handler.main(StringIO(message))
1135 self.compareMessages(self._get_mail(),
1136 '''FROM: Roundup issue tracker <roundup-admin@your.tracker.email.domain.example>
1137 TO: nonexisting@bork.bork.bork
1138 From nobody Tue Jul 14 12:04:11 2009
1139 Content-Type: multipart/mixed; boundary="===============0639262320=="
1140 MIME-Version: 1.0
1141 Subject: Failed issue tracker submission
1142 To: nonexisting@bork.bork.bork
1143 From: Roundup issue tracker <roundup-admin@your.tracker.email.domain.example>
1144 Date: Tue, 14 Jul 2009 12:04:11 +0000
1145 Precedence: bulk
1146 X-Roundup-Name: Roundup issue tracker
1147 X-Roundup-Loop: hello
1148 X-Roundup-Version: 1.4.8
1149 MIME-Version: 1.0
1151 --===============0639262320==
1152 Content-Type: text/plain; charset="us-ascii"
1153 MIME-Version: 1.0
1154 Content-Transfer-Encoding: 7bit
1158 You are not a registered user. Please register at:
1160 http://tracker.example/cgi-bin/roundup.cgi/bugs/user?template=register
1162 ...before sending mail to the tracker.
1164 Unknown address: nonexisting@bork.bork.bork
1166 --===============0639262320==
1167 Content-Type: text/plain; charset="us-ascii"
1168 MIME-Version: 1.0
1169 Content-Transfer-Encoding: 7bit
1171 Content-Type: text/plain;
1172 charset="iso-8859-1"
1173 From: Nonexisting User <nonexisting@bork.bork.bork>
1174 To: issue_tracker@your.tracker.email.domain.example
1175 Message-Id: <dummy_test_message_id>
1176 Subject: [issue] Testing nonexisting user...
1178 This is a test submission of a new issue.
1180 --===============0639262320==--
1181 ''')
1183 def testEnc01(self):
1184 self.db.user.set(self.mary_id,
1185 realname='\xe4\xf6\xfc\xc4\xd6\xdc\xdf, Mary'.decode
1186 ('latin-1').encode('utf-8'))
1187 self.doNewIssue()
1188 self._handle_mail('''Content-Type: text/plain;
1189 charset="iso-8859-1"
1190 From: mary <mary@test.test>
1191 To: issue_tracker@your.tracker.email.domain.example
1192 Message-Id: <followup_dummy_id>
1193 In-Reply-To: <dummy_test_message_id>
1194 Subject: [issue1] Testing...
1195 Content-Type: text/plain;
1196 charset="iso-8859-1"
1197 Content-Transfer-Encoding: quoted-printable
1199 A message with encoding (encoded oe =F6)
1201 ''')
1202 self.compareMessages(self._get_mail(),
1203 '''FROM: roundup-admin@your.tracker.email.domain.example
1204 TO: chef@bork.bork.bork, richard@test.test
1205 Content-Type: text/plain; charset="utf-8"
1206 Subject: [issue1] Testing...
1207 To: chef@bork.bork.bork, richard@test.test
1208 From: =?utf-8?b?w6TDtsO8w4TDlsOcw58sIE1hcnk=?=
1209 <issue_tracker@your.tracker.email.domain.example>
1210 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1211 MIME-Version: 1.0
1212 Message-Id: <followup_dummy_id>
1213 In-Reply-To: <dummy_test_message_id>
1214 X-Roundup-Name: Roundup issue tracker
1215 X-Roundup-Loop: hello
1216 X-Roundup-Issue-Status: chatting
1217 Content-Transfer-Encoding: quoted-printable
1220 =C3=A4=C3=B6=C3=BC=C3=84=C3=96=C3=9C=C3=9F, Mary <mary@test.test> added the=
1221 comment:
1223 A message with encoding (encoded oe =C3=B6)
1225 ----------
1226 status: unread -> chatting
1228 _______________________________________________________________________
1229 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1230 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1231 _______________________________________________________________________
1232 ''')
1234 def testEncNonUTF8(self):
1235 self.doNewIssue()
1236 self.instance.config.EMAIL_CHARSET = 'iso-8859-1'
1237 self._handle_mail('''Content-Type: text/plain;
1238 charset="iso-8859-1"
1239 From: mary <mary@test.test>
1240 To: issue_tracker@your.tracker.email.domain.example
1241 Message-Id: <followup_dummy_id>
1242 In-Reply-To: <dummy_test_message_id>
1243 Subject: [issue1] Testing...
1244 Content-Type: text/plain;
1245 charset="iso-8859-1"
1246 Content-Transfer-Encoding: quoted-printable
1248 A message with encoding (encoded oe =F6)
1250 ''')
1251 self.compareMessages(self._get_mail(),
1252 '''FROM: roundup-admin@your.tracker.email.domain.example
1253 TO: chef@bork.bork.bork, richard@test.test
1254 Content-Type: text/plain; charset="iso-8859-1"
1255 Subject: [issue1] Testing...
1256 To: chef@bork.bork.bork, richard@test.test
1257 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
1258 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1259 MIME-Version: 1.0
1260 Message-Id: <followup_dummy_id>
1261 In-Reply-To: <dummy_test_message_id>
1262 X-Roundup-Name: Roundup issue tracker
1263 X-Roundup-Loop: hello
1264 X-Roundup-Issue-Status: chatting
1265 Content-Transfer-Encoding: quoted-printable
1268 Contrary, Mary <mary@test.test> added the comment:
1270 A message with encoding (encoded oe =F6)
1272 ----------
1273 status: unread -> chatting
1275 _______________________________________________________________________
1276 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1277 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1278 _______________________________________________________________________
1279 ''')
1282 def testMultipartEnc01(self):
1283 self.doNewIssue()
1284 self._handle_mail('''Content-Type: text/plain;
1285 charset="iso-8859-1"
1286 From: mary <mary@test.test>
1287 To: issue_tracker@your.tracker.email.domain.example
1288 Message-Id: <followup_dummy_id>
1289 In-Reply-To: <dummy_test_message_id>
1290 Subject: [issue1] Testing...
1291 Content-Type: multipart/mixed;
1292 boundary="----_=_NextPart_000_01"
1294 This message is in MIME format. Since your mail reader does not understand
1295 this format, some or all of this message may not be legible.
1297 ------_=_NextPart_000_01
1298 Content-Type: text/plain;
1299 charset="iso-8859-1"
1300 Content-Transfer-Encoding: quoted-printable
1302 A message with first part encoded (encoded oe =F6)
1304 ''')
1305 self.compareMessages(self._get_mail(),
1306 '''FROM: roundup-admin@your.tracker.email.domain.example
1307 TO: chef@bork.bork.bork, richard@test.test
1308 Content-Type: text/plain; charset="utf-8"
1309 Subject: [issue1] Testing...
1310 To: chef@bork.bork.bork, richard@test.test
1311 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
1312 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1313 MIME-Version: 1.0
1314 Message-Id: <followup_dummy_id>
1315 In-Reply-To: <dummy_test_message_id>
1316 X-Roundup-Name: Roundup issue tracker
1317 X-Roundup-Loop: hello
1318 X-Roundup-Issue-Status: chatting
1319 Content-Transfer-Encoding: quoted-printable
1322 Contrary, Mary <mary@test.test> added the comment:
1324 A message with first part encoded (encoded oe =C3=B6)
1326 ----------
1327 status: unread -> chatting
1329 _______________________________________________________________________
1330 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1331 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1332 _______________________________________________________________________
1333 ''')
1335 def testContentDisposition(self):
1336 self.doNewIssue()
1337 self._handle_mail('''Content-Type: text/plain;
1338 charset="iso-8859-1"
1339 From: mary <mary@test.test>
1340 To: issue_tracker@your.tracker.email.domain.example
1341 Message-Id: <followup_dummy_id>
1342 In-Reply-To: <dummy_test_message_id>
1343 Subject: [issue1] Testing...
1344 Content-Type: multipart/mixed; boundary="bCsyhTFzCvuiizWE"
1345 Content-Disposition: inline
1348 --bCsyhTFzCvuiizWE
1349 Content-Type: text/plain; charset=us-ascii
1350 Content-Disposition: inline
1352 test attachment binary
1354 --bCsyhTFzCvuiizWE
1355 Content-Type: application/octet-stream
1356 Content-Disposition: attachment; filename="main.dvi"
1357 Content-Transfer-Encoding: base64
1359 SnVzdCBhIHRlc3QgAQo=
1361 --bCsyhTFzCvuiizWE--
1362 ''')
1363 messages = self.db.issue.get('1', 'messages')
1364 messages.sort()
1365 file = self.db.file.getnode (self.db.msg.get(messages[-1], 'files')[0])
1366 self.assertEqual(file.name, 'main.dvi')
1367 self.assertEqual(file.content, 'Just a test \001\n')
1369 def testFollowupStupidQuoting(self):
1370 self.doNewIssue()
1372 self._handle_mail('''Content-Type: text/plain;
1373 charset="iso-8859-1"
1374 From: richard <richard@test.test>
1375 To: issue_tracker@your.tracker.email.domain.example
1376 Message-Id: <followup_dummy_id>
1377 In-Reply-To: <dummy_test_message_id>
1378 Subject: Re: "[issue1] Testing... "
1380 This is a followup
1381 ''')
1382 self.compareMessages(self._get_mail(),
1383 '''FROM: roundup-admin@your.tracker.email.domain.example
1384 TO: chef@bork.bork.bork
1385 Content-Type: text/plain; charset="utf-8"
1386 Subject: [issue1] Testing...
1387 To: chef@bork.bork.bork
1388 From: richard <issue_tracker@your.tracker.email.domain.example>
1389 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1390 MIME-Version: 1.0
1391 Message-Id: <followup_dummy_id>
1392 In-Reply-To: <dummy_test_message_id>
1393 X-Roundup-Name: Roundup issue tracker
1394 X-Roundup-Loop: hello
1395 X-Roundup-Issue-Status: chatting
1396 Content-Transfer-Encoding: quoted-printable
1399 richard <richard@test.test> added the comment:
1401 This is a followup
1403 ----------
1404 status: unread -> chatting
1406 _______________________________________________________________________
1407 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1408 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1409 _______________________________________________________________________
1410 ''')
1412 def testEmailQuoting(self):
1413 self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
1414 self.innerTestQuoting('''This is a followup
1415 ''')
1417 def testEmailQuotingRemove(self):
1418 self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
1419 self.innerTestQuoting('''Blah blah wrote:
1420 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
1421 > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
1422 >
1424 This is a followup
1425 ''')
1427 def innerTestQuoting(self, expect):
1428 nodeid = self.doNewIssue()
1430 messages = self.db.issue.get(nodeid, 'messages')
1432 self._handle_mail('''Content-Type: text/plain;
1433 charset="iso-8859-1"
1434 From: richard <richard@test.test>
1435 To: issue_tracker@your.tracker.email.domain.example
1436 Message-Id: <followup_dummy_id>
1437 In-Reply-To: <dummy_test_message_id>
1438 Subject: Re: [issue1] Testing...
1440 Blah blah wrote:
1441 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
1442 > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
1443 >
1445 This is a followup
1446 ''')
1447 # figure the new message id
1448 newmessages = self.db.issue.get(nodeid, 'messages')
1449 for msg in messages:
1450 newmessages.remove(msg)
1451 messageid = newmessages[0]
1453 self.compareMessages(self.db.msg.get(messageid, 'content'), expect)
1455 def testUserLookup(self):
1456 i = self.db.user.create(username='user1', address='user1@foo.com')
1457 self.assertEqual(uidFromAddress(self.db, ('', 'user1@foo.com'), 0), i)
1458 self.assertEqual(uidFromAddress(self.db, ('', 'USER1@foo.com'), 0), i)
1459 i = self.db.user.create(username='user2', address='USER2@foo.com')
1460 self.assertEqual(uidFromAddress(self.db, ('', 'USER2@foo.com'), 0), i)
1461 self.assertEqual(uidFromAddress(self.db, ('', 'user2@foo.com'), 0), i)
1463 def testUserAlternateLookup(self):
1464 i = self.db.user.create(username='user1', address='user1@foo.com',
1465 alternate_addresses='user1@bar.com')
1466 self.assertEqual(uidFromAddress(self.db, ('', 'user1@bar.com'), 0), i)
1467 self.assertEqual(uidFromAddress(self.db, ('', 'USER1@bar.com'), 0), i)
1469 def testUserCreate(self):
1470 i = uidFromAddress(self.db, ('', 'user@foo.com'), 1)
1471 self.assertNotEqual(uidFromAddress(self.db, ('', 'user@bar.com'), 1), i)
1473 def testRFC2822(self):
1474 ascii_header = "[issue243] This is a \"test\" - with 'quotation' marks"
1475 unicode_header = '[issue244] \xd0\xb0\xd0\xbd\xd0\xb4\xd1\x80\xd0\xb5\xd0\xb9'
1476 unicode_encoded = '=?utf-8?q?[issue244]_=D0=B0=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?='
1477 self.assertEqual(rfc2822.encode_header(ascii_header), ascii_header)
1478 self.assertEqual(rfc2822.encode_header(unicode_header), unicode_encoded)
1480 def testRegistrationConfirmation(self):
1481 otk = "Aj4euk4LZSAdwePohj90SME5SpopLETL"
1482 self.db.getOTKManager().set(otk, username='johannes')
1483 self._handle_mail('''Content-Type: text/plain;
1484 charset="iso-8859-1"
1485 From: Chef <chef@bork.bork.bork>
1486 To: issue_tracker@your.tracker.email.domain.example
1487 Cc: richard@test.test
1488 Message-Id: <dummy_test_message_id>
1489 Subject: Re: Complete your registration to Roundup issue tracker
1490 -- key %s
1492 This is a test confirmation of registration.
1493 ''' % otk)
1494 self.db.user.lookup('johannes')
1496 def testFollowupOnNonIssue(self):
1497 self.db.keyword.create(name='Foo')
1498 self._handle_mail('''Content-Type: text/plain;
1499 charset="iso-8859-1"
1500 From: richard <richard@test.test>
1501 To: issue_tracker@your.tracker.email.domain.example
1502 Message-Id: <followup_dummy_id>
1503 In-Reply-To: <dummy_test_message_id>
1504 Subject: [keyword1] Testing... [name=Bar]
1506 ''')
1507 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1509 def testResentFrom(self):
1510 nodeid = self._handle_mail('''Content-Type: text/plain;
1511 charset="iso-8859-1"
1512 From: Chef <chef@bork.bork.bork>
1513 Resent-From: mary <mary@test.test>
1514 To: issue_tracker@your.tracker.email.domain.example
1515 Cc: richard@test.test
1516 Message-Id: <dummy_test_message_id>
1517 Subject: [issue] Testing...
1519 This is a test submission of a new issue.
1520 ''')
1521 assert not os.path.exists(SENDMAILDEBUG)
1522 l = self.db.issue.get(nodeid, 'nosy')
1523 l.sort()
1524 self.assertEqual(l, [self.richard_id, self.mary_id])
1525 return nodeid
1527 def testDejaVu(self):
1528 self.assertRaises(IgnoreLoop, self._handle_mail,
1529 '''Content-Type: text/plain;
1530 charset="iso-8859-1"
1531 From: Chef <chef@bork.bork.bork>
1532 X-Roundup-Loop: hello
1533 To: issue_tracker@your.tracker.email.domain.example
1534 Cc: richard@test.test
1535 Message-Id: <dummy_test_message_id>
1536 Subject: Re: [issue] Testing...
1538 Hi, I've been mis-configured to loop messages back to myself.
1539 ''')
1541 def testItsBulkStupid(self):
1542 self.assertRaises(IgnoreBulk, self._handle_mail,
1543 '''Content-Type: text/plain;
1544 charset="iso-8859-1"
1545 From: Chef <chef@bork.bork.bork>
1546 Precedence: bulk
1547 To: issue_tracker@your.tracker.email.domain.example
1548 Cc: richard@test.test
1549 Message-Id: <dummy_test_message_id>
1550 Subject: Re: [issue] Testing...
1552 Hi, I'm on holidays, and this is a dumb auto-responder.
1553 ''')
1555 def testAutoReplyEmailsAreIgnored(self):
1556 self.assertRaises(IgnoreBulk, self._handle_mail,
1557 '''Content-Type: text/plain;
1558 charset="iso-8859-1"
1559 From: Chef <chef@bork.bork.bork>
1560 To: issue_tracker@your.tracker.email.domain.example
1561 Cc: richard@test.test
1562 Message-Id: <dummy_test_message_id>
1563 Subject: Re: [issue] Out of office AutoReply: Back next week
1565 Hi, I am back in the office next week
1566 ''')
1568 def testNoSubject(self):
1569 self.assertRaises(MailUsageError, self._handle_mail,
1570 '''Content-Type: text/plain;
1571 charset="iso-8859-1"
1572 From: Chef <chef@bork.bork.bork>
1573 To: issue_tracker@your.tracker.email.domain.example
1574 Cc: richard@test.test
1575 Reply-To: chef@bork.bork.bork
1576 Message-Id: <dummy_test_message_id>
1578 ''')
1580 #
1581 # TEST FOR INVALID DESIGNATOR HANDLING
1582 #
1583 def testInvalidDesignator(self):
1584 self.assertRaises(MailUsageError, self._handle_mail,
1585 '''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: [frobulated] testing
1590 Cc: richard@test.test
1591 Reply-To: chef@bork.bork.bork
1592 Message-Id: <dummy_test_message_id>
1594 ''')
1595 self.assertRaises(MailUsageError, self._handle_mail,
1596 '''Content-Type: text/plain;
1597 charset="iso-8859-1"
1598 From: Chef <chef@bork.bork.bork>
1599 To: issue_tracker@your.tracker.email.domain.example
1600 Subject: [issue12345] testing
1601 Cc: richard@test.test
1602 Reply-To: chef@bork.bork.bork
1603 Message-Id: <dummy_test_message_id>
1605 ''')
1607 def testInvalidClassLoose(self):
1608 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1609 nodeid = self._handle_mail('''Content-Type: text/plain;
1610 charset="iso-8859-1"
1611 From: Chef <chef@bork.bork.bork>
1612 To: issue_tracker@your.tracker.email.domain.example
1613 Subject: [frobulated] testing
1614 Cc: richard@test.test
1615 Reply-To: chef@bork.bork.bork
1616 Message-Id: <dummy_test_message_id>
1618 ''')
1619 assert not os.path.exists(SENDMAILDEBUG)
1620 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1621 '[frobulated] testing')
1623 def testInvalidClassLooseReply(self):
1624 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1625 nodeid = self._handle_mail('''Content-Type: text/plain;
1626 charset="iso-8859-1"
1627 From: Chef <chef@bork.bork.bork>
1628 To: issue_tracker@your.tracker.email.domain.example
1629 Subject: Re: [frobulated] testing
1630 Cc: richard@test.test
1631 Reply-To: chef@bork.bork.bork
1632 Message-Id: <dummy_test_message_id>
1634 ''')
1635 assert not os.path.exists(SENDMAILDEBUG)
1636 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1637 '[frobulated] testing')
1639 def testInvalidClassLoose(self):
1640 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1641 nodeid = self._handle_mail('''Content-Type: text/plain;
1642 charset="iso-8859-1"
1643 From: Chef <chef@bork.bork.bork>
1644 To: issue_tracker@your.tracker.email.domain.example
1645 Subject: [issue1234] testing
1646 Cc: richard@test.test
1647 Reply-To: chef@bork.bork.bork
1648 Message-Id: <dummy_test_message_id>
1650 ''')
1651 assert not os.path.exists(SENDMAILDEBUG)
1652 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1653 '[issue1234] testing')
1655 def testClassLooseOK(self):
1656 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1657 self.db.keyword.create(name='Foo')
1658 nodeid = 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 Subject: [keyword1] Testing... [name=Bar]
1663 Cc: richard@test.test
1664 Reply-To: chef@bork.bork.bork
1665 Message-Id: <dummy_test_message_id>
1667 ''')
1668 assert not os.path.exists(SENDMAILDEBUG)
1669 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1671 def testClassStrictInvalid(self):
1672 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'strict'
1673 self.instance.config.MAILGW_DEFAULT_CLASS = ''
1675 message = '''Content-Type: text/plain;
1676 charset="iso-8859-1"
1677 From: Chef <chef@bork.bork.bork>
1678 To: issue_tracker@your.tracker.email.domain.example
1679 Subject: Testing...
1680 Cc: richard@test.test
1681 Reply-To: chef@bork.bork.bork
1682 Message-Id: <dummy_test_message_id>
1684 '''
1685 self.assertRaises(MailUsageError, self._handle_mail, message)
1687 def testClassStrictValid(self):
1688 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'strict'
1689 self.instance.config.MAILGW_DEFAULT_CLASS = ''
1691 nodeid = 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: [issue] Testing...
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.issue.get(nodeid, 'title'), 'Testing...')
1705 #
1706 # TEST FOR INVALID COMMANDS HANDLING
1707 #
1708 def testInvalidCommands(self):
1709 self.assertRaises(MailUsageError, self._handle_mail,
1710 '''Content-Type: text/plain;
1711 charset="iso-8859-1"
1712 From: Chef <chef@bork.bork.bork>
1713 To: issue_tracker@your.tracker.email.domain.example
1714 Subject: testing [frobulated]
1715 Cc: richard@test.test
1716 Reply-To: chef@bork.bork.bork
1717 Message-Id: <dummy_test_message_id>
1719 ''')
1721 def testInvalidCommandPassthrough(self):
1722 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'none'
1723 nodeid = self._handle_mail('''Content-Type: text/plain;
1724 charset="iso-8859-1"
1725 From: Chef <chef@bork.bork.bork>
1726 To: issue_tracker@your.tracker.email.domain.example
1727 Subject: testing [frobulated]
1728 Cc: richard@test.test
1729 Reply-To: chef@bork.bork.bork
1730 Message-Id: <dummy_test_message_id>
1732 ''')
1733 assert not os.path.exists(SENDMAILDEBUG)
1734 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1735 'testing [frobulated]')
1737 def testInvalidCommandPassthroughLoose(self):
1738 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'loose'
1739 nodeid = self._handle_mail('''Content-Type: text/plain;
1740 charset="iso-8859-1"
1741 From: Chef <chef@bork.bork.bork>
1742 To: issue_tracker@your.tracker.email.domain.example
1743 Subject: testing [frobulated]
1744 Cc: richard@test.test
1745 Reply-To: chef@bork.bork.bork
1746 Message-Id: <dummy_test_message_id>
1748 ''')
1749 assert not os.path.exists(SENDMAILDEBUG)
1750 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1751 'testing [frobulated]')
1753 def testInvalidCommandPassthroughLooseOK(self):
1754 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'loose'
1755 nodeid = self._handle_mail('''Content-Type: text/plain;
1756 charset="iso-8859-1"
1757 From: Chef <chef@bork.bork.bork>
1758 To: issue_tracker@your.tracker.email.domain.example
1759 Subject: testing [assignedto=mary]
1760 Cc: richard@test.test
1761 Reply-To: chef@bork.bork.bork
1762 Message-Id: <dummy_test_message_id>
1764 ''')
1765 assert not os.path.exists(SENDMAILDEBUG)
1766 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing')
1767 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), self.mary_id)
1769 def testCommandDelimiters(self):
1770 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
1771 nodeid = self._handle_mail('''Content-Type: text/plain;
1772 charset="iso-8859-1"
1773 From: Chef <chef@bork.bork.bork>
1774 To: issue_tracker@your.tracker.email.domain.example
1775 Subject: testing {assignedto=mary}
1776 Cc: richard@test.test
1777 Reply-To: chef@bork.bork.bork
1778 Message-Id: <dummy_test_message_id>
1780 ''')
1781 assert not os.path.exists(SENDMAILDEBUG)
1782 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing')
1783 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), self.mary_id)
1785 def testPrefixDelimiters(self):
1786 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
1787 self.db.keyword.create(name='Foo')
1788 self._handle_mail('''Content-Type: text/plain;
1789 charset="iso-8859-1"
1790 From: richard <richard@test.test>
1791 To: issue_tracker@your.tracker.email.domain.example
1792 Message-Id: <followup_dummy_id>
1793 In-Reply-To: <dummy_test_message_id>
1794 Subject: {keyword1} Testing... {name=Bar}
1796 ''')
1797 assert not os.path.exists(SENDMAILDEBUG)
1798 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1800 def testCommandDelimitersIgnore(self):
1801 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
1802 nodeid = self._handle_mail('''Content-Type: text/plain;
1803 charset="iso-8859-1"
1804 From: Chef <chef@bork.bork.bork>
1805 To: issue_tracker@your.tracker.email.domain.example
1806 Subject: testing [assignedto=mary]
1807 Cc: richard@test.test
1808 Reply-To: chef@bork.bork.bork
1809 Message-Id: <dummy_test_message_id>
1811 ''')
1812 assert not os.path.exists(SENDMAILDEBUG)
1813 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1814 'testing [assignedto=mary]')
1815 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), None)
1817 def testReplytoMatch(self):
1818 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1819 nodeid = self.doNewIssue()
1820 nodeid2 = self._handle_mail('''Content-Type: text/plain;
1821 charset="iso-8859-1"
1822 From: Chef <chef@bork.bork.bork>
1823 To: issue_tracker@your.tracker.email.domain.example
1824 Message-Id: <dummy_test_message_id2>
1825 In-Reply-To: <dummy_test_message_id>
1826 Subject: Testing...
1828 Followup message.
1829 ''')
1831 nodeid3 = self._handle_mail('''Content-Type: text/plain;
1832 charset="iso-8859-1"
1833 From: Chef <chef@bork.bork.bork>
1834 To: issue_tracker@your.tracker.email.domain.example
1835 Message-Id: <dummy_test_message_id3>
1836 In-Reply-To: <dummy_test_message_id2>
1837 Subject: Testing...
1839 Yet another message in the same thread/issue.
1840 ''')
1842 self.assertEqual(nodeid, nodeid2)
1843 self.assertEqual(nodeid, nodeid3)
1845 def testHelpSubject(self):
1846 message = '''Content-Type: text/plain;
1847 charset="iso-8859-1"
1848 From: Chef <chef@bork.bork.bork>
1849 To: issue_tracker@your.tracker.email.domain.example
1850 Message-Id: <dummy_test_message_id2>
1851 In-Reply-To: <dummy_test_message_id>
1852 Subject: hElp
1855 '''
1856 self.assertRaises(MailUsageHelp, self._handle_mail, message)
1858 def testMaillistSubject(self):
1859 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '[]'
1860 self.db.keyword.create(name='Foo')
1861 self._handle_mail('''Content-Type: text/plain;
1862 charset="iso-8859-1"
1863 From: Chef <chef@bork.bork.bork>
1864 To: issue_tracker@your.tracker.email.domain.example
1865 Subject: [mailinglist-name] [keyword1] Testing.. [name=Bar]
1866 Cc: richard@test.test
1867 Reply-To: chef@bork.bork.bork
1868 Message-Id: <dummy_test_message_id>
1870 ''')
1872 assert not os.path.exists(SENDMAILDEBUG)
1873 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1875 def testUnknownPrefixSubject(self):
1876 self.db.keyword.create(name='Foo')
1877 self._handle_mail('''Content-Type: text/plain;
1878 charset="iso-8859-1"
1879 From: Chef <chef@bork.bork.bork>
1880 To: issue_tracker@your.tracker.email.domain.example
1881 Subject: VeryStrangeRe: [keyword1] Testing.. [name=Bar]
1882 Cc: richard@test.test
1883 Reply-To: chef@bork.bork.bork
1884 Message-Id: <dummy_test_message_id>
1886 ''')
1888 assert not os.path.exists(SENDMAILDEBUG)
1889 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1891 def testIssueidLast(self):
1892 nodeid1 = self.doNewIssue()
1893 nodeid2 = self._handle_mail('''Content-Type: text/plain;
1894 charset="iso-8859-1"
1895 From: mary <mary@test.test>
1896 To: issue_tracker@your.tracker.email.domain.example
1897 Message-Id: <followup_dummy_id>
1898 In-Reply-To: <dummy_test_message_id>
1899 Subject: New title [issue1]
1901 This is a second followup
1902 ''')
1904 assert nodeid1 == nodeid2
1905 self.assertEqual(self.db.issue.get(nodeid2, 'title'), "Testing...")
1907 def testSecurityMessagePermissionContent(self):
1908 id = self.doNewIssue()
1909 issue = self.db.issue.getnode (id)
1910 self.db.security.addRole(name='Nomsg')
1911 self.db.security.addPermissionToRole('Nomsg', 'Email Access')
1912 for cl in 'issue', 'file', 'keyword':
1913 for p in 'View', 'Edit', 'Create':
1914 self.db.security.addPermissionToRole('Nomsg', p, cl)
1915 self.db.user.set(self.mary_id, roles='Nomsg')
1916 nodeid = self._handle_mail('''Content-Type: text/plain;
1917 charset="iso-8859-1"
1918 From: Chef <chef@bork.bork.bork>
1919 To: issue_tracker@your.tracker.email.domain.example
1920 Message-Id: <dummy_test_message_id>
1921 Subject: [issue%(id)s] Testing... [nosy=+mary]
1923 Just a test reply
1924 '''%locals())
1925 assert os.path.exists(SENDMAILDEBUG)
1926 self.compareMessages(self._get_mail(),
1927 '''FROM: roundup-admin@your.tracker.email.domain.example
1928 TO: chef@bork.bork.bork, richard@test.test
1929 Content-Type: text/plain; charset="utf-8"
1930 Subject: [issue1] Testing...
1931 To: richard@test.test
1932 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
1933 Reply-To: Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1934 MIME-Version: 1.0
1935 Message-Id: <dummy_test_message_id>
1936 X-Roundup-Name: Roundup issue tracker
1937 X-Roundup-Loop: hello
1938 X-Roundup-Issue-Status: chatting
1939 Content-Transfer-Encoding: quoted-printable
1942 Bork, Chef <chef@bork.bork.bork> added the comment:
1944 Just a test reply
1946 ----------
1947 nosy: +mary
1948 status: unread -> chatting
1950 _______________________________________________________________________
1951 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1952 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1953 _______________________________________________________________________
1954 ''')
1957 def test_suite():
1958 suite = unittest.TestSuite()
1959 suite.addTest(unittest.makeSuite(MailgwTestCase))
1960 return suite
1962 if __name__ == '__main__':
1963 runner = unittest.TextTestRunner()
1964 unittest.main(testRunner=runner)
1966 # vim: set filetype=python sts=4 sw=4 et si :