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
30 import memorydb
32 class Message(rfc822.Message):
33 """String-based Message class with equivalence test."""
34 def __init__(self, s):
35 rfc822.Message.__init__(self, StringIO(s.strip()))
37 def __eq__(self, other):
38 return (self.dict == other.dict and
39 self.fp.read() == other.fp.read())
41 class Tracker(object):
42 def open(self, journaltag):
43 return self.db
45 class DiffHelper:
46 def compareMessages(self, new, old):
47 """Compare messages for semantic equivalence."""
48 new, old = Message(new), Message(old)
50 # all Roundup-generated messages have "Precedence: bulk"
51 old['Precedence'] = 'bulk'
53 # don't try to compare the date
54 del new['date'], old['date']
56 if not new == old:
57 res = []
59 replace = {}
60 for key in new.keys():
61 if key.startswith('from '):
62 # skip the unix from line
63 continue
64 if key.lower() == 'x-roundup-version':
65 # version changes constantly, so handle it specially
66 if new[key] != __version__:
67 res.append(' %s: %r != %r' % (key, __version__,
68 new[key]))
69 elif key.lower() == 'content-type' and 'boundary=' in new[key]:
70 # handle mime messages
71 newmime = new[key].split('=',1)[-1].strip('"')
72 oldmime = old.get(key, '').split('=',1)[-1].strip('"')
73 replace ['--' + newmime] = '--' + oldmime
74 replace ['--' + newmime + '--'] = '--' + oldmime + '--'
75 elif new.get(key, '') != old.get(key, ''):
76 res.append(' %s: %r != %r' % (key, old.get(key, ''),
77 new.get(key, '')))
79 body_diff = self.compareStrings(new.fp.read(), old.fp.read(),
80 replace=replace)
81 if body_diff:
82 res.append('')
83 res.extend(body_diff)
85 if res:
86 res.insert(0, 'Generated message not correct (diff follows, expected vs. actual):')
87 raise AssertionError, '\n'.join(res)
89 def compareStrings(self, s2, s1, replace={}):
90 '''Note the reversal of s2 and s1 - difflib.SequenceMatcher wants
91 the first to be the "original" but in the calls in this file,
92 the second arg is the original. Ho hum.
93 Do replacements over the replace dict -- used for mime boundary
94 '''
95 l1 = s1.strip().split('\n')
96 l2 = [replace.get(i,i) for i in s2.strip().split('\n')]
97 if l1 == l2:
98 return
99 s = difflib.SequenceMatcher(None, l1, l2)
100 res = []
101 for value, s1s, s1e, s2s, s2e in s.get_opcodes():
102 if value == 'equal':
103 for i in range(s1s, s1e):
104 res.append(' %s'%l1[i])
105 elif value == 'delete':
106 for i in range(s1s, s1e):
107 res.append('- %s'%l1[i])
108 elif value == 'insert':
109 for i in range(s2s, s2e):
110 res.append('+ %s'%l2[i])
111 elif value == 'replace':
112 for i, j in zip(range(s1s, s1e), range(s2s, s2e)):
113 res.append('- %s'%l1[i])
114 res.append('+ %s'%l2[j])
116 return res
118 class MailgwTestCase(unittest.TestCase, DiffHelper):
119 count = 0
120 schema = 'classic'
121 def setUp(self):
122 MailgwTestCase.count = MailgwTestCase.count + 1
124 # and open the database / "instance"
125 self.db = memorydb.create('admin')
126 self.instance = Tracker()
127 self.instance.db = self.db
128 self.instance.config = self.db.config
129 self.instance.MailGW = MailGW
131 self.chef_id = self.db.user.create(username='Chef',
132 address='chef@bork.bork.bork', realname='Bork, Chef', roles='User')
133 self.richard_id = self.db.user.create(username='richard',
134 address='richard@test.test', roles='User')
135 self.mary_id = self.db.user.create(username='mary',
136 address='mary@test.test', roles='User', realname='Contrary, Mary')
137 self.john_id = self.db.user.create(username='john',
138 address='john@test.test', roles='User', realname='John Doe',
139 alternate_addresses='jondoe@test.test\njohn.doe@test.test')
141 def tearDown(self):
142 if os.path.exists(SENDMAILDEBUG):
143 os.remove(SENDMAILDEBUG)
144 self.db.close()
146 def _create_mailgw(self, message):
147 class MailGW(self.instance.MailGW):
148 def handle_message(self, message):
149 return self._handle_message(message)
150 handler = MailGW(self.instance)
151 handler.db = self.db
152 return handler
154 def _handle_mail(self, message):
155 handler = self._create_mailgw(message)
156 handler.trapExceptions = 0
157 return handler.main(StringIO(message))
159 def _get_mail(self):
160 f = open(SENDMAILDEBUG)
161 try:
162 return f.read()
163 finally:
164 f.close()
166 def testEmptyMessage(self):
167 nodeid = self._handle_mail('''Content-Type: text/plain;
168 charset="iso-8859-1"
169 From: Chef <chef@bork.bork.bork>
170 To: issue_tracker@your.tracker.email.domain.example
171 Cc: richard@test.test
172 Reply-To: chef@bork.bork.bork
173 Message-Id: <dummy_test_message_id>
174 Subject: [issue] Testing...
176 ''')
177 assert not os.path.exists(SENDMAILDEBUG)
178 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
180 def testMessageWithFromInIt(self):
181 nodeid = self._handle_mail('''Content-Type: text/plain;
182 charset="iso-8859-1"
183 From: Chef <chef@bork.bork.bork>
184 To: issue_tracker@your.tracker.email.domain.example
185 Cc: richard@test.test
186 Reply-To: chef@bork.bork.bork
187 Message-Id: <dummy_test_message_id>
188 Subject: [issue] Testing...
190 From here to there!
191 ''')
192 assert not os.path.exists(SENDMAILDEBUG)
193 msgid = self.db.issue.get(nodeid, 'messages')[0]
194 self.assertEqual(self.db.msg.get(msgid, 'content'), 'From here to there!')
196 def doNewIssue(self):
197 nodeid = self._handle_mail('''Content-Type: text/plain;
198 charset="iso-8859-1"
199 From: Chef <chef@bork.bork.bork>
200 To: issue_tracker@your.tracker.email.domain.example
201 Cc: richard@test.test
202 Message-Id: <dummy_test_message_id>
203 Subject: [issue] Testing...
205 This is a test submission of a new issue.
206 ''')
207 assert not os.path.exists(SENDMAILDEBUG)
208 l = self.db.issue.get(nodeid, 'nosy')
209 l.sort()
210 self.assertEqual(l, [self.chef_id, self.richard_id])
211 return nodeid
213 def testNewIssue(self):
214 self.doNewIssue()
216 def testNewIssueNosy(self):
217 self.instance.config.ADD_AUTHOR_TO_NOSY = 'yes'
218 nodeid = self._handle_mail('''Content-Type: text/plain;
219 charset="iso-8859-1"
220 From: Chef <chef@bork.bork.bork>
221 To: issue_tracker@your.tracker.email.domain.example
222 Cc: richard@test.test
223 Message-Id: <dummy_test_message_id>
224 Subject: [issue] Testing...
226 This is a test submission of a new issue.
227 ''')
228 assert not os.path.exists(SENDMAILDEBUG)
229 l = self.db.issue.get(nodeid, 'nosy')
230 l.sort()
231 self.assertEqual(l, [self.chef_id, self.richard_id])
233 def testAlternateAddress(self):
234 self._handle_mail('''Content-Type: text/plain;
235 charset="iso-8859-1"
236 From: John Doe <john.doe@test.test>
237 To: issue_tracker@your.tracker.email.domain.example
238 Message-Id: <dummy_test_message_id>
239 Subject: [issue] Testing...
241 This is a test submission of a new issue.
242 ''')
243 userlist = self.db.user.list()
244 assert not os.path.exists(SENDMAILDEBUG)
245 self.assertEqual(userlist, self.db.user.list(),
246 "user created when it shouldn't have been")
248 def testNewIssueNoClass(self):
249 self._handle_mail('''Content-Type: text/plain;
250 charset="iso-8859-1"
251 From: Chef <chef@bork.bork.bork>
252 To: issue_tracker@your.tracker.email.domain.example
253 Cc: richard@test.test
254 Message-Id: <dummy_test_message_id>
255 Subject: Testing...
257 This is a test submission of a new issue.
258 ''')
259 assert not os.path.exists(SENDMAILDEBUG)
261 def testNewIssueAuthMsg(self):
262 # TODO: fix the damn config - this is apalling
263 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
264 self._handle_mail('''Content-Type: text/plain;
265 charset="iso-8859-1"
266 From: Chef <chef@bork.bork.bork>
267 To: issue_tracker@your.tracker.email.domain.example
268 Message-Id: <dummy_test_message_id>
269 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
271 This is a test submission of a new issue.
272 ''')
273 self.compareMessages(self._get_mail(),
274 '''FROM: roundup-admin@your.tracker.email.domain.example
275 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
276 Content-Type: text/plain; charset="utf-8"
277 Subject: [issue1] Testing...
278 To: chef@bork.bork.bork, mary@test.test, richard@test.test
279 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
280 Reply-To: Roundup issue tracker
281 <issue_tracker@your.tracker.email.domain.example>
282 MIME-Version: 1.0
283 Message-Id: <dummy_test_message_id>
284 X-Roundup-Name: Roundup issue tracker
285 X-Roundup-Loop: hello
286 X-Roundup-Issue-Status: unread
287 Content-Transfer-Encoding: quoted-printable
290 New submission from Bork, Chef <chef@bork.bork.bork>:
292 This is a test submission of a new issue.
294 ----------
295 assignedto: richard
296 messages: 1
297 nosy: Chef, mary, richard
298 status: unread
299 title: Testing...
301 _______________________________________________________________________
302 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
303 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
304 _______________________________________________________________________
305 ''')
307 def testNewIssueNoAuthorInfo(self):
308 self.db.config.MAIL_ADD_AUTHORINFO = 'no'
309 self._handle_mail('''Content-Type: text/plain;
310 charset="iso-8859-1"
311 From: Chef <chef@bork.bork.bork>
312 To: issue_tracker@your.tracker.email.domain.example
313 Message-Id: <dummy_test_message_id>
314 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
316 This is a test submission of a new issue.
317 ''')
318 self.compareMessages(self._get_mail(),
319 '''FROM: roundup-admin@your.tracker.email.domain.example
320 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
321 Content-Type: text/plain; charset="utf-8"
322 Subject: [issue1] Testing...
323 To: mary@test.test, richard@test.test
324 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
325 Reply-To: Roundup issue tracker
326 <issue_tracker@your.tracker.email.domain.example>
327 MIME-Version: 1.0
328 Message-Id: <dummy_test_message_id>
329 X-Roundup-Name: Roundup issue tracker
330 X-Roundup-Loop: hello
331 X-Roundup-Issue-Status: unread
332 Content-Transfer-Encoding: quoted-printable
334 This is a test submission of a new issue.
336 ----------
337 assignedto: richard
338 messages: 1
339 nosy: Chef, mary, richard
340 status: unread
341 title: Testing...
343 _______________________________________________________________________
344 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
345 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
346 _______________________________________________________________________
347 ''')
349 def testNewIssueNoAuthorEmail(self):
350 self.db.config.MAIL_ADD_AUTHOREMAIL = 'no'
351 self._handle_mail('''Content-Type: text/plain;
352 charset="iso-8859-1"
353 From: Chef <chef@bork.bork.bork>
354 To: issue_tracker@your.tracker.email.domain.example
355 Message-Id: <dummy_test_message_id>
356 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
358 This is a test submission of a new issue.
359 ''')
360 self.compareMessages(self._get_mail(),
361 '''FROM: roundup-admin@your.tracker.email.domain.example
362 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
363 Content-Type: text/plain; charset="utf-8"
364 Subject: [issue1] Testing...
365 To: mary@test.test, richard@test.test
366 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
367 Reply-To: Roundup issue tracker
368 <issue_tracker@your.tracker.email.domain.example>
369 MIME-Version: 1.0
370 Message-Id: <dummy_test_message_id>
371 X-Roundup-Name: Roundup issue tracker
372 X-Roundup-Loop: hello
373 X-Roundup-Issue-Status: unread
374 Content-Transfer-Encoding: quoted-printable
376 New submission from Bork, Chef:
378 This is a test submission of a new issue.
380 ----------
381 assignedto: richard
382 messages: 1
383 nosy: Chef, mary, richard
384 status: unread
385 title: Testing...
387 _______________________________________________________________________
388 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
389 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
390 _______________________________________________________________________
391 ''')
393 multipart_msg = '''From: mary <mary@test.test>
394 To: issue_tracker@your.tracker.email.domain.example
395 Message-Id: <followup_dummy_id>
396 In-Reply-To: <dummy_test_message_id>
397 Subject: [issue1] Testing...
398 Content-Type: multipart/mixed; boundary="bxyzzy"
399 Content-Disposition: inline
402 --bxyzzy
403 Content-Type: multipart/alternative; boundary="bCsyhTFzCvuiizWE"
404 Content-Disposition: inline
406 --bCsyhTFzCvuiizWE
407 Content-Type: text/plain; charset=us-ascii
408 Content-Disposition: inline
410 test attachment first text/plain
412 --bCsyhTFzCvuiizWE
413 Content-Type: application/octet-stream
414 Content-Disposition: attachment; filename="first.dvi"
415 Content-Transfer-Encoding: base64
417 SnVzdCBhIHRlc3QgAQo=
419 --bCsyhTFzCvuiizWE
420 Content-Type: text/plain; charset=us-ascii
421 Content-Disposition: inline
423 test attachment second text/plain
425 --bCsyhTFzCvuiizWE
426 Content-Type: text/html
427 Content-Disposition: inline
429 <html>
430 to be ignored.
431 </html>
433 --bCsyhTFzCvuiizWE--
435 --bxyzzy
436 Content-Type: multipart/alternative; boundary="bCsyhTFzCvuiizWF"
437 Content-Disposition: inline
439 --bCsyhTFzCvuiizWF
440 Content-Type: text/plain; charset=us-ascii
441 Content-Disposition: inline
443 test attachment third text/plain
445 --bCsyhTFzCvuiizWF
446 Content-Type: application/octet-stream
447 Content-Disposition: attachment; filename="second.dvi"
448 Content-Transfer-Encoding: base64
450 SnVzdCBhIHRlc3QK
452 --bCsyhTFzCvuiizWF--
454 --bxyzzy--
455 '''
457 def testMultipartKeepAlternatives(self):
458 self.doNewIssue()
459 self._handle_mail(self.multipart_msg)
460 messages = self.db.issue.get('1', 'messages')
461 messages.sort()
462 msg = self.db.msg.getnode (messages[-1])
463 assert(len(msg.files) == 5)
464 names = {0 : 'first.dvi', 4 : 'second.dvi'}
465 content = {3 : 'test attachment third text/plain\n',
466 4 : 'Just a test\n'}
467 for n, id in enumerate (msg.files):
468 f = self.db.file.getnode (id)
469 self.assertEqual(f.name, names.get (n, 'unnamed'))
470 if n in content :
471 self.assertEqual(f.content, content [n])
472 self.assertEqual(msg.content, 'test attachment second text/plain')
474 def testMultipartDropAlternatives(self):
475 self.doNewIssue()
476 self.db.config.MAILGW_IGNORE_ALTERNATIVES = True
477 self._handle_mail(self.multipart_msg)
478 messages = self.db.issue.get('1', 'messages')
479 messages.sort()
480 msg = self.db.msg.getnode (messages[-1])
481 assert(len(msg.files) == 2)
482 names = {1 : 'second.dvi'}
483 content = {0 : 'test attachment third text/plain\n',
484 1 : 'Just a test\n'}
485 for n, id in enumerate (msg.files):
486 f = self.db.file.getnode (id)
487 self.assertEqual(f.name, names.get (n, 'unnamed'))
488 if n in content :
489 self.assertEqual(f.content, content [n])
490 self.assertEqual(msg.content, 'test attachment second text/plain')
492 def testSimpleFollowup(self):
493 self.doNewIssue()
494 self._handle_mail('''Content-Type: text/plain;
495 charset="iso-8859-1"
496 From: mary <mary@test.test>
497 To: issue_tracker@your.tracker.email.domain.example
498 Message-Id: <followup_dummy_id>
499 In-Reply-To: <dummy_test_message_id>
500 Subject: [issue1] Testing...
502 This is a second followup
503 ''')
504 self.compareMessages(self._get_mail(),
505 '''FROM: roundup-admin@your.tracker.email.domain.example
506 TO: chef@bork.bork.bork, richard@test.test
507 Content-Type: text/plain; charset="utf-8"
508 Subject: [issue1] Testing...
509 To: chef@bork.bork.bork, richard@test.test
510 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
511 Reply-To: Roundup issue tracker
512 <issue_tracker@your.tracker.email.domain.example>
513 MIME-Version: 1.0
514 Message-Id: <followup_dummy_id>
515 In-Reply-To: <dummy_test_message_id>
516 X-Roundup-Name: Roundup issue tracker
517 X-Roundup-Loop: hello
518 X-Roundup-Issue-Status: chatting
519 Content-Transfer-Encoding: quoted-printable
522 Contrary, Mary <mary@test.test> added the comment:
524 This is a second followup
526 ----------
527 status: unread -> chatting
529 _______________________________________________________________________
530 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
531 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
532 _______________________________________________________________________
533 ''')
535 def testFollowup(self):
536 self.doNewIssue()
538 self._handle_mail('''Content-Type: text/plain;
539 charset="iso-8859-1"
540 From: richard <richard@test.test>
541 To: issue_tracker@your.tracker.email.domain.example
542 Message-Id: <followup_dummy_id>
543 In-Reply-To: <dummy_test_message_id>
544 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
546 This is a followup
547 ''')
548 l = self.db.issue.get('1', 'nosy')
549 l.sort()
550 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
551 self.john_id])
553 self.compareMessages(self._get_mail(),
554 '''FROM: roundup-admin@your.tracker.email.domain.example
555 TO: chef@bork.bork.bork, john@test.test, mary@test.test
556 Content-Type: text/plain; charset="utf-8"
557 Subject: [issue1] Testing...
558 To: chef@bork.bork.bork, john@test.test, mary@test.test
559 From: richard <issue_tracker@your.tracker.email.domain.example>
560 Reply-To: Roundup issue tracker
561 <issue_tracker@your.tracker.email.domain.example>
562 MIME-Version: 1.0
563 Message-Id: <followup_dummy_id>
564 In-Reply-To: <dummy_test_message_id>
565 X-Roundup-Name: Roundup issue tracker
566 X-Roundup-Loop: hello
567 X-Roundup-Issue-Status: chatting
568 Content-Transfer-Encoding: quoted-printable
571 richard <richard@test.test> added the comment:
573 This is a followup
575 ----------
576 assignedto: -> mary
577 nosy: +john, mary
578 status: unread -> chatting
580 _______________________________________________________________________
581 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
582 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
583 _______________________________________________________________________
584 ''')
586 def testNosyGeneration(self):
587 self.db.issue.create(title='test')
589 # create a nosy message
590 msg = self.db.msg.create(content='This is a test',
591 author=self.richard_id, messageid='<dummy_test_message_id>')
592 self.db.journaltag = 'richard'
593 l = self.db.issue.create(title='test', messages=[msg],
594 nosy=[self.chef_id, self.mary_id, self.john_id])
596 self.compareMessages(self._get_mail(),
597 '''FROM: roundup-admin@your.tracker.email.domain.example
598 TO: chef@bork.bork.bork, john@test.test, mary@test.test
599 Content-Type: text/plain; charset="utf-8"
600 Subject: [issue2] test
601 To: chef@bork.bork.bork, john@test.test, mary@test.test
602 From: richard <issue_tracker@your.tracker.email.domain.example>
603 Reply-To: Roundup issue tracker
604 <issue_tracker@your.tracker.email.domain.example>
605 MIME-Version: 1.0
606 Message-Id: <dummy_test_message_id>
607 X-Roundup-Name: Roundup issue tracker
608 X-Roundup-Loop: hello
609 X-Roundup-Issue-Status: unread
610 Content-Transfer-Encoding: quoted-printable
613 New submission from richard <richard@test.test>:
615 This is a test
617 ----------
618 messages: 1
619 nosy: Chef, john, mary, richard
620 status: unread
621 title: test
623 _______________________________________________________________________
624 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
625 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue2>
626 _______________________________________________________________________
627 ''')
629 def testPropertyChangeOnly(self):
630 self.doNewIssue()
631 oldvalues = self.db.getnode('issue', '1').copy()
632 oldvalues['assignedto'] = None
633 # reconstruct old behaviour: This would reuse the
634 # database-handle from the doNewIssue above which has committed
635 # as user "Chef". So we close and reopen the db as that user.
636 #self.db.close() actually don't close 'cos this empties memorydb
637 self.db = self.instance.open('Chef')
638 self.db.issue.set('1', assignedto=self.chef_id)
639 self.db.commit()
640 self.db.issue.nosymessage('1', None, oldvalues)
642 new_mail = ""
643 for line in self._get_mail().split("\n"):
644 if "Message-Id: " in line:
645 continue
646 if "Date: " in line:
647 continue
648 new_mail += line+"\n"
650 self.compareMessages(new_mail, """
651 FROM: roundup-admin@your.tracker.email.domain.example
652 TO: chef@bork.bork.bork, richard@test.test
653 Content-Type: text/plain; charset="utf-8"
654 Subject: [issue1] Testing...
655 To: chef@bork.bork.bork, richard@test.test
656 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
657 X-Roundup-Name: Roundup issue tracker
658 X-Roundup-Loop: hello
659 X-Roundup-Issue-Status: unread
660 X-Roundup-Version: 1.3.3
661 In-Reply-To: <dummy_test_message_id>
662 MIME-Version: 1.0
663 Reply-To: Roundup issue tracker
664 <issue_tracker@your.tracker.email.domain.example>
665 Content-Transfer-Encoding: quoted-printable
668 Change by Bork, Chef <chef@bork.bork.bork>:
671 ----------
672 assignedto: -> Chef
674 _______________________________________________________________________
675 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
676 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
677 _______________________________________________________________________
678 """)
681 #
682 # FOLLOWUP TITLE MATCH
683 #
684 def testFollowupTitleMatch(self):
685 self.doNewIssue()
686 self._handle_mail('''Content-Type: text/plain;
687 charset="iso-8859-1"
688 From: richard <richard@test.test>
689 To: issue_tracker@your.tracker.email.domain.example
690 Message-Id: <followup_dummy_id>
691 Subject: Re: Testing... [assignedto=mary; nosy=+john]
693 This is a followup
694 ''')
695 self.compareMessages(self._get_mail(),
696 '''FROM: roundup-admin@your.tracker.email.domain.example
697 TO: chef@bork.bork.bork, john@test.test, mary@test.test
698 Content-Type: text/plain; charset="utf-8"
699 Subject: [issue1] Testing...
700 To: chef@bork.bork.bork, john@test.test, mary@test.test
701 From: richard <issue_tracker@your.tracker.email.domain.example>
702 Reply-To: Roundup issue tracker
703 <issue_tracker@your.tracker.email.domain.example>
704 MIME-Version: 1.0
705 Message-Id: <followup_dummy_id>
706 In-Reply-To: <dummy_test_message_id>
707 X-Roundup-Name: Roundup issue tracker
708 X-Roundup-Loop: hello
709 X-Roundup-Issue-Status: chatting
710 Content-Transfer-Encoding: quoted-printable
713 richard <richard@test.test> added the comment:
715 This is a followup
717 ----------
718 assignedto: -> mary
719 nosy: +john, mary
720 status: unread -> chatting
722 _______________________________________________________________________
723 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
724 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
725 _______________________________________________________________________
726 ''')
728 def testFollowupTitleMatchMultiRe(self):
729 nodeid1 = self.doNewIssue()
730 nodeid2 = self._handle_mail('''Content-Type: text/plain;
731 charset="iso-8859-1"
732 From: richard <richard@test.test>
733 To: issue_tracker@your.tracker.email.domain.example
734 Message-Id: <followup_dummy_id>
735 Subject: Re: Testing... [assignedto=mary; nosy=+john]
737 This is a followup
738 ''')
740 nodeid3 = self._handle_mail('''Content-Type: text/plain;
741 charset="iso-8859-1"
742 From: richard <richard@test.test>
743 To: issue_tracker@your.tracker.email.domain.example
744 Message-Id: <followup2_dummy_id>
745 Subject: Ang: Re: Testing...
747 This is a followup
748 ''')
749 self.assertEqual(nodeid1, nodeid2)
750 self.assertEqual(nodeid1, nodeid3)
752 def testFollowupTitleMatchNever(self):
753 nodeid = self.doNewIssue()
754 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'never'
755 self.assertNotEqual(self._handle_mail('''Content-Type: text/plain;
756 charset="iso-8859-1"
757 From: richard <richard@test.test>
758 To: issue_tracker@your.tracker.email.domain.example
759 Message-Id: <followup_dummy_id>
760 Subject: Re: Testing...
762 This is a followup
763 '''), nodeid)
765 def testFollowupTitleMatchNeverInterval(self):
766 nodeid = self.doNewIssue()
767 # force failure of the interval
768 time.sleep(2)
769 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation 00:00:01'
770 self.assertNotEqual(self._handle_mail('''Content-Type: text/plain;
771 charset="iso-8859-1"
772 From: richard <richard@test.test>
773 To: issue_tracker@your.tracker.email.domain.example
774 Message-Id: <followup_dummy_id>
775 Subject: Re: Testing...
777 This is a followup
778 '''), nodeid)
781 def testFollowupTitleMatchInterval(self):
782 nodeid = self.doNewIssue()
783 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation +1d'
784 self.assertEqual(self._handle_mail('''Content-Type: text/plain;
785 charset="iso-8859-1"
786 From: richard <richard@test.test>
787 To: issue_tracker@your.tracker.email.domain.example
788 Message-Id: <followup_dummy_id>
789 Subject: Re: Testing...
791 This is a followup
792 '''), nodeid)
795 def testFollowupNosyAuthor(self):
796 self.doNewIssue()
797 self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
798 self._handle_mail('''Content-Type: text/plain;
799 charset="iso-8859-1"
800 From: john@test.test
801 To: issue_tracker@your.tracker.email.domain.example
802 Message-Id: <followup_dummy_id>
803 In-Reply-To: <dummy_test_message_id>
804 Subject: [issue1] Testing...
806 This is a followup
807 ''')
809 self.compareMessages(self._get_mail(),
810 '''FROM: roundup-admin@your.tracker.email.domain.example
811 TO: chef@bork.bork.bork, richard@test.test
812 Content-Type: text/plain; charset="utf-8"
813 Subject: [issue1] Testing...
814 To: chef@bork.bork.bork, richard@test.test
815 From: John Doe <issue_tracker@your.tracker.email.domain.example>
816 Reply-To: Roundup issue tracker
817 <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 testFollowupNosyRecipients(self):
843 self.doNewIssue()
844 self.db.config.ADD_RECIPIENTS_TO_NOSY = 'yes'
845 self._handle_mail('''Content-Type: text/plain;
846 charset="iso-8859-1"
847 From: richard@test.test
848 To: issue_tracker@your.tracker.email.domain.example
849 Cc: john@test.test
850 Message-Id: <followup_dummy_id>
851 In-Reply-To: <dummy_test_message_id>
852 Subject: [issue1] Testing...
854 This is a followup
855 ''')
856 self.compareMessages(self._get_mail(),
857 '''FROM: roundup-admin@your.tracker.email.domain.example
858 TO: chef@bork.bork.bork
859 Content-Type: text/plain; charset="utf-8"
860 Subject: [issue1] Testing...
861 To: chef@bork.bork.bork
862 From: richard <issue_tracker@your.tracker.email.domain.example>
863 Reply-To: Roundup issue tracker
864 <issue_tracker@your.tracker.email.domain.example>
865 MIME-Version: 1.0
866 Message-Id: <followup_dummy_id>
867 In-Reply-To: <dummy_test_message_id>
868 X-Roundup-Name: Roundup issue tracker
869 X-Roundup-Loop: hello
870 X-Roundup-Issue-Status: chatting
871 Content-Transfer-Encoding: quoted-printable
874 richard <richard@test.test> added the comment:
876 This is a followup
878 ----------
879 nosy: +john
880 status: unread -> chatting
882 _______________________________________________________________________
883 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
884 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
885 _______________________________________________________________________
887 ''')
889 def testFollowupNosyAuthorAndCopy(self):
890 self.doNewIssue()
891 self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
892 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
893 self._handle_mail('''Content-Type: text/plain;
894 charset="iso-8859-1"
895 From: john@test.test
896 To: issue_tracker@your.tracker.email.domain.example
897 Message-Id: <followup_dummy_id>
898 In-Reply-To: <dummy_test_message_id>
899 Subject: [issue1] Testing...
901 This is a followup
902 ''')
903 self.compareMessages(self._get_mail(),
904 '''FROM: roundup-admin@your.tracker.email.domain.example
905 TO: chef@bork.bork.bork, john@test.test, richard@test.test
906 Content-Type: text/plain; charset="utf-8"
907 Subject: [issue1] Testing...
908 To: chef@bork.bork.bork, john@test.test, richard@test.test
909 From: John Doe <issue_tracker@your.tracker.email.domain.example>
910 Reply-To: Roundup issue tracker
911 <issue_tracker@your.tracker.email.domain.example>
912 MIME-Version: 1.0
913 Message-Id: <followup_dummy_id>
914 In-Reply-To: <dummy_test_message_id>
915 X-Roundup-Name: Roundup issue tracker
916 X-Roundup-Loop: hello
917 X-Roundup-Issue-Status: chatting
918 Content-Transfer-Encoding: quoted-printable
921 John Doe <john@test.test> added the comment:
923 This is a followup
925 ----------
926 nosy: +john
927 status: unread -> chatting
929 _______________________________________________________________________
930 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
931 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
932 _______________________________________________________________________
934 ''')
936 def testFollowupNoNosyAuthor(self):
937 self.doNewIssue()
938 self.instance.config.ADD_AUTHOR_TO_NOSY = 'no'
939 self._handle_mail('''Content-Type: text/plain;
940 charset="iso-8859-1"
941 From: john@test.test
942 To: issue_tracker@your.tracker.email.domain.example
943 Message-Id: <followup_dummy_id>
944 In-Reply-To: <dummy_test_message_id>
945 Subject: [issue1] Testing...
947 This is a followup
948 ''')
949 self.compareMessages(self._get_mail(),
950 '''FROM: roundup-admin@your.tracker.email.domain.example
951 TO: chef@bork.bork.bork, richard@test.test
952 Content-Type: text/plain; charset="utf-8"
953 Subject: [issue1] Testing...
954 To: chef@bork.bork.bork, richard@test.test
955 From: John Doe <issue_tracker@your.tracker.email.domain.example>
956 Reply-To: Roundup issue tracker
957 <issue_tracker@your.tracker.email.domain.example>
958 MIME-Version: 1.0
959 Message-Id: <followup_dummy_id>
960 In-Reply-To: <dummy_test_message_id>
961 X-Roundup-Name: Roundup issue tracker
962 X-Roundup-Loop: hello
963 X-Roundup-Issue-Status: chatting
964 Content-Transfer-Encoding: quoted-printable
967 John Doe <john@test.test> added the comment:
969 This is a followup
971 ----------
972 status: unread -> chatting
974 _______________________________________________________________________
975 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
976 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
977 _______________________________________________________________________
979 ''')
981 def testFollowupNoNosyRecipients(self):
982 self.doNewIssue()
983 self.instance.config.ADD_RECIPIENTS_TO_NOSY = 'no'
984 self._handle_mail('''Content-Type: text/plain;
985 charset="iso-8859-1"
986 From: richard@test.test
987 To: issue_tracker@your.tracker.email.domain.example
988 Cc: john@test.test
989 Message-Id: <followup_dummy_id>
990 In-Reply-To: <dummy_test_message_id>
991 Subject: [issue1] Testing...
993 This is a followup
994 ''')
995 self.compareMessages(self._get_mail(),
996 '''FROM: roundup-admin@your.tracker.email.domain.example
997 TO: chef@bork.bork.bork
998 Content-Type: text/plain; charset="utf-8"
999 Subject: [issue1] Testing...
1000 To: chef@bork.bork.bork
1001 From: richard <issue_tracker@your.tracker.email.domain.example>
1002 Reply-To: Roundup issue tracker
1003 <issue_tracker@your.tracker.email.domain.example>
1004 MIME-Version: 1.0
1005 Message-Id: <followup_dummy_id>
1006 In-Reply-To: <dummy_test_message_id>
1007 X-Roundup-Name: Roundup issue tracker
1008 X-Roundup-Loop: hello
1009 X-Roundup-Issue-Status: chatting
1010 Content-Transfer-Encoding: quoted-printable
1013 richard <richard@test.test> added the comment:
1015 This is a followup
1017 ----------
1018 status: unread -> chatting
1020 _______________________________________________________________________
1021 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1022 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1023 _______________________________________________________________________
1025 ''')
1027 def testFollowupEmptyMessage(self):
1028 self.doNewIssue()
1030 self._handle_mail('''Content-Type: text/plain;
1031 charset="iso-8859-1"
1032 From: richard <richard@test.test>
1033 To: issue_tracker@your.tracker.email.domain.example
1034 Message-Id: <followup_dummy_id>
1035 In-Reply-To: <dummy_test_message_id>
1036 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
1038 ''')
1039 l = self.db.issue.get('1', 'nosy')
1040 l.sort()
1041 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
1042 self.john_id])
1044 # should be no file created (ie. no message)
1045 assert not os.path.exists(SENDMAILDEBUG)
1047 def testFollowupEmptyMessageNoSubject(self):
1048 self.doNewIssue()
1050 self._handle_mail('''Content-Type: text/plain;
1051 charset="iso-8859-1"
1052 From: richard <richard@test.test>
1053 To: issue_tracker@your.tracker.email.domain.example
1054 Message-Id: <followup_dummy_id>
1055 In-Reply-To: <dummy_test_message_id>
1056 Subject: [issue1] [assignedto=mary; nosy=+john]
1058 ''')
1059 l = self.db.issue.get('1', 'nosy')
1060 l.sort()
1061 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
1062 self.john_id])
1064 # should be no file created (ie. no message)
1065 assert not os.path.exists(SENDMAILDEBUG)
1067 def testNosyRemove(self):
1068 self.doNewIssue()
1070 self._handle_mail('''Content-Type: text/plain;
1071 charset="iso-8859-1"
1072 From: richard <richard@test.test>
1073 To: issue_tracker@your.tracker.email.domain.example
1074 Message-Id: <followup_dummy_id>
1075 In-Reply-To: <dummy_test_message_id>
1076 Subject: [issue1] Testing... [nosy=-richard]
1078 ''')
1079 l = self.db.issue.get('1', 'nosy')
1080 l.sort()
1081 self.assertEqual(l, [self.chef_id])
1083 # NO NOSY MESSAGE SHOULD BE SENT!
1084 assert not os.path.exists(SENDMAILDEBUG)
1086 def testNewUserAuthor(self):
1087 self.db.commit()
1088 l = self.db.user.list()
1089 l.sort()
1090 message = '''Content-Type: text/plain;
1091 charset="iso-8859-1"
1092 From: fubar <fubar@bork.bork.bork>
1093 To: issue_tracker@your.tracker.email.domain.example
1094 Message-Id: <dummy_test_message_id>
1095 Subject: [issue] Testing...
1097 This is a test submission of a new issue.
1098 '''
1099 self.db.security.role['anonymous'].permissions=[]
1100 anonid = self.db.user.lookup('anonymous')
1101 self.db.user.set(anonid, roles='Anonymous')
1102 try:
1103 self._handle_mail(message)
1104 except Unauthorized, value:
1105 body_diff = self.compareMessages(str(value), """
1106 You are not a registered user.
1108 Unknown address: fubar@bork.bork.bork
1109 """)
1110 assert not body_diff, body_diff
1111 else:
1112 raise AssertionError, "Unathorized not raised when handling mail"
1114 # Add Web Access role to anonymous, and try again to make sure
1115 # we get a "please register at:" message this time.
1116 p = [
1117 self.db.security.getPermission('Register', 'user'),
1118 self.db.security.getPermission('Web Access', None),
1119 ]
1120 self.db.security.role['anonymous'].permissions=p
1121 try:
1122 self._handle_mail(message)
1123 except Unauthorized, value:
1124 body_diff = self.compareMessages(str(value), """
1125 You are not a registered user. Please register at:
1127 http://tracker.example/cgi-bin/roundup.cgi/bugs/user?template=register
1129 ...before sending mail to the tracker.
1131 Unknown address: fubar@bork.bork.bork
1132 """)
1133 assert not body_diff, body_diff
1134 else:
1135 raise AssertionError, "Unathorized not raised when handling mail"
1137 # Make sure list of users is the same as before.
1138 m = self.db.user.list()
1139 m.sort()
1140 self.assertEqual(l, m)
1142 # now with the permission
1143 p = [
1144 self.db.security.getPermission('Register', 'user'),
1145 self.db.security.getPermission('Email Access', None),
1146 ]
1147 self.db.security.role['anonymous'].permissions=p
1148 self._handle_mail(message)
1149 m = self.db.user.list()
1150 m.sort()
1151 self.assertNotEqual(l, m)
1153 def testNewUserAuthorEncodedName(self):
1154 l = set(self.db.user.list())
1155 # From: name has Euro symbol in it
1156 message = '''Content-Type: text/plain;
1157 charset="iso-8859-1"
1158 From: =?utf8?b?SOKCrGxsbw==?= <fubar@bork.bork.bork>
1159 To: issue_tracker@your.tracker.email.domain.example
1160 Message-Id: <dummy_test_message_id>
1161 Subject: [issue] Testing...
1163 This is a test submission of a new issue.
1164 '''
1165 p = [
1166 self.db.security.getPermission('Register', 'user'),
1167 self.db.security.getPermission('Email Access', None),
1168 self.db.security.getPermission('Create', 'issue'),
1169 self.db.security.getPermission('Create', 'msg'),
1170 ]
1171 self.db.security.role['anonymous'].permissions = p
1172 self._handle_mail(message)
1173 m = set(self.db.user.list())
1174 new = list(m - l)[0]
1175 name = self.db.user.get(new, 'realname')
1176 self.assertEquals(name, 'H€llo')
1178 def testUnknownUser(self):
1179 l = set(self.db.user.list())
1180 message = '''Content-Type: text/plain;
1181 charset="iso-8859-1"
1182 From: Nonexisting User <nonexisting@bork.bork.bork>
1183 To: issue_tracker@your.tracker.email.domain.example
1184 Message-Id: <dummy_test_message_id>
1185 Subject: [issue] Testing nonexisting user...
1187 This is a test submission of a new issue.
1188 '''
1189 handler = self._create_mailgw(message)
1190 # we want a bounce message:
1191 handler.trapExceptions = 1
1192 ret = handler.main(StringIO(message))
1193 self.compareMessages(self._get_mail(),
1194 '''FROM: Roundup issue tracker <roundup-admin@your.tracker.email.domain.example>
1195 TO: nonexisting@bork.bork.bork
1196 From nobody Tue Jul 14 12:04:11 2009
1197 Content-Type: multipart/mixed; boundary="===============0639262320=="
1198 MIME-Version: 1.0
1199 Subject: Failed issue tracker submission
1200 To: nonexisting@bork.bork.bork
1201 From: Roundup issue tracker <roundup-admin@your.tracker.email.domain.example>
1202 Date: Tue, 14 Jul 2009 12:04:11 +0000
1203 Precedence: bulk
1204 X-Roundup-Name: Roundup issue tracker
1205 X-Roundup-Loop: hello
1206 X-Roundup-Version: 1.4.8
1207 MIME-Version: 1.0
1209 --===============0639262320==
1210 Content-Type: text/plain; charset="us-ascii"
1211 MIME-Version: 1.0
1212 Content-Transfer-Encoding: 7bit
1216 You are not a registered user. Please register at:
1218 http://tracker.example/cgi-bin/roundup.cgi/bugs/user?template=register
1220 ...before sending mail to the tracker.
1222 Unknown address: nonexisting@bork.bork.bork
1224 --===============0639262320==
1225 Content-Type: text/plain; charset="us-ascii"
1226 MIME-Version: 1.0
1227 Content-Transfer-Encoding: 7bit
1229 Content-Type: text/plain;
1230 charset="iso-8859-1"
1231 From: Nonexisting User <nonexisting@bork.bork.bork>
1232 To: issue_tracker@your.tracker.email.domain.example
1233 Message-Id: <dummy_test_message_id>
1234 Subject: [issue] Testing nonexisting user...
1236 This is a test submission of a new issue.
1238 --===============0639262320==--
1239 ''')
1241 def testEnc01(self):
1242 self.db.user.set(self.mary_id,
1243 realname='\xe4\xf6\xfc\xc4\xd6\xdc\xdf, Mary'.decode
1244 ('latin-1').encode('utf-8'))
1245 self.doNewIssue()
1246 self._handle_mail('''Content-Type: text/plain;
1247 charset="iso-8859-1"
1248 From: mary <mary@test.test>
1249 To: issue_tracker@your.tracker.email.domain.example
1250 Message-Id: <followup_dummy_id>
1251 In-Reply-To: <dummy_test_message_id>
1252 Subject: [issue1] Testing...
1253 Content-Type: text/plain;
1254 charset="iso-8859-1"
1255 Content-Transfer-Encoding: quoted-printable
1257 A message with encoding (encoded oe =F6)
1259 ''')
1260 self.compareMessages(self._get_mail(),
1261 '''FROM: roundup-admin@your.tracker.email.domain.example
1262 TO: chef@bork.bork.bork, richard@test.test
1263 Content-Type: text/plain; charset="utf-8"
1264 Subject: [issue1] Testing...
1265 To: chef@bork.bork.bork, richard@test.test
1266 From: =?utf-8?b?w6TDtsO8w4TDlsOcw58sIE1hcnk=?=
1267 <issue_tracker@your.tracker.email.domain.example>
1268 Reply-To: Roundup issue tracker
1269 <issue_tracker@your.tracker.email.domain.example>
1270 MIME-Version: 1.0
1271 Message-Id: <followup_dummy_id>
1272 In-Reply-To: <dummy_test_message_id>
1273 X-Roundup-Name: Roundup issue tracker
1274 X-Roundup-Loop: hello
1275 X-Roundup-Issue-Status: chatting
1276 Content-Transfer-Encoding: quoted-printable
1279 =C3=A4=C3=B6=C3=BC=C3=84=C3=96=C3=9C=C3=9F, Mary <mary@test.test> added the=
1280 comment:
1282 A message with encoding (encoded oe =C3=B6)
1284 ----------
1285 status: unread -> chatting
1287 _______________________________________________________________________
1288 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1289 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1290 _______________________________________________________________________
1291 ''')
1293 def testEncNonUTF8(self):
1294 self.doNewIssue()
1295 self.instance.config.EMAIL_CHARSET = 'iso-8859-1'
1296 self._handle_mail('''Content-Type: text/plain;
1297 charset="iso-8859-1"
1298 From: mary <mary@test.test>
1299 To: issue_tracker@your.tracker.email.domain.example
1300 Message-Id: <followup_dummy_id>
1301 In-Reply-To: <dummy_test_message_id>
1302 Subject: [issue1] Testing...
1303 Content-Type: text/plain;
1304 charset="iso-8859-1"
1305 Content-Transfer-Encoding: quoted-printable
1307 A message with encoding (encoded oe =F6)
1309 ''')
1310 self.compareMessages(self._get_mail(),
1311 '''FROM: roundup-admin@your.tracker.email.domain.example
1312 TO: chef@bork.bork.bork, richard@test.test
1313 Content-Type: text/plain; charset="iso-8859-1"
1314 Subject: [issue1] Testing...
1315 To: chef@bork.bork.bork, richard@test.test
1316 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
1317 Reply-To: Roundup issue tracker
1318 <issue_tracker@your.tracker.email.domain.example>
1319 MIME-Version: 1.0
1320 Message-Id: <followup_dummy_id>
1321 In-Reply-To: <dummy_test_message_id>
1322 X-Roundup-Name: Roundup issue tracker
1323 X-Roundup-Loop: hello
1324 X-Roundup-Issue-Status: chatting
1325 Content-Transfer-Encoding: quoted-printable
1328 Contrary, Mary <mary@test.test> added the comment:
1330 A message with encoding (encoded oe =F6)
1332 ----------
1333 status: unread -> chatting
1335 _______________________________________________________________________
1336 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1337 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1338 _______________________________________________________________________
1339 ''')
1342 def testMultipartEnc01(self):
1343 self.doNewIssue()
1344 self._handle_mail('''Content-Type: text/plain;
1345 charset="iso-8859-1"
1346 From: mary <mary@test.test>
1347 To: issue_tracker@your.tracker.email.domain.example
1348 Message-Id: <followup_dummy_id>
1349 In-Reply-To: <dummy_test_message_id>
1350 Subject: [issue1] Testing...
1351 Content-Type: multipart/mixed;
1352 boundary="----_=_NextPart_000_01"
1354 This message is in MIME format. Since your mail reader does not understand
1355 this format, some or all of this message may not be legible.
1357 ------_=_NextPart_000_01
1358 Content-Type: text/plain;
1359 charset="iso-8859-1"
1360 Content-Transfer-Encoding: quoted-printable
1362 A message with first part encoded (encoded oe =F6)
1364 ''')
1365 self.compareMessages(self._get_mail(),
1366 '''FROM: roundup-admin@your.tracker.email.domain.example
1367 TO: chef@bork.bork.bork, richard@test.test
1368 Content-Type: text/plain; charset="utf-8"
1369 Subject: [issue1] Testing...
1370 To: chef@bork.bork.bork, richard@test.test
1371 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
1372 Reply-To: Roundup issue tracker
1373 <issue_tracker@your.tracker.email.domain.example>
1374 MIME-Version: 1.0
1375 Message-Id: <followup_dummy_id>
1376 In-Reply-To: <dummy_test_message_id>
1377 X-Roundup-Name: Roundup issue tracker
1378 X-Roundup-Loop: hello
1379 X-Roundup-Issue-Status: chatting
1380 Content-Transfer-Encoding: quoted-printable
1383 Contrary, Mary <mary@test.test> added the comment:
1385 A message with first part encoded (encoded oe =C3=B6)
1387 ----------
1388 status: unread -> chatting
1390 _______________________________________________________________________
1391 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1392 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1393 _______________________________________________________________________
1394 ''')
1396 def testContentDisposition(self):
1397 self.doNewIssue()
1398 self._handle_mail('''Content-Type: text/plain;
1399 charset="iso-8859-1"
1400 From: mary <mary@test.test>
1401 To: issue_tracker@your.tracker.email.domain.example
1402 Message-Id: <followup_dummy_id>
1403 In-Reply-To: <dummy_test_message_id>
1404 Subject: [issue1] Testing...
1405 Content-Type: multipart/mixed; boundary="bCsyhTFzCvuiizWE"
1406 Content-Disposition: inline
1409 --bCsyhTFzCvuiizWE
1410 Content-Type: text/plain; charset=us-ascii
1411 Content-Disposition: inline
1413 test attachment binary
1415 --bCsyhTFzCvuiizWE
1416 Content-Type: application/octet-stream
1417 Content-Disposition: attachment; filename="main.dvi"
1418 Content-Transfer-Encoding: base64
1420 SnVzdCBhIHRlc3QgAQo=
1422 --bCsyhTFzCvuiizWE--
1423 ''')
1424 messages = self.db.issue.get('1', 'messages')
1425 messages.sort()
1426 file = self.db.file.getnode (self.db.msg.get(messages[-1], 'files')[0])
1427 self.assertEqual(file.name, 'main.dvi')
1428 self.assertEqual(file.content, 'Just a test \001\n')
1430 def testFollowupStupidQuoting(self):
1431 self.doNewIssue()
1433 self._handle_mail('''Content-Type: text/plain;
1434 charset="iso-8859-1"
1435 From: richard <richard@test.test>
1436 To: issue_tracker@your.tracker.email.domain.example
1437 Message-Id: <followup_dummy_id>
1438 In-Reply-To: <dummy_test_message_id>
1439 Subject: Re: "[issue1] Testing... "
1441 This is a followup
1442 ''')
1443 self.compareMessages(self._get_mail(),
1444 '''FROM: roundup-admin@your.tracker.email.domain.example
1445 TO: chef@bork.bork.bork
1446 Content-Type: text/plain; charset="utf-8"
1447 Subject: [issue1] Testing...
1448 To: chef@bork.bork.bork
1449 From: richard <issue_tracker@your.tracker.email.domain.example>
1450 Reply-To: Roundup issue tracker
1451 <issue_tracker@your.tracker.email.domain.example>
1452 MIME-Version: 1.0
1453 Message-Id: <followup_dummy_id>
1454 In-Reply-To: <dummy_test_message_id>
1455 X-Roundup-Name: Roundup issue tracker
1456 X-Roundup-Loop: hello
1457 X-Roundup-Issue-Status: chatting
1458 Content-Transfer-Encoding: quoted-printable
1461 richard <richard@test.test> added the comment:
1463 This is a followup
1465 ----------
1466 status: unread -> chatting
1468 _______________________________________________________________________
1469 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1470 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1471 _______________________________________________________________________
1472 ''')
1474 def testEmailQuoting(self):
1475 self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
1476 self.innerTestQuoting('''This is a followup
1477 ''')
1479 def testEmailQuotingRemove(self):
1480 self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
1481 self.innerTestQuoting('''Blah blah wrote:
1482 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
1483 > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
1484 >
1486 This is a followup
1487 ''')
1489 def innerTestQuoting(self, expect):
1490 nodeid = self.doNewIssue()
1492 messages = self.db.issue.get(nodeid, 'messages')
1494 self._handle_mail('''Content-Type: text/plain;
1495 charset="iso-8859-1"
1496 From: richard <richard@test.test>
1497 To: issue_tracker@your.tracker.email.domain.example
1498 Message-Id: <followup_dummy_id>
1499 In-Reply-To: <dummy_test_message_id>
1500 Subject: Re: [issue1] Testing...
1502 Blah blah wrote:
1503 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
1504 > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
1505 >
1507 This is a followup
1508 ''')
1509 # figure the new message id
1510 newmessages = self.db.issue.get(nodeid, 'messages')
1511 for msg in messages:
1512 newmessages.remove(msg)
1513 messageid = newmessages[0]
1515 self.compareMessages(self.db.msg.get(messageid, 'content'), expect)
1517 def testUserLookup(self):
1518 i = self.db.user.create(username='user1', address='user1@foo.com')
1519 self.assertEqual(uidFromAddress(self.db, ('', 'user1@foo.com'), 0), i)
1520 self.assertEqual(uidFromAddress(self.db, ('', 'USER1@foo.com'), 0), i)
1521 i = self.db.user.create(username='user2', address='USER2@foo.com')
1522 self.assertEqual(uidFromAddress(self.db, ('', 'USER2@foo.com'), 0), i)
1523 self.assertEqual(uidFromAddress(self.db, ('', 'user2@foo.com'), 0), i)
1525 def testUserAlternateLookup(self):
1526 i = self.db.user.create(username='user1', address='user1@foo.com',
1527 alternate_addresses='user1@bar.com')
1528 self.assertEqual(uidFromAddress(self.db, ('', 'user1@bar.com'), 0), i)
1529 self.assertEqual(uidFromAddress(self.db, ('', 'USER1@bar.com'), 0), i)
1531 def testUserCreate(self):
1532 i = uidFromAddress(self.db, ('', 'user@foo.com'), 1)
1533 self.assertNotEqual(uidFromAddress(self.db, ('', 'user@bar.com'), 1), i)
1535 def testRFC2822(self):
1536 ascii_header = "[issue243] This is a \"test\" - with 'quotation' marks"
1537 unicode_header = '[issue244] \xd0\xb0\xd0\xbd\xd0\xb4\xd1\x80\xd0\xb5\xd0\xb9'
1538 unicode_encoded = '=?utf-8?q?[issue244]_=D0=B0=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?='
1539 self.assertEqual(rfc2822.encode_header(ascii_header), ascii_header)
1540 self.assertEqual(rfc2822.encode_header(unicode_header), unicode_encoded)
1542 def testRegistrationConfirmation(self):
1543 otk = "Aj4euk4LZSAdwePohj90SME5SpopLETL"
1544 self.db.getOTKManager().set(otk, username='johannes')
1545 self._handle_mail('''Content-Type: text/plain;
1546 charset="iso-8859-1"
1547 From: Chef <chef@bork.bork.bork>
1548 To: issue_tracker@your.tracker.email.domain.example
1549 Cc: richard@test.test
1550 Message-Id: <dummy_test_message_id>
1551 Subject: Re: Complete your registration to Roundup issue tracker
1552 -- key %s
1554 This is a test confirmation of registration.
1555 ''' % otk)
1556 self.db.user.lookup('johannes')
1558 def testFollowupOnNonIssue(self):
1559 self.db.keyword.create(name='Foo')
1560 self._handle_mail('''Content-Type: text/plain;
1561 charset="iso-8859-1"
1562 From: richard <richard@test.test>
1563 To: issue_tracker@your.tracker.email.domain.example
1564 Message-Id: <followup_dummy_id>
1565 In-Reply-To: <dummy_test_message_id>
1566 Subject: [keyword1] Testing... [name=Bar]
1568 ''')
1569 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1571 def testResentFrom(self):
1572 nodeid = self._handle_mail('''Content-Type: text/plain;
1573 charset="iso-8859-1"
1574 From: Chef <chef@bork.bork.bork>
1575 Resent-From: mary <mary@test.test>
1576 To: issue_tracker@your.tracker.email.domain.example
1577 Cc: richard@test.test
1578 Message-Id: <dummy_test_message_id>
1579 Subject: [issue] Testing...
1581 This is a test submission of a new issue.
1582 ''')
1583 assert not os.path.exists(SENDMAILDEBUG)
1584 l = self.db.issue.get(nodeid, 'nosy')
1585 l.sort()
1586 self.assertEqual(l, [self.richard_id, self.mary_id])
1587 return nodeid
1589 def testDejaVu(self):
1590 self.assertRaises(IgnoreLoop, self._handle_mail,
1591 '''Content-Type: text/plain;
1592 charset="iso-8859-1"
1593 From: Chef <chef@bork.bork.bork>
1594 X-Roundup-Loop: hello
1595 To: issue_tracker@your.tracker.email.domain.example
1596 Cc: richard@test.test
1597 Message-Id: <dummy_test_message_id>
1598 Subject: Re: [issue] Testing...
1600 Hi, I've been mis-configured to loop messages back to myself.
1601 ''')
1603 def testItsBulkStupid(self):
1604 self.assertRaises(IgnoreBulk, self._handle_mail,
1605 '''Content-Type: text/plain;
1606 charset="iso-8859-1"
1607 From: Chef <chef@bork.bork.bork>
1608 Precedence: bulk
1609 To: issue_tracker@your.tracker.email.domain.example
1610 Cc: richard@test.test
1611 Message-Id: <dummy_test_message_id>
1612 Subject: Re: [issue] Testing...
1614 Hi, I'm on holidays, and this is a dumb auto-responder.
1615 ''')
1617 def testAutoReplyEmailsAreIgnored(self):
1618 self.assertRaises(IgnoreBulk, self._handle_mail,
1619 '''Content-Type: text/plain;
1620 charset="iso-8859-1"
1621 From: Chef <chef@bork.bork.bork>
1622 To: issue_tracker@your.tracker.email.domain.example
1623 Cc: richard@test.test
1624 Message-Id: <dummy_test_message_id>
1625 Subject: Re: [issue] Out of office AutoReply: Back next week
1627 Hi, I am back in the office next week
1628 ''')
1630 def testNoSubject(self):
1631 self.assertRaises(MailUsageError, self._handle_mail,
1632 '''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 Cc: richard@test.test
1637 Reply-To: chef@bork.bork.bork
1638 Message-Id: <dummy_test_message_id>
1640 ''')
1642 #
1643 # TEST FOR INVALID DESIGNATOR HANDLING
1644 #
1645 def testInvalidDesignator(self):
1646 self.assertRaises(MailUsageError, self._handle_mail,
1647 '''Content-Type: text/plain;
1648 charset="iso-8859-1"
1649 From: Chef <chef@bork.bork.bork>
1650 To: issue_tracker@your.tracker.email.domain.example
1651 Subject: [frobulated] testing
1652 Cc: richard@test.test
1653 Reply-To: chef@bork.bork.bork
1654 Message-Id: <dummy_test_message_id>
1656 ''')
1657 self.assertRaises(MailUsageError, self._handle_mail,
1658 '''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: [issue12345] testing
1663 Cc: richard@test.test
1664 Reply-To: chef@bork.bork.bork
1665 Message-Id: <dummy_test_message_id>
1667 ''')
1669 def testInvalidClassLoose(self):
1670 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1671 nodeid = self._handle_mail('''Content-Type: text/plain;
1672 charset="iso-8859-1"
1673 From: Chef <chef@bork.bork.bork>
1674 To: issue_tracker@your.tracker.email.domain.example
1675 Subject: [frobulated] testing
1676 Cc: richard@test.test
1677 Reply-To: chef@bork.bork.bork
1678 Message-Id: <dummy_test_message_id>
1680 ''')
1681 assert not os.path.exists(SENDMAILDEBUG)
1682 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1683 '[frobulated] testing')
1685 def testInvalidClassLooseReply(self):
1686 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1687 nodeid = self._handle_mail('''Content-Type: text/plain;
1688 charset="iso-8859-1"
1689 From: Chef <chef@bork.bork.bork>
1690 To: issue_tracker@your.tracker.email.domain.example
1691 Subject: Re: [frobulated] testing
1692 Cc: richard@test.test
1693 Reply-To: chef@bork.bork.bork
1694 Message-Id: <dummy_test_message_id>
1696 ''')
1697 assert not os.path.exists(SENDMAILDEBUG)
1698 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1699 '[frobulated] testing')
1701 def testInvalidClassLoose(self):
1702 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1703 nodeid = self._handle_mail('''Content-Type: text/plain;
1704 charset="iso-8859-1"
1705 From: Chef <chef@bork.bork.bork>
1706 To: issue_tracker@your.tracker.email.domain.example
1707 Subject: [issue1234] testing
1708 Cc: richard@test.test
1709 Reply-To: chef@bork.bork.bork
1710 Message-Id: <dummy_test_message_id>
1712 ''')
1713 assert not os.path.exists(SENDMAILDEBUG)
1714 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1715 '[issue1234] testing')
1717 def testClassLooseOK(self):
1718 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1719 self.db.keyword.create(name='Foo')
1720 nodeid = self._handle_mail('''Content-Type: text/plain;
1721 charset="iso-8859-1"
1722 From: Chef <chef@bork.bork.bork>
1723 To: issue_tracker@your.tracker.email.domain.example
1724 Subject: [keyword1] Testing... [name=Bar]
1725 Cc: richard@test.test
1726 Reply-To: chef@bork.bork.bork
1727 Message-Id: <dummy_test_message_id>
1729 ''')
1730 assert not os.path.exists(SENDMAILDEBUG)
1731 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1733 def testClassStrictInvalid(self):
1734 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'strict'
1735 self.instance.config.MAILGW_DEFAULT_CLASS = ''
1737 message = '''Content-Type: text/plain;
1738 charset="iso-8859-1"
1739 From: Chef <chef@bork.bork.bork>
1740 To: issue_tracker@your.tracker.email.domain.example
1741 Subject: Testing...
1742 Cc: richard@test.test
1743 Reply-To: chef@bork.bork.bork
1744 Message-Id: <dummy_test_message_id>
1746 '''
1747 self.assertRaises(MailUsageError, self._handle_mail, message)
1749 def testClassStrictValid(self):
1750 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'strict'
1751 self.instance.config.MAILGW_DEFAULT_CLASS = ''
1753 nodeid = self._handle_mail('''Content-Type: text/plain;
1754 charset="iso-8859-1"
1755 From: Chef <chef@bork.bork.bork>
1756 To: issue_tracker@your.tracker.email.domain.example
1757 Subject: [issue] Testing...
1758 Cc: richard@test.test
1759 Reply-To: chef@bork.bork.bork
1760 Message-Id: <dummy_test_message_id>
1762 ''')
1764 assert not os.path.exists(SENDMAILDEBUG)
1765 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
1767 #
1768 # TEST FOR INVALID COMMANDS HANDLING
1769 #
1770 def testInvalidCommands(self):
1771 self.assertRaises(MailUsageError, self._handle_mail,
1772 '''Content-Type: text/plain;
1773 charset="iso-8859-1"
1774 From: Chef <chef@bork.bork.bork>
1775 To: issue_tracker@your.tracker.email.domain.example
1776 Subject: testing [frobulated]
1777 Cc: richard@test.test
1778 Reply-To: chef@bork.bork.bork
1779 Message-Id: <dummy_test_message_id>
1781 ''')
1783 def testInvalidCommandPassthrough(self):
1784 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'none'
1785 nodeid = self._handle_mail('''Content-Type: text/plain;
1786 charset="iso-8859-1"
1787 From: Chef <chef@bork.bork.bork>
1788 To: issue_tracker@your.tracker.email.domain.example
1789 Subject: testing [frobulated]
1790 Cc: richard@test.test
1791 Reply-To: chef@bork.bork.bork
1792 Message-Id: <dummy_test_message_id>
1794 ''')
1795 assert not os.path.exists(SENDMAILDEBUG)
1796 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1797 'testing [frobulated]')
1799 def testInvalidCommandPassthroughLoose(self):
1800 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'loose'
1801 nodeid = self._handle_mail('''Content-Type: text/plain;
1802 charset="iso-8859-1"
1803 From: Chef <chef@bork.bork.bork>
1804 To: issue_tracker@your.tracker.email.domain.example
1805 Subject: testing [frobulated]
1806 Cc: richard@test.test
1807 Reply-To: chef@bork.bork.bork
1808 Message-Id: <dummy_test_message_id>
1810 ''')
1811 assert not os.path.exists(SENDMAILDEBUG)
1812 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1813 'testing [frobulated]')
1815 def testInvalidCommandPassthroughLooseOK(self):
1816 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'loose'
1817 nodeid = self._handle_mail('''Content-Type: text/plain;
1818 charset="iso-8859-1"
1819 From: Chef <chef@bork.bork.bork>
1820 To: issue_tracker@your.tracker.email.domain.example
1821 Subject: testing [assignedto=mary]
1822 Cc: richard@test.test
1823 Reply-To: chef@bork.bork.bork
1824 Message-Id: <dummy_test_message_id>
1826 ''')
1827 assert not os.path.exists(SENDMAILDEBUG)
1828 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing')
1829 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), self.mary_id)
1831 def testCommandDelimiters(self):
1832 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
1833 nodeid = self._handle_mail('''Content-Type: text/plain;
1834 charset="iso-8859-1"
1835 From: Chef <chef@bork.bork.bork>
1836 To: issue_tracker@your.tracker.email.domain.example
1837 Subject: testing {assignedto=mary}
1838 Cc: richard@test.test
1839 Reply-To: chef@bork.bork.bork
1840 Message-Id: <dummy_test_message_id>
1842 ''')
1843 assert not os.path.exists(SENDMAILDEBUG)
1844 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing')
1845 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), self.mary_id)
1847 def testPrefixDelimiters(self):
1848 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
1849 self.db.keyword.create(name='Foo')
1850 self._handle_mail('''Content-Type: text/plain;
1851 charset="iso-8859-1"
1852 From: richard <richard@test.test>
1853 To: issue_tracker@your.tracker.email.domain.example
1854 Message-Id: <followup_dummy_id>
1855 In-Reply-To: <dummy_test_message_id>
1856 Subject: {keyword1} Testing... {name=Bar}
1858 ''')
1859 assert not os.path.exists(SENDMAILDEBUG)
1860 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1862 def testCommandDelimitersIgnore(self):
1863 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
1864 nodeid = self._handle_mail('''Content-Type: text/plain;
1865 charset="iso-8859-1"
1866 From: Chef <chef@bork.bork.bork>
1867 To: issue_tracker@your.tracker.email.domain.example
1868 Subject: testing [assignedto=mary]
1869 Cc: richard@test.test
1870 Reply-To: chef@bork.bork.bork
1871 Message-Id: <dummy_test_message_id>
1873 ''')
1874 assert not os.path.exists(SENDMAILDEBUG)
1875 self.assertEqual(self.db.issue.get(nodeid, 'title'),
1876 'testing [assignedto=mary]')
1877 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), None)
1879 def testReplytoMatch(self):
1880 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
1881 nodeid = self.doNewIssue()
1882 nodeid2 = self._handle_mail('''Content-Type: text/plain;
1883 charset="iso-8859-1"
1884 From: Chef <chef@bork.bork.bork>
1885 To: issue_tracker@your.tracker.email.domain.example
1886 Message-Id: <dummy_test_message_id2>
1887 In-Reply-To: <dummy_test_message_id>
1888 Subject: Testing...
1890 Followup message.
1891 ''')
1893 nodeid3 = self._handle_mail('''Content-Type: text/plain;
1894 charset="iso-8859-1"
1895 From: Chef <chef@bork.bork.bork>
1896 To: issue_tracker@your.tracker.email.domain.example
1897 Message-Id: <dummy_test_message_id3>
1898 In-Reply-To: <dummy_test_message_id2>
1899 Subject: Testing...
1901 Yet another message in the same thread/issue.
1902 ''')
1904 self.assertEqual(nodeid, nodeid2)
1905 self.assertEqual(nodeid, nodeid3)
1907 def testHelpSubject(self):
1908 message = '''Content-Type: text/plain;
1909 charset="iso-8859-1"
1910 From: Chef <chef@bork.bork.bork>
1911 To: issue_tracker@your.tracker.email.domain.example
1912 Message-Id: <dummy_test_message_id2>
1913 In-Reply-To: <dummy_test_message_id>
1914 Subject: hElp
1917 '''
1918 self.assertRaises(MailUsageHelp, self._handle_mail, message)
1920 def testMaillistSubject(self):
1921 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '[]'
1922 self.db.keyword.create(name='Foo')
1923 self._handle_mail('''Content-Type: text/plain;
1924 charset="iso-8859-1"
1925 From: Chef <chef@bork.bork.bork>
1926 To: issue_tracker@your.tracker.email.domain.example
1927 Subject: [mailinglist-name] [keyword1] Testing.. [name=Bar]
1928 Cc: richard@test.test
1929 Reply-To: chef@bork.bork.bork
1930 Message-Id: <dummy_test_message_id>
1932 ''')
1934 assert not os.path.exists(SENDMAILDEBUG)
1935 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1937 def testUnknownPrefixSubject(self):
1938 self.db.keyword.create(name='Foo')
1939 self._handle_mail('''Content-Type: text/plain;
1940 charset="iso-8859-1"
1941 From: Chef <chef@bork.bork.bork>
1942 To: issue_tracker@your.tracker.email.domain.example
1943 Subject: VeryStrangeRe: [keyword1] Testing.. [name=Bar]
1944 Cc: richard@test.test
1945 Reply-To: chef@bork.bork.bork
1946 Message-Id: <dummy_test_message_id>
1948 ''')
1950 assert not os.path.exists(SENDMAILDEBUG)
1951 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1953 def testIssueidLast(self):
1954 nodeid1 = self.doNewIssue()
1955 nodeid2 = self._handle_mail('''Content-Type: text/plain;
1956 charset="iso-8859-1"
1957 From: mary <mary@test.test>
1958 To: issue_tracker@your.tracker.email.domain.example
1959 Message-Id: <followup_dummy_id>
1960 In-Reply-To: <dummy_test_message_id>
1961 Subject: New title [issue1]
1963 This is a second followup
1964 ''')
1966 assert nodeid1 == nodeid2
1967 self.assertEqual(self.db.issue.get(nodeid2, 'title'), "Testing...")
1969 def testSecurityMessagePermissionContent(self):
1970 id = self.doNewIssue()
1971 issue = self.db.issue.getnode (id)
1972 self.db.security.addRole(name='Nomsg')
1973 self.db.security.addPermissionToRole('Nomsg', 'Email Access')
1974 for cl in 'issue', 'file', 'keyword':
1975 for p in 'View', 'Edit', 'Create':
1976 self.db.security.addPermissionToRole('Nomsg', p, cl)
1977 self.db.user.set(self.mary_id, roles='Nomsg')
1978 nodeid = self._handle_mail('''Content-Type: text/plain;
1979 charset="iso-8859-1"
1980 From: Chef <chef@bork.bork.bork>
1981 To: issue_tracker@your.tracker.email.domain.example
1982 Message-Id: <dummy_test_message_id_2>
1983 Subject: [issue%(id)s] Testing... [nosy=+mary]
1985 Just a test reply
1986 '''%locals())
1987 assert os.path.exists(SENDMAILDEBUG)
1988 self.compareMessages(self._get_mail(),
1989 '''FROM: roundup-admin@your.tracker.email.domain.example
1990 TO: chef@bork.bork.bork, richard@test.test
1991 Content-Type: text/plain; charset="utf-8"
1992 Subject: [issue1] Testing...
1993 To: richard@test.test
1994 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
1995 Reply-To: Roundup issue tracker
1996 <issue_tracker@your.tracker.email.domain.example>
1997 MIME-Version: 1.0
1998 Message-Id: <dummy_test_message_id_2>
1999 In-Reply-To: <dummy_test_message_id>
2000 X-Roundup-Name: Roundup issue tracker
2001 X-Roundup-Loop: hello
2002 X-Roundup-Issue-Status: chatting
2003 Content-Transfer-Encoding: quoted-printable
2006 Bork, Chef <chef@bork.bork.bork> added the comment:
2008 Just a test reply
2010 ----------
2011 nosy: +mary
2012 status: unread -> chatting
2014 _______________________________________________________________________
2015 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
2016 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
2017 _______________________________________________________________________
2018 ''')
2021 def test_suite():
2022 suite = unittest.TestSuite()
2023 suite.addTest(unittest.makeSuite(MailgwTestCase))
2024 return suite
2026 if __name__ == '__main__':
2027 runner = unittest.TextTestRunner()
2028 unittest.main(testRunner=runner)
2030 # vim: set filetype=python sts=4 sw=4 et si :