Code

The email for the first message on an issue was sometimes having its
[roundup.git] / test / test_mailgw.py
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
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
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 :