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 import mailgw, i18n, roundupdb
25 from roundup.mailgw import MailGW, Unauthorized, uidFromAddress, \
26 parseContent, IgnoreLoop, IgnoreBulk, MailUsageError, MailUsageHelp
27 from roundup import init, instance, password, rfc2822, __version__
28 from roundup.anypy.sets_ import set
30 #import db_test_base
31 import memorydb
33 class Message(rfc822.Message):
34 """String-based Message class with equivalence test."""
35 def __init__(self, s):
36 rfc822.Message.__init__(self, StringIO(s.strip()))
38 def __eq__(self, other):
39 return (self.dict == other.dict and
40 self.fp.read() == other.fp.read())
42 class Tracker(object):
43 def open(self, journaltag):
44 return self.db
46 class DiffHelper:
47 def compareMessages(self, new, old):
48 """Compare messages for semantic equivalence."""
49 new, old = Message(new), Message(old)
51 # all Roundup-generated messages have "Precedence: bulk"
52 old['Precedence'] = 'bulk'
54 # don't try to compare the date
55 del new['date'], old['date']
57 if not new == old:
58 res = []
60 replace = {}
61 for key in new.keys():
62 if key.startswith('from '):
63 # skip the unix from line
64 continue
65 if key.lower() == 'x-roundup-version':
66 # version changes constantly, so handle it specially
67 if new[key] != __version__:
68 res.append(' %s: %r != %r' % (key, __version__,
69 new[key]))
70 elif key.lower() == 'content-type' and 'boundary=' in new[key]:
71 # handle mime messages
72 newmime = new[key].split('=',1)[-1].strip('"')
73 oldmime = old.get(key, '').split('=',1)[-1].strip('"')
74 replace ['--' + newmime] = '--' + oldmime
75 replace ['--' + newmime + '--'] = '--' + oldmime + '--'
76 elif new.get(key, '') != old.get(key, ''):
77 res.append(' %s: %r != %r' % (key, old.get(key, ''),
78 new.get(key, '')))
80 body_diff = self.compareStrings(new.fp.read(), old.fp.read(),
81 replace=replace)
82 if body_diff:
83 res.append('')
84 res.extend(body_diff)
86 if res:
87 res.insert(0, 'Generated message not correct (diff follows, expected vs. actual):')
88 raise AssertionError, '\n'.join(res)
90 def compareStrings(self, s2, s1, replace={}):
91 '''Note the reversal of s2 and s1 - difflib.SequenceMatcher wants
92 the first to be the "original" but in the calls in this file,
93 the second arg is the original. Ho hum.
94 Do replacements over the replace dict -- used for mime boundary
95 '''
96 l1 = s1.strip().split('\n')
97 l2 = [replace.get(i,i) for i in s2.strip().split('\n')]
98 if l1 == l2:
99 return
100 s = difflib.SequenceMatcher(None, l1, l2)
101 res = []
102 for value, s1s, s1e, s2s, s2e in s.get_opcodes():
103 if value == 'equal':
104 for i in range(s1s, s1e):
105 res.append(' %s'%l1[i])
106 elif value == 'delete':
107 for i in range(s1s, s1e):
108 res.append('- %s'%l1[i])
109 elif value == 'insert':
110 for i in range(s2s, s2e):
111 res.append('+ %s'%l2[i])
112 elif value == 'replace':
113 for i, j in zip(range(s1s, s1e), range(s2s, s2e)):
114 res.append('- %s'%l1[i])
115 res.append('+ %s'%l2[j])
117 return res
119 class MailgwTestCase(unittest.TestCase, DiffHelper):
120 count = 0
121 schema = 'classic'
122 def setUp(self):
123 self.old_translate_ = mailgw._
124 roundupdb._ = mailgw._ = i18n.get_translation(language='C').gettext
125 MailgwTestCase.count = MailgwTestCase.count + 1
127 # and open the database / "instance"
128 self.db = memorydb.create('admin')
129 self.instance = Tracker()
130 self.instance.db = self.db
131 self.instance.config = self.db.config
132 self.instance.MailGW = MailGW
134 self.chef_id = self.db.user.create(username='Chef',
135 address='chef@bork.bork.bork', realname='Bork, Chef', roles='User')
136 self.richard_id = self.db.user.create(username='richard',
137 address='richard@test.test', roles='User')
138 self.mary_id = self.db.user.create(username='mary',
139 address='mary@test.test', roles='User', realname='Contrary, Mary')
140 self.john_id = self.db.user.create(username='john',
141 address='john@test.test', roles='User', realname='John Doe',
142 alternate_addresses='jondoe@test.test\njohn.doe@test.test')
143 self.rgg_id = self.db.user.create(username='rgg',
144 address='rgg@test.test', roles='User')
146 def tearDown(self):
147 roundupdb._ = mailgw._ = self.old_translate_
148 if os.path.exists(SENDMAILDEBUG):
149 os.remove(SENDMAILDEBUG)
150 self.db.close()
152 def _create_mailgw(self, message):
153 class MailGW(self.instance.MailGW):
154 def handle_message(self, message):
155 return self._handle_message(message)
156 handler = MailGW(self.instance)
157 handler.db = self.db
158 return handler
160 def _handle_mail(self, message):
161 handler = self._create_mailgw(message)
162 handler.trapExceptions = 0
163 return handler.main(StringIO(message))
165 def _get_mail(self):
166 f = open(SENDMAILDEBUG)
167 try:
168 return f.read()
169 finally:
170 f.close()
172 def testEmptyMessage(self):
173 nodeid = self._handle_mail('''Content-Type: text/plain;
174 charset="iso-8859-1"
175 From: Chef <chef@bork.bork.bork>
176 To: issue_tracker@your.tracker.email.domain.example
177 Cc: richard@test.test
178 Reply-To: chef@bork.bork.bork
179 Message-Id: <dummy_test_message_id>
180 Subject: [issue] Testing...
182 ''')
183 assert not os.path.exists(SENDMAILDEBUG)
184 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
186 def testMessageWithFromInIt(self):
187 nodeid = self._handle_mail('''Content-Type: text/plain;
188 charset="iso-8859-1"
189 From: Chef <chef@bork.bork.bork>
190 To: issue_tracker@your.tracker.email.domain.example
191 Cc: richard@test.test
192 Reply-To: chef@bork.bork.bork
193 Message-Id: <dummy_test_message_id>
194 Subject: [issue] Testing...
196 From here to there!
197 ''')
198 assert not os.path.exists(SENDMAILDEBUG)
199 msgid = self.db.issue.get(nodeid, 'messages')[0]
200 self.assertEqual(self.db.msg.get(msgid, 'content'), 'From here to there!')
202 def doNewIssue(self):
203 nodeid = self._handle_mail('''Content-Type: text/plain;
204 charset="iso-8859-1"
205 From: Chef <chef@bork.bork.bork>
206 To: issue_tracker@your.tracker.email.domain.example
207 Cc: richard@test.test
208 Message-Id: <dummy_test_message_id>
209 Subject: [issue] Testing...
211 This is a test submission of a new issue.
212 ''')
213 assert not os.path.exists(SENDMAILDEBUG)
214 l = self.db.issue.get(nodeid, 'nosy')
215 l.sort()
216 self.assertEqual(l, [self.chef_id, self.richard_id])
217 return nodeid
219 def testNewIssue(self):
220 self.doNewIssue()
222 def testNewIssueNosy(self):
223 self.instance.config.ADD_AUTHOR_TO_NOSY = 'yes'
224 nodeid = self._handle_mail('''Content-Type: text/plain;
225 charset="iso-8859-1"
226 From: Chef <chef@bork.bork.bork>
227 To: issue_tracker@your.tracker.email.domain.example
228 Cc: richard@test.test
229 Message-Id: <dummy_test_message_id>
230 Subject: [issue] Testing...
232 This is a test submission of a new issue.
233 ''')
234 assert not os.path.exists(SENDMAILDEBUG)
235 l = self.db.issue.get(nodeid, 'nosy')
236 l.sort()
237 self.assertEqual(l, [self.chef_id, self.richard_id])
239 def testAlternateAddress(self):
240 self._handle_mail('''Content-Type: text/plain;
241 charset="iso-8859-1"
242 From: John Doe <john.doe@test.test>
243 To: issue_tracker@your.tracker.email.domain.example
244 Message-Id: <dummy_test_message_id>
245 Subject: [issue] Testing...
247 This is a test submission of a new issue.
248 ''')
249 userlist = self.db.user.list()
250 assert not os.path.exists(SENDMAILDEBUG)
251 self.assertEqual(userlist, self.db.user.list(),
252 "user created when it shouldn't have been")
254 def testNewIssueNoClass(self):
255 self._handle_mail('''Content-Type: text/plain;
256 charset="iso-8859-1"
257 From: Chef <chef@bork.bork.bork>
258 To: issue_tracker@your.tracker.email.domain.example
259 Cc: richard@test.test
260 Message-Id: <dummy_test_message_id>
261 Subject: Testing...
263 This is a test submission of a new issue.
264 ''')
265 assert not os.path.exists(SENDMAILDEBUG)
267 def testNewIssueAuthMsg(self):
268 # TODO: fix the damn config - this is apalling
269 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
270 self._handle_mail('''Content-Type: text/plain;
271 charset="iso-8859-1"
272 From: Chef <chef@bork.bork.bork>
273 To: issue_tracker@your.tracker.email.domain.example
274 Message-Id: <dummy_test_message_id>
275 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
277 This is a test submission of a new issue.
278 ''')
279 self.compareMessages(self._get_mail(),
280 '''FROM: roundup-admin@your.tracker.email.domain.example
281 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
282 Content-Type: text/plain; charset="utf-8"
283 Subject: [issue1] Testing...
284 To: chef@bork.bork.bork, mary@test.test, richard@test.test
285 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
286 Reply-To: Roundup issue tracker
287 <issue_tracker@your.tracker.email.domain.example>
288 MIME-Version: 1.0
289 Message-Id: <dummy_test_message_id>
290 X-Roundup-Name: Roundup issue tracker
291 X-Roundup-Loop: hello
292 X-Roundup-Issue-Status: unread
293 Content-Transfer-Encoding: quoted-printable
296 New submission from Bork, Chef <chef@bork.bork.bork>:
298 This is a test submission of a new issue.
300 ----------
301 assignedto: richard
302 messages: 1
303 nosy: Chef, mary, richard
304 status: unread
305 title: Testing...
307 _______________________________________________________________________
308 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
309 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
310 _______________________________________________________________________
311 ''')
313 def testNewIssueNoAuthorInfo(self):
314 self.db.config.MAIL_ADD_AUTHORINFO = 'no'
315 self._handle_mail('''Content-Type: text/plain;
316 charset="iso-8859-1"
317 From: Chef <chef@bork.bork.bork>
318 To: issue_tracker@your.tracker.email.domain.example
319 Message-Id: <dummy_test_message_id>
320 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
322 This is a test submission of a new issue.
323 ''')
324 self.compareMessages(self._get_mail(),
325 '''FROM: roundup-admin@your.tracker.email.domain.example
326 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
327 Content-Type: text/plain; charset="utf-8"
328 Subject: [issue1] Testing...
329 To: mary@test.test, richard@test.test
330 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
331 Reply-To: Roundup issue tracker
332 <issue_tracker@your.tracker.email.domain.example>
333 MIME-Version: 1.0
334 Message-Id: <dummy_test_message_id>
335 X-Roundup-Name: Roundup issue tracker
336 X-Roundup-Loop: hello
337 X-Roundup-Issue-Status: unread
338 Content-Transfer-Encoding: quoted-printable
340 This is a test submission of a new issue.
342 ----------
343 assignedto: richard
344 messages: 1
345 nosy: Chef, mary, richard
346 status: unread
347 title: Testing...
349 _______________________________________________________________________
350 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
351 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
352 _______________________________________________________________________
353 ''')
355 def testNewIssueNoAuthorEmail(self):
356 self.db.config.MAIL_ADD_AUTHOREMAIL = 'no'
357 self._handle_mail('''Content-Type: text/plain;
358 charset="iso-8859-1"
359 From: Chef <chef@bork.bork.bork>
360 To: issue_tracker@your.tracker.email.domain.example
361 Message-Id: <dummy_test_message_id>
362 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
364 This is a test submission of a new issue.
365 ''')
366 self.compareMessages(self._get_mail(),
367 '''FROM: roundup-admin@your.tracker.email.domain.example
368 TO: chef@bork.bork.bork, mary@test.test, richard@test.test
369 Content-Type: text/plain; charset="utf-8"
370 Subject: [issue1] Testing...
371 To: mary@test.test, richard@test.test
372 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
373 Reply-To: Roundup issue tracker
374 <issue_tracker@your.tracker.email.domain.example>
375 MIME-Version: 1.0
376 Message-Id: <dummy_test_message_id>
377 X-Roundup-Name: Roundup issue tracker
378 X-Roundup-Loop: hello
379 X-Roundup-Issue-Status: unread
380 Content-Transfer-Encoding: quoted-printable
382 New submission from Bork, Chef:
384 This is a test submission of a new issue.
386 ----------
387 assignedto: richard
388 messages: 1
389 nosy: Chef, mary, richard
390 status: unread
391 title: Testing...
393 _______________________________________________________________________
394 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
395 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
396 _______________________________________________________________________
397 ''')
399 multipart_msg = '''From: mary <mary@test.test>
400 To: issue_tracker@your.tracker.email.domain.example
401 Message-Id: <followup_dummy_id>
402 In-Reply-To: <dummy_test_message_id>
403 Subject: [issue1] Testing...
404 Content-Type: multipart/mixed; boundary="bxyzzy"
405 Content-Disposition: inline
408 --bxyzzy
409 Content-Type: multipart/alternative; boundary="bCsyhTFzCvuiizWE"
410 Content-Disposition: inline
412 --bCsyhTFzCvuiizWE
413 Content-Type: text/plain; charset=us-ascii
414 Content-Disposition: inline
416 test attachment first text/plain
418 --bCsyhTFzCvuiizWE
419 Content-Type: application/octet-stream
420 Content-Disposition: attachment; filename="first.dvi"
421 Content-Transfer-Encoding: base64
423 SnVzdCBhIHRlc3QgAQo=
425 --bCsyhTFzCvuiizWE
426 Content-Type: text/plain; charset=us-ascii
427 Content-Disposition: inline
429 test attachment second text/plain
431 --bCsyhTFzCvuiizWE
432 Content-Type: text/html
433 Content-Disposition: inline
435 <html>
436 to be ignored.
437 </html>
439 --bCsyhTFzCvuiizWE--
441 --bxyzzy
442 Content-Type: multipart/alternative; boundary="bCsyhTFzCvuiizWF"
443 Content-Disposition: inline
445 --bCsyhTFzCvuiizWF
446 Content-Type: text/plain; charset=us-ascii
447 Content-Disposition: inline
449 test attachment third text/plain
451 --bCsyhTFzCvuiizWF
452 Content-Type: application/octet-stream
453 Content-Disposition: attachment; filename="second.dvi"
454 Content-Transfer-Encoding: base64
456 SnVzdCBhIHRlc3QK
458 --bCsyhTFzCvuiizWF--
460 --bxyzzy--
461 '''
463 multipart_msg_latin1 = '''From: mary <mary@test.test>
464 To: issue_tracker@your.tracker.email.domain.example
465 Message-Id: <followup_dummy_id>
466 In-Reply-To: <dummy_test_message_id>
467 Subject: [issue1] Testing...
468 Content-Type: multipart/alternative; boundary=001485f339f8f361fb049188dbba
471 --001485f339f8f361fb049188dbba
472 Content-Type: text/plain; charset=ISO-8859-1
473 Content-Transfer-Encoding: quoted-printable
475 umlaut =E4=F6=FC=C4=D6=DC=DF
477 --001485f339f8f361fb049188dbba
478 Content-Type: text/html; charset=ISO-8859-1
479 Content-Transfer-Encoding: quoted-printable
481 <html>umlaut =E4=F6=FC=C4=D6=DC=DF</html>
483 --001485f339f8f361fb049188dbba--
484 '''
486 multipart_msg_rfc822 = '''From: mary <mary@test.test>
487 To: issue_tracker@your.tracker.email.domain.example
488 Message-Id: <followup_dummy_id>
489 In-Reply-To: <dummy_test_message_id>
490 Subject: [issue1] Testing...
491 Content-Type: multipart/mixed; boundary=001485f339f8f361fb049188dbba
493 This is a multi-part message in MIME format.
494 --001485f339f8f361fb049188dbba
495 Content-Type: text/plain; charset=ISO-8859-15
496 Content-Transfer-Encoding: 7bit
498 First part: Text
500 --001485f339f8f361fb049188dbba
501 Content-Type: message/rfc822; name="Fwd: Original email subject.eml"
502 Content-Transfer-Encoding: 7bit
503 Content-Disposition: attachment; filename="Fwd: Original email subject.eml"
505 Message-Id: <followup_dummy_id_2>
506 In-Reply-To: <dummy_test_message_id_2>
507 MIME-Version: 1.0
508 Subject: Fwd: Original email subject
509 Date: Mon, 23 Aug 2010 08:23:33 +0200
510 Content-Type: multipart/alternative; boundary="090500050101020406060002"
512 This is a multi-part message in MIME format.
513 --090500050101020406060002
514 Content-Type: text/plain; charset=ISO-8859-15; format=flowed
515 Content-Transfer-Encoding: 7bit
517 some text in inner email
518 ========================
520 --090500050101020406060002
521 Content-Type: text/html; charset=ISO-8859-15
522 Content-Transfer-Encoding: 7bit
524 <html>
525 some text in inner email
526 ========================
527 </html>
529 --090500050101020406060002--
531 --001485f339f8f361fb049188dbba--
532 '''
534 def testMultipartKeepAlternatives(self):
535 self.doNewIssue()
536 self._handle_mail(self.multipart_msg)
537 messages = self.db.issue.get('1', 'messages')
538 messages.sort()
539 msg = self.db.msg.getnode (messages[-1])
540 assert(len(msg.files) == 5)
541 names = {0 : 'first.dvi', 4 : 'second.dvi'}
542 content = {3 : 'test attachment third text/plain\n',
543 4 : 'Just a test\n'}
544 for n, id in enumerate (msg.files):
545 f = self.db.file.getnode (id)
546 self.assertEqual(f.name, names.get (n, 'unnamed'))
547 if n in content :
548 self.assertEqual(f.content, content [n])
549 self.assertEqual(msg.content, 'test attachment second text/plain')
551 def testMultipartDropAlternatives(self):
552 self.doNewIssue()
553 self.db.config.MAILGW_IGNORE_ALTERNATIVES = True
554 self._handle_mail(self.multipart_msg)
555 messages = self.db.issue.get('1', 'messages')
556 messages.sort()
557 msg = self.db.msg.getnode (messages[-1])
558 assert(len(msg.files) == 2)
559 names = {1 : 'second.dvi'}
560 content = {0 : 'test attachment third text/plain\n',
561 1 : 'Just a test\n'}
562 for n, id in enumerate (msg.files):
563 f = self.db.file.getnode (id)
564 self.assertEqual(f.name, names.get (n, 'unnamed'))
565 if n in content :
566 self.assertEqual(f.content, content [n])
567 self.assertEqual(msg.content, 'test attachment second text/plain')
569 def testMultipartCharsetUTF8NoAttach(self):
570 c = 'umlaut \xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c\xc3\x9f'
571 self.doNewIssue()
572 self.db.config.NOSY_MAX_ATTACHMENT_SIZE = 0
573 self._handle_mail(self.multipart_msg_latin1)
574 messages = self.db.issue.get('1', 'messages')
575 messages.sort()
576 msg = self.db.msg.getnode (messages[-1])
577 assert(len(msg.files) == 1)
578 name = 'unnamed'
579 content = '<html>' + c + '</html>\n'
580 for n, id in enumerate (msg.files):
581 f = self.db.file.getnode (id)
582 self.assertEqual(f.name, name)
583 self.assertEqual(f.content, content)
584 self.assertEqual(msg.content, c)
585 self.compareMessages(self._get_mail(),
586 '''FROM: roundup-admin@your.tracker.email.domain.example
587 TO: chef@bork.bork.bork, richard@test.test
588 Content-Type: text/plain; charset="utf-8"
589 Subject: [issue1] Testing...
590 To: chef@bork.bork.bork, richard@test.test
591 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
592 Reply-To: Roundup issue tracker
593 <issue_tracker@your.tracker.email.domain.example>
594 MIME-Version: 1.0
595 Message-Id: <followup_dummy_id>
596 In-Reply-To: <dummy_test_message_id>
597 X-Roundup-Name: Roundup issue tracker
598 X-Roundup-Loop: hello
599 X-Roundup-Issue-Status: chatting
600 X-Roundup-Issue-Files: unnamed
601 Content-Transfer-Encoding: quoted-printable
604 Contrary, Mary <mary@test.test> added the comment:
606 umlaut =C3=A4=C3=B6=C3=BC=C3=84=C3=96=C3=9C=C3=9F
607 File 'unnamed' not attached - you can download it from http://tracker.examp=
608 le/cgi-bin/roundup.cgi/bugs/file1.
610 ----------
611 status: unread -> chatting
613 _______________________________________________________________________
614 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
615 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
616 _______________________________________________________________________
617 ''')
619 def testMultipartCharsetLatin1NoAttach(self):
620 c = 'umlaut \xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c\xc3\x9f'
621 self.doNewIssue()
622 self.db.config.NOSY_MAX_ATTACHMENT_SIZE = 0
623 self.db.config.MAIL_CHARSET = 'iso-8859-1'
624 self._handle_mail(self.multipart_msg_latin1)
625 messages = self.db.issue.get('1', 'messages')
626 messages.sort()
627 msg = self.db.msg.getnode (messages[-1])
628 assert(len(msg.files) == 1)
629 name = 'unnamed'
630 content = '<html>' + c + '</html>\n'
631 for n, id in enumerate (msg.files):
632 f = self.db.file.getnode (id)
633 self.assertEqual(f.name, name)
634 self.assertEqual(f.content, content)
635 self.assertEqual(msg.content, c)
636 self.compareMessages(self._get_mail(),
637 '''FROM: roundup-admin@your.tracker.email.domain.example
638 TO: chef@bork.bork.bork, richard@test.test
639 Content-Type: text/plain; charset="iso-8859-1"
640 Subject: [issue1] Testing...
641 To: chef@bork.bork.bork, richard@test.test
642 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
643 Reply-To: Roundup issue tracker
644 <issue_tracker@your.tracker.email.domain.example>
645 MIME-Version: 1.0
646 Message-Id: <followup_dummy_id>
647 In-Reply-To: <dummy_test_message_id>
648 X-Roundup-Name: Roundup issue tracker
649 X-Roundup-Loop: hello
650 X-Roundup-Issue-Status: chatting
651 X-Roundup-Issue-Files: unnamed
652 Content-Transfer-Encoding: quoted-printable
655 Contrary, Mary <mary@test.test> added the comment:
657 umlaut =E4=F6=FC=C4=D6=DC=DF
658 File 'unnamed' not attached - you can download it from http://tracker.examp=
659 le/cgi-bin/roundup.cgi/bugs/file1.
661 ----------
662 status: unread -> chatting
664 _______________________________________________________________________
665 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
666 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
667 _______________________________________________________________________
668 ''')
670 def testMultipartCharsetUTF8AttachFile(self):
671 c = 'umlaut \xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c\xc3\x9f'
672 self.doNewIssue()
673 self._handle_mail(self.multipart_msg_latin1)
674 messages = self.db.issue.get('1', 'messages')
675 messages.sort()
676 msg = self.db.msg.getnode (messages[-1])
677 assert(len(msg.files) == 1)
678 name = 'unnamed'
679 content = '<html>' + c + '</html>\n'
680 for n, id in enumerate (msg.files):
681 f = self.db.file.getnode (id)
682 self.assertEqual(f.name, name)
683 self.assertEqual(f.content, content)
684 self.assertEqual(msg.content, c)
685 self.compareMessages(self._get_mail(),
686 '''FROM: roundup-admin@your.tracker.email.domain.example
687 TO: chef@bork.bork.bork, richard@test.test
688 Content-Type: multipart/mixed; boundary="utf-8"
689 Subject: [issue1] Testing...
690 To: chef@bork.bork.bork, richard@test.test
691 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
692 Reply-To: Roundup issue tracker
693 <issue_tracker@your.tracker.email.domain.example>
694 MIME-Version: 1.0
695 Message-Id: <followup_dummy_id>
696 In-Reply-To: <dummy_test_message_id>
697 X-Roundup-Name: Roundup issue tracker
698 X-Roundup-Loop: hello
699 X-Roundup-Issue-Status: chatting
700 X-Roundup-Issue-Files: unnamed
701 Content-Transfer-Encoding: quoted-printable
704 --utf-8
705 MIME-Version: 1.0
706 Content-Type: text/plain; charset="utf-8"
707 Content-Transfer-Encoding: quoted-printable
710 Contrary, Mary <mary@test.test> added the comment:
712 umlaut =C3=A4=C3=B6=C3=BC=C3=84=C3=96=C3=9C=C3=9F
714 ----------
715 status: unread -> chatting
717 _______________________________________________________________________
718 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
719 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
720 _______________________________________________________________________
721 --utf-8
722 Content-Type: text/html
723 MIME-Version: 1.0
724 Content-Transfer-Encoding: base64
725 Content-Disposition: attachment;
726 filename="unnamed"
728 PGh0bWw+dW1sYXV0IMOkw7bDvMOEw5bDnMOfPC9odG1sPgo=
730 --utf-8--
731 ''')
733 def testMultipartCharsetLatin1AttachFile(self):
734 c = 'umlaut \xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c\xc3\x9f'
735 self.doNewIssue()
736 self.db.config.MAIL_CHARSET = 'iso-8859-1'
737 self._handle_mail(self.multipart_msg_latin1)
738 messages = self.db.issue.get('1', 'messages')
739 messages.sort()
740 msg = self.db.msg.getnode (messages[-1])
741 assert(len(msg.files) == 1)
742 name = 'unnamed'
743 content = '<html>' + c + '</html>\n'
744 for n, id in enumerate (msg.files):
745 f = self.db.file.getnode (id)
746 self.assertEqual(f.name, name)
747 self.assertEqual(f.content, content)
748 self.assertEqual(msg.content, c)
749 self.compareMessages(self._get_mail(),
750 '''FROM: roundup-admin@your.tracker.email.domain.example
751 TO: chef@bork.bork.bork, richard@test.test
752 Content-Type: multipart/mixed; boundary="utf-8"
753 Subject: [issue1] Testing...
754 To: chef@bork.bork.bork, richard@test.test
755 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
756 Reply-To: Roundup issue tracker
757 <issue_tracker@your.tracker.email.domain.example>
758 MIME-Version: 1.0
759 Message-Id: <followup_dummy_id>
760 In-Reply-To: <dummy_test_message_id>
761 X-Roundup-Name: Roundup issue tracker
762 X-Roundup-Loop: hello
763 X-Roundup-Issue-Status: chatting
764 X-Roundup-Issue-Files: unnamed
765 Content-Transfer-Encoding: quoted-printable
768 --utf-8
769 MIME-Version: 1.0
770 Content-Type: text/plain; charset="iso-8859-1"
771 Content-Transfer-Encoding: quoted-printable
774 Contrary, Mary <mary@test.test> added the comment:
776 umlaut =E4=F6=FC=C4=D6=DC=DF
778 ----------
779 status: unread -> chatting
781 _______________________________________________________________________
782 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
783 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
784 _______________________________________________________________________
785 --utf-8
786 Content-Type: text/html
787 MIME-Version: 1.0
788 Content-Transfer-Encoding: base64
789 Content-Disposition: attachment;
790 filename="unnamed"
792 PGh0bWw+dW1sYXV0IMOkw7bDvMOEw5bDnMOfPC9odG1sPgo=
794 --utf-8--
795 ''')
797 def testMultipartRFC822(self):
798 self.doNewIssue()
799 self._handle_mail(self.multipart_msg_rfc822)
800 messages = self.db.issue.get('1', 'messages')
801 messages.sort()
802 msg = self.db.msg.getnode (messages[-1])
803 assert(len(msg.files) == 1)
804 name = "Fwd: Original email subject.eml"
805 for n, id in enumerate (msg.files):
806 f = self.db.file.getnode (id)
807 self.assertEqual(f.name, name)
808 self.assertEqual(msg.content, 'First part: Text')
809 self.compareMessages(self._get_mail(),
810 '''TO: chef@bork.bork.bork, richard@test.test
811 Content-Type: text/plain; charset="utf-8"
812 Subject: [issue1] Testing...
813 To: chef@bork.bork.bork, richard@test.test
814 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
815 Reply-To: Roundup issue tracker
816 <issue_tracker@your.tracker.email.domain.example>
817 MIME-Version: 1.0
818 Message-Id: <followup_dummy_id>
819 In-Reply-To: <dummy_test_message_id>
820 X-Roundup-Name: Roundup issue tracker
821 X-Roundup-Loop: hello
822 X-Roundup-Issue-Status: chatting
823 X-Roundup-Issue-Files: Fwd: Original email subject.eml
824 Content-Transfer-Encoding: quoted-printable
827 --utf-8
828 MIME-Version: 1.0
829 Content-Type: text/plain; charset="utf-8"
830 Content-Transfer-Encoding: quoted-printable
833 Contrary, Mary <mary@test.test> added the comment:
835 First part: Text
837 ----------
838 status: unread -> chatting
840 _______________________________________________________________________
841 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
842 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
843 _______________________________________________________________________
844 --utf-8
845 Content-Type: message/rfc822
846 MIME-Version: 1.0
847 Content-Disposition: attachment;
848 filename="Fwd: Original email subject.eml"
850 Message-Id: <followup_dummy_id_2>
851 In-Reply-To: <dummy_test_message_id_2>
852 MIME-Version: 1.0
853 Subject: Fwd: Original email subject
854 Date: Mon, 23 Aug 2010 08:23:33 +0200
855 Content-Type: multipart/alternative; boundary="090500050101020406060002"
857 This is a multi-part message in MIME format.
858 --090500050101020406060002
859 Content-Type: text/plain; charset=ISO-8859-15; format=flowed
860 Content-Transfer-Encoding: 7bit
862 some text in inner email
863 ========================
865 --090500050101020406060002
866 Content-Type: text/html; charset=ISO-8859-15
867 Content-Transfer-Encoding: 7bit
869 <html>
870 some text in inner email
871 ========================
872 </html>
874 --090500050101020406060002--
876 --utf-8--
877 ''')
879 def testMultipartRFC822Unpack(self):
880 self.doNewIssue()
881 self.db.config.MAILGW_UNPACK_RFC822 = True
882 self._handle_mail(self.multipart_msg_rfc822)
883 messages = self.db.issue.get('1', 'messages')
884 messages.sort()
885 msg = self.db.msg.getnode (messages[-1])
886 self.assertEqual(len(msg.files), 2)
887 t = 'some text in inner email\n========================\n'
888 content = {0 : t, 1 : '<html>\n' + t + '</html>\n'}
889 for n, id in enumerate (msg.files):
890 f = self.db.file.getnode (id)
891 self.assertEqual(f.name, 'unnamed')
892 if n in content :
893 self.assertEqual(f.content, content [n])
894 self.assertEqual(msg.content, 'First part: Text')
896 def testSimpleFollowup(self):
897 self.doNewIssue()
898 self._handle_mail('''Content-Type: text/plain;
899 charset="iso-8859-1"
900 From: mary <mary@test.test>
901 To: issue_tracker@your.tracker.email.domain.example
902 Message-Id: <followup_dummy_id>
903 In-Reply-To: <dummy_test_message_id>
904 Subject: [issue1] Testing...
906 This is a second followup
907 ''')
908 self.compareMessages(self._get_mail(),
909 '''FROM: roundup-admin@your.tracker.email.domain.example
910 TO: chef@bork.bork.bork, richard@test.test
911 Content-Type: text/plain; charset="utf-8"
912 Subject: [issue1] Testing...
913 To: chef@bork.bork.bork, richard@test.test
914 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
915 Reply-To: Roundup issue tracker
916 <issue_tracker@your.tracker.email.domain.example>
917 MIME-Version: 1.0
918 Message-Id: <followup_dummy_id>
919 In-Reply-To: <dummy_test_message_id>
920 X-Roundup-Name: Roundup issue tracker
921 X-Roundup-Loop: hello
922 X-Roundup-Issue-Status: chatting
923 Content-Transfer-Encoding: quoted-printable
926 Contrary, Mary <mary@test.test> added the comment:
928 This is a second followup
930 ----------
931 status: unread -> chatting
933 _______________________________________________________________________
934 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
935 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
936 _______________________________________________________________________
937 ''')
939 def testFollowup(self):
940 self.doNewIssue()
942 self._handle_mail('''Content-Type: text/plain;
943 charset="iso-8859-1"
944 From: richard <richard@test.test>
945 To: issue_tracker@your.tracker.email.domain.example
946 Message-Id: <followup_dummy_id>
947 In-Reply-To: <dummy_test_message_id>
948 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
950 This is a followup
951 ''')
952 l = self.db.issue.get('1', 'nosy')
953 l.sort()
954 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
955 self.john_id])
957 self.compareMessages(self._get_mail(),
958 '''FROM: roundup-admin@your.tracker.email.domain.example
959 TO: chef@bork.bork.bork, john@test.test, mary@test.test
960 Content-Type: text/plain; charset="utf-8"
961 Subject: [issue1] Testing...
962 To: chef@bork.bork.bork, john@test.test, mary@test.test
963 From: richard <issue_tracker@your.tracker.email.domain.example>
964 Reply-To: Roundup issue tracker
965 <issue_tracker@your.tracker.email.domain.example>
966 MIME-Version: 1.0
967 Message-Id: <followup_dummy_id>
968 In-Reply-To: <dummy_test_message_id>
969 X-Roundup-Name: Roundup issue tracker
970 X-Roundup-Loop: hello
971 X-Roundup-Issue-Status: chatting
972 Content-Transfer-Encoding: quoted-printable
975 richard <richard@test.test> added the comment:
977 This is a followup
979 ----------
980 assignedto: -> mary
981 nosy: +john, mary
982 status: unread -> chatting
984 _______________________________________________________________________
985 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
986 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
987 _______________________________________________________________________
988 ''')
990 def testFollowupNoSubjectChange(self):
991 self.db.config.MAILGW_SUBJECT_UPDATES_TITLE = 'no'
992 self.doNewIssue()
994 self._handle_mail('''Content-Type: text/plain;
995 charset="iso-8859-1"
996 From: richard <richard@test.test>
997 To: issue_tracker@your.tracker.email.domain.example
998 Message-Id: <followup_dummy_id>
999 In-Reply-To: <dummy_test_message_id>
1000 Subject: [issue1] Wrzlbrmft... [assignedto=mary; nosy=+john]
1002 This is a followup
1003 ''')
1004 l = self.db.issue.get('1', 'nosy')
1005 l.sort()
1006 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
1007 self.john_id])
1009 self.compareMessages(self._get_mail(),
1010 '''FROM: roundup-admin@your.tracker.email.domain.example
1011 TO: chef@bork.bork.bork, john@test.test, mary@test.test
1012 Content-Type: text/plain; charset="utf-8"
1013 Subject: [issue1] Testing...
1014 To: chef@bork.bork.bork, john@test.test, mary@test.test
1015 From: richard <issue_tracker@your.tracker.email.domain.example>
1016 Reply-To: Roundup issue tracker
1017 <issue_tracker@your.tracker.email.domain.example>
1018 MIME-Version: 1.0
1019 Message-Id: <followup_dummy_id>
1020 In-Reply-To: <dummy_test_message_id>
1021 X-Roundup-Name: Roundup issue tracker
1022 X-Roundup-Loop: hello
1023 X-Roundup-Issue-Status: chatting
1024 Content-Transfer-Encoding: quoted-printable
1027 richard <richard@test.test> added the comment:
1029 This is a followup
1031 ----------
1032 assignedto: -> mary
1033 nosy: +john, mary
1034 status: unread -> chatting
1036 _______________________________________________________________________
1037 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1038 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1039 _______________________________________________________________________
1040 ''')
1041 self.assertEqual(self.db.issue.get('1','title'), 'Testing...')
1043 def testFollowupExplicitSubjectChange(self):
1044 self.doNewIssue()
1046 self._handle_mail('''Content-Type: text/plain;
1047 charset="iso-8859-1"
1048 From: richard <richard@test.test>
1049 To: issue_tracker@your.tracker.email.domain.example
1050 Message-Id: <followup_dummy_id>
1051 In-Reply-To: <dummy_test_message_id>
1052 Subject: [issue1] Wrzlbrmft... [assignedto=mary; nosy=+john; title=new title]
1054 This is a followup
1055 ''')
1056 l = self.db.issue.get('1', 'nosy')
1057 l.sort()
1058 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
1059 self.john_id])
1061 self.compareMessages(self._get_mail(),
1062 '''FROM: roundup-admin@your.tracker.email.domain.example
1063 TO: chef@bork.bork.bork, john@test.test, mary@test.test
1064 Content-Type: text/plain; charset="utf-8"
1065 Subject: [issue1] new title
1066 To: chef@bork.bork.bork, john@test.test, mary@test.test
1067 From: richard <issue_tracker@your.tracker.email.domain.example>
1068 Reply-To: Roundup issue tracker
1069 <issue_tracker@your.tracker.email.domain.example>
1070 MIME-Version: 1.0
1071 Message-Id: <followup_dummy_id>
1072 In-Reply-To: <dummy_test_message_id>
1073 X-Roundup-Name: Roundup issue tracker
1074 X-Roundup-Loop: hello
1075 X-Roundup-Issue-Status: chatting
1076 Content-Transfer-Encoding: quoted-printable
1079 richard <richard@test.test> added the comment:
1081 This is a followup
1083 ----------
1084 assignedto: -> mary
1085 nosy: +john, mary
1086 status: unread -> chatting
1087 title: Testing... -> new title
1089 _______________________________________________________________________
1090 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1091 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1092 _______________________________________________________________________
1093 ''')
1095 def testNosyGeneration(self):
1096 self.db.issue.create(title='test')
1098 # create a nosy message
1099 msg = self.db.msg.create(content='This is a test',
1100 author=self.richard_id, messageid='<dummy_test_message_id>')
1101 self.db.journaltag = 'richard'
1102 l = self.db.issue.create(title='test', messages=[msg],
1103 nosy=[self.chef_id, self.mary_id, self.john_id])
1105 self.compareMessages(self._get_mail(),
1106 '''FROM: roundup-admin@your.tracker.email.domain.example
1107 TO: chef@bork.bork.bork, john@test.test, mary@test.test
1108 Content-Type: text/plain; charset="utf-8"
1109 Subject: [issue2] test
1110 To: chef@bork.bork.bork, john@test.test, mary@test.test
1111 From: richard <issue_tracker@your.tracker.email.domain.example>
1112 Reply-To: Roundup issue tracker
1113 <issue_tracker@your.tracker.email.domain.example>
1114 MIME-Version: 1.0
1115 Message-Id: <dummy_test_message_id>
1116 X-Roundup-Name: Roundup issue tracker
1117 X-Roundup-Loop: hello
1118 X-Roundup-Issue-Status: unread
1119 Content-Transfer-Encoding: quoted-printable
1122 New submission from richard <richard@test.test>:
1124 This is a test
1126 ----------
1127 messages: 1
1128 nosy: Chef, john, mary, richard
1129 status: unread
1130 title: test
1132 _______________________________________________________________________
1133 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1134 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue2>
1135 _______________________________________________________________________
1136 ''')
1138 def testPropertyChangeOnly(self):
1139 self.doNewIssue()
1140 oldvalues = self.db.getnode('issue', '1').copy()
1141 oldvalues['assignedto'] = None
1142 # reconstruct old behaviour: This would reuse the
1143 # database-handle from the doNewIssue above which has committed
1144 # as user "Chef". So we close and reopen the db as that user.
1145 #self.db.close() actually don't close 'cos this empties memorydb
1146 self.db = self.instance.open('Chef')
1147 self.db.issue.set('1', assignedto=self.chef_id)
1148 self.db.commit()
1149 self.db.issue.nosymessage('1', None, oldvalues)
1151 new_mail = ""
1152 for line in self._get_mail().split("\n"):
1153 if "Message-Id: " in line:
1154 continue
1155 if "Date: " in line:
1156 continue
1157 new_mail += line+"\n"
1159 self.compareMessages(new_mail, """
1160 FROM: roundup-admin@your.tracker.email.domain.example
1161 TO: chef@bork.bork.bork, richard@test.test
1162 Content-Type: text/plain; charset="utf-8"
1163 Subject: [issue1] Testing...
1164 To: chef@bork.bork.bork, richard@test.test
1165 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
1166 X-Roundup-Name: Roundup issue tracker
1167 X-Roundup-Loop: hello
1168 X-Roundup-Issue-Status: unread
1169 X-Roundup-Version: 1.3.3
1170 In-Reply-To: <dummy_test_message_id>
1171 MIME-Version: 1.0
1172 Reply-To: Roundup issue tracker
1173 <issue_tracker@your.tracker.email.domain.example>
1174 Content-Transfer-Encoding: quoted-printable
1177 Change by Bork, Chef <chef@bork.bork.bork>:
1180 ----------
1181 assignedto: -> Chef
1183 _______________________________________________________________________
1184 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1185 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1186 _______________________________________________________________________
1187 """)
1190 #
1191 # FOLLOWUP TITLE MATCH
1192 #
1193 def testFollowupTitleMatch(self):
1194 self.doNewIssue()
1195 self._handle_mail('''Content-Type: text/plain;
1196 charset="iso-8859-1"
1197 From: richard <richard@test.test>
1198 To: issue_tracker@your.tracker.email.domain.example
1199 Message-Id: <followup_dummy_id>
1200 Subject: Re: Testing... [assignedto=mary; nosy=+john]
1202 This is a followup
1203 ''')
1204 self.compareMessages(self._get_mail(),
1205 '''FROM: roundup-admin@your.tracker.email.domain.example
1206 TO: chef@bork.bork.bork, john@test.test, mary@test.test
1207 Content-Type: text/plain; charset="utf-8"
1208 Subject: [issue1] Testing...
1209 To: chef@bork.bork.bork, john@test.test, mary@test.test
1210 From: richard <issue_tracker@your.tracker.email.domain.example>
1211 Reply-To: Roundup issue tracker
1212 <issue_tracker@your.tracker.email.domain.example>
1213 MIME-Version: 1.0
1214 Message-Id: <followup_dummy_id>
1215 In-Reply-To: <dummy_test_message_id>
1216 X-Roundup-Name: Roundup issue tracker
1217 X-Roundup-Loop: hello
1218 X-Roundup-Issue-Status: chatting
1219 Content-Transfer-Encoding: quoted-printable
1222 richard <richard@test.test> added the comment:
1224 This is a followup
1226 ----------
1227 assignedto: -> mary
1228 nosy: +john, mary
1229 status: unread -> chatting
1231 _______________________________________________________________________
1232 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1233 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1234 _______________________________________________________________________
1235 ''')
1237 def testFollowupTitleMatchMultiRe(self):
1238 nodeid1 = self.doNewIssue()
1239 nodeid2 = self._handle_mail('''Content-Type: text/plain;
1240 charset="iso-8859-1"
1241 From: richard <richard@test.test>
1242 To: issue_tracker@your.tracker.email.domain.example
1243 Message-Id: <followup_dummy_id>
1244 Subject: Re: Testing... [assignedto=mary; nosy=+john]
1246 This is a followup
1247 ''')
1249 nodeid3 = self._handle_mail('''Content-Type: text/plain;
1250 charset="iso-8859-1"
1251 From: richard <richard@test.test>
1252 To: issue_tracker@your.tracker.email.domain.example
1253 Message-Id: <followup2_dummy_id>
1254 Subject: Ang: Re: Testing...
1256 This is a followup
1257 ''')
1258 self.assertEqual(nodeid1, nodeid2)
1259 self.assertEqual(nodeid1, nodeid3)
1261 def testFollowupTitleMatchNever(self):
1262 nodeid = self.doNewIssue()
1263 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'never'
1264 self.assertNotEqual(self._handle_mail('''Content-Type: text/plain;
1265 charset="iso-8859-1"
1266 From: richard <richard@test.test>
1267 To: issue_tracker@your.tracker.email.domain.example
1268 Message-Id: <followup_dummy_id>
1269 Subject: Re: Testing...
1271 This is a followup
1272 '''), nodeid)
1274 def testFollowupTitleMatchNeverInterval(self):
1275 nodeid = self.doNewIssue()
1276 # force failure of the interval
1277 time.sleep(2)
1278 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation 00:00:01'
1279 self.assertNotEqual(self._handle_mail('''Content-Type: text/plain;
1280 charset="iso-8859-1"
1281 From: richard <richard@test.test>
1282 To: issue_tracker@your.tracker.email.domain.example
1283 Message-Id: <followup_dummy_id>
1284 Subject: Re: Testing...
1286 This is a followup
1287 '''), nodeid)
1290 def testFollowupTitleMatchInterval(self):
1291 nodeid = self.doNewIssue()
1292 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation +1d'
1293 self.assertEqual(self._handle_mail('''Content-Type: text/plain;
1294 charset="iso-8859-1"
1295 From: richard <richard@test.test>
1296 To: issue_tracker@your.tracker.email.domain.example
1297 Message-Id: <followup_dummy_id>
1298 Subject: Re: Testing...
1300 This is a followup
1301 '''), nodeid)
1304 def testFollowupNosyAuthor(self):
1305 self.doNewIssue()
1306 self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
1307 self._handle_mail('''Content-Type: text/plain;
1308 charset="iso-8859-1"
1309 From: john@test.test
1310 To: issue_tracker@your.tracker.email.domain.example
1311 Message-Id: <followup_dummy_id>
1312 In-Reply-To: <dummy_test_message_id>
1313 Subject: [issue1] Testing...
1315 This is a followup
1316 ''')
1318 self.compareMessages(self._get_mail(),
1319 '''FROM: roundup-admin@your.tracker.email.domain.example
1320 TO: chef@bork.bork.bork, richard@test.test
1321 Content-Type: text/plain; charset="utf-8"
1322 Subject: [issue1] Testing...
1323 To: chef@bork.bork.bork, richard@test.test
1324 From: John Doe <issue_tracker@your.tracker.email.domain.example>
1325 Reply-To: Roundup issue tracker
1326 <issue_tracker@your.tracker.email.domain.example>
1327 MIME-Version: 1.0
1328 Message-Id: <followup_dummy_id>
1329 In-Reply-To: <dummy_test_message_id>
1330 X-Roundup-Name: Roundup issue tracker
1331 X-Roundup-Loop: hello
1332 X-Roundup-Issue-Status: chatting
1333 Content-Transfer-Encoding: quoted-printable
1336 John Doe <john@test.test> added the comment:
1338 This is a followup
1340 ----------
1341 nosy: +john
1342 status: unread -> chatting
1344 _______________________________________________________________________
1345 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1346 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1347 _______________________________________________________________________
1349 ''')
1351 def testFollowupNosyRecipients(self):
1352 self.doNewIssue()
1353 self.db.config.ADD_RECIPIENTS_TO_NOSY = 'yes'
1354 self._handle_mail('''Content-Type: text/plain;
1355 charset="iso-8859-1"
1356 From: richard@test.test
1357 To: issue_tracker@your.tracker.email.domain.example
1358 Cc: john@test.test
1359 Message-Id: <followup_dummy_id>
1360 In-Reply-To: <dummy_test_message_id>
1361 Subject: [issue1] Testing...
1363 This is a followup
1364 ''')
1365 self.compareMessages(self._get_mail(),
1366 '''FROM: roundup-admin@your.tracker.email.domain.example
1367 TO: chef@bork.bork.bork
1368 Content-Type: text/plain; charset="utf-8"
1369 Subject: [issue1] Testing...
1370 To: chef@bork.bork.bork
1371 From: richard <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 richard <richard@test.test> added the comment:
1385 This is a followup
1387 ----------
1388 nosy: +john
1389 status: unread -> chatting
1391 _______________________________________________________________________
1392 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1393 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1394 _______________________________________________________________________
1396 ''')
1398 def testFollowupNosyAuthorAndCopy(self):
1399 self.doNewIssue()
1400 self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
1401 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
1402 self._handle_mail('''Content-Type: text/plain;
1403 charset="iso-8859-1"
1404 From: john@test.test
1405 To: issue_tracker@your.tracker.email.domain.example
1406 Message-Id: <followup_dummy_id>
1407 In-Reply-To: <dummy_test_message_id>
1408 Subject: [issue1] Testing...
1410 This is a followup
1411 ''')
1412 self.compareMessages(self._get_mail(),
1413 '''FROM: roundup-admin@your.tracker.email.domain.example
1414 TO: chef@bork.bork.bork, john@test.test, richard@test.test
1415 Content-Type: text/plain; charset="utf-8"
1416 Subject: [issue1] Testing...
1417 To: chef@bork.bork.bork, john@test.test, richard@test.test
1418 From: John Doe <issue_tracker@your.tracker.email.domain.example>
1419 Reply-To: Roundup issue tracker
1420 <issue_tracker@your.tracker.email.domain.example>
1421 MIME-Version: 1.0
1422 Message-Id: <followup_dummy_id>
1423 In-Reply-To: <dummy_test_message_id>
1424 X-Roundup-Name: Roundup issue tracker
1425 X-Roundup-Loop: hello
1426 X-Roundup-Issue-Status: chatting
1427 Content-Transfer-Encoding: quoted-printable
1430 John Doe <john@test.test> added the comment:
1432 This is a followup
1434 ----------
1435 nosy: +john
1436 status: unread -> chatting
1438 _______________________________________________________________________
1439 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1440 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1441 _______________________________________________________________________
1443 ''')
1445 def testFollowupNoNosyAuthor(self):
1446 self.doNewIssue()
1447 self.instance.config.ADD_AUTHOR_TO_NOSY = 'no'
1448 self._handle_mail('''Content-Type: text/plain;
1449 charset="iso-8859-1"
1450 From: john@test.test
1451 To: issue_tracker@your.tracker.email.domain.example
1452 Message-Id: <followup_dummy_id>
1453 In-Reply-To: <dummy_test_message_id>
1454 Subject: [issue1] Testing...
1456 This is a followup
1457 ''')
1458 self.compareMessages(self._get_mail(),
1459 '''FROM: roundup-admin@your.tracker.email.domain.example
1460 TO: chef@bork.bork.bork, richard@test.test
1461 Content-Type: text/plain; charset="utf-8"
1462 Subject: [issue1] Testing...
1463 To: chef@bork.bork.bork, richard@test.test
1464 From: John Doe <issue_tracker@your.tracker.email.domain.example>
1465 Reply-To: Roundup issue tracker
1466 <issue_tracker@your.tracker.email.domain.example>
1467 MIME-Version: 1.0
1468 Message-Id: <followup_dummy_id>
1469 In-Reply-To: <dummy_test_message_id>
1470 X-Roundup-Name: Roundup issue tracker
1471 X-Roundup-Loop: hello
1472 X-Roundup-Issue-Status: chatting
1473 Content-Transfer-Encoding: quoted-printable
1476 John Doe <john@test.test> added the comment:
1478 This is a followup
1480 ----------
1481 status: unread -> chatting
1483 _______________________________________________________________________
1484 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1485 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1486 _______________________________________________________________________
1488 ''')
1490 def testFollowupNoNosyRecipients(self):
1491 self.doNewIssue()
1492 self.instance.config.ADD_RECIPIENTS_TO_NOSY = 'no'
1493 self._handle_mail('''Content-Type: text/plain;
1494 charset="iso-8859-1"
1495 From: richard@test.test
1496 To: issue_tracker@your.tracker.email.domain.example
1497 Cc: john@test.test
1498 Message-Id: <followup_dummy_id>
1499 In-Reply-To: <dummy_test_message_id>
1500 Subject: [issue1] Testing...
1502 This is a followup
1503 ''')
1504 self.compareMessages(self._get_mail(),
1505 '''FROM: roundup-admin@your.tracker.email.domain.example
1506 TO: chef@bork.bork.bork
1507 Content-Type: text/plain; charset="utf-8"
1508 Subject: [issue1] Testing...
1509 To: chef@bork.bork.bork
1510 From: richard <issue_tracker@your.tracker.email.domain.example>
1511 Reply-To: Roundup issue tracker
1512 <issue_tracker@your.tracker.email.domain.example>
1513 MIME-Version: 1.0
1514 Message-Id: <followup_dummy_id>
1515 In-Reply-To: <dummy_test_message_id>
1516 X-Roundup-Name: Roundup issue tracker
1517 X-Roundup-Loop: hello
1518 X-Roundup-Issue-Status: chatting
1519 Content-Transfer-Encoding: quoted-printable
1522 richard <richard@test.test> added the comment:
1524 This is a followup
1526 ----------
1527 status: unread -> chatting
1529 _______________________________________________________________________
1530 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1531 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1532 _______________________________________________________________________
1534 ''')
1536 def testFollowupEmptyMessage(self):
1537 self.doNewIssue()
1539 self._handle_mail('''Content-Type: text/plain;
1540 charset="iso-8859-1"
1541 From: richard <richard@test.test>
1542 To: issue_tracker@your.tracker.email.domain.example
1543 Message-Id: <followup_dummy_id>
1544 In-Reply-To: <dummy_test_message_id>
1545 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
1547 ''')
1548 l = self.db.issue.get('1', 'nosy')
1549 l.sort()
1550 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
1551 self.john_id])
1553 # should be no file created (ie. no message)
1554 assert not os.path.exists(SENDMAILDEBUG)
1556 def testFollowupEmptyMessageNoSubject(self):
1557 self.doNewIssue()
1559 self._handle_mail('''Content-Type: text/plain;
1560 charset="iso-8859-1"
1561 From: richard <richard@test.test>
1562 To: issue_tracker@your.tracker.email.domain.example
1563 Message-Id: <followup_dummy_id>
1564 In-Reply-To: <dummy_test_message_id>
1565 Subject: [issue1] [assignedto=mary; nosy=+john]
1567 ''')
1568 l = self.db.issue.get('1', 'nosy')
1569 l.sort()
1570 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
1571 self.john_id])
1573 # should be no file created (ie. no message)
1574 assert not os.path.exists(SENDMAILDEBUG)
1576 def testNosyRemove(self):
1577 self.doNewIssue()
1579 self._handle_mail('''Content-Type: text/plain;
1580 charset="iso-8859-1"
1581 From: richard <richard@test.test>
1582 To: issue_tracker@your.tracker.email.domain.example
1583 Message-Id: <followup_dummy_id>
1584 In-Reply-To: <dummy_test_message_id>
1585 Subject: [issue1] Testing... [nosy=-richard]
1587 ''')
1588 l = self.db.issue.get('1', 'nosy')
1589 l.sort()
1590 self.assertEqual(l, [self.chef_id])
1592 # NO NOSY MESSAGE SHOULD BE SENT!
1593 assert not os.path.exists(SENDMAILDEBUG)
1595 def testNewUserAuthor(self):
1596 self.db.commit()
1597 l = self.db.user.list()
1598 l.sort()
1599 message = '''Content-Type: text/plain;
1600 charset="iso-8859-1"
1601 From: fubar <fubar@bork.bork.bork>
1602 To: issue_tracker@your.tracker.email.domain.example
1603 Message-Id: <dummy_test_message_id>
1604 Subject: [issue] Testing...
1606 This is a test submission of a new issue.
1607 '''
1608 self.db.security.role['anonymous'].permissions=[]
1609 anonid = self.db.user.lookup('anonymous')
1610 self.db.user.set(anonid, roles='Anonymous')
1611 try:
1612 self._handle_mail(message)
1613 except Unauthorized, value:
1614 body_diff = self.compareMessages(str(value), """
1615 You are not a registered user.
1617 Unknown address: fubar@bork.bork.bork
1618 """)
1619 assert not body_diff, body_diff
1620 else:
1621 raise AssertionError, "Unathorized not raised when handling mail"
1623 # Add Web Access role to anonymous, and try again to make sure
1624 # we get a "please register at:" message this time.
1625 p = [
1626 self.db.security.getPermission('Register', 'user'),
1627 self.db.security.getPermission('Web Access', None),
1628 ]
1629 self.db.security.role['anonymous'].permissions=p
1630 try:
1631 self._handle_mail(message)
1632 except Unauthorized, value:
1633 body_diff = self.compareMessages(str(value), """
1634 You are not a registered user. Please register at:
1636 http://tracker.example/cgi-bin/roundup.cgi/bugs/user?template=register
1638 ...before sending mail to the tracker.
1640 Unknown address: fubar@bork.bork.bork
1641 """)
1642 assert not body_diff, body_diff
1643 else:
1644 raise AssertionError, "Unathorized not raised when handling mail"
1646 # Make sure list of users is the same as before.
1647 m = self.db.user.list()
1648 m.sort()
1649 self.assertEqual(l, m)
1651 # now with the permission
1652 p = [
1653 self.db.security.getPermission('Register', 'user'),
1654 self.db.security.getPermission('Email Access', None),
1655 ]
1656 self.db.security.role['anonymous'].permissions=p
1657 self._handle_mail(message)
1658 m = self.db.user.list()
1659 m.sort()
1660 self.assertNotEqual(l, m)
1662 def testNewUserAuthorEncodedName(self):
1663 l = set(self.db.user.list())
1664 # From: name has Euro symbol in it
1665 message = '''Content-Type: text/plain;
1666 charset="iso-8859-1"
1667 From: =?utf8?b?SOKCrGxsbw==?= <fubar@bork.bork.bork>
1668 To: issue_tracker@your.tracker.email.domain.example
1669 Message-Id: <dummy_test_message_id>
1670 Subject: [issue] Testing...
1672 This is a test submission of a new issue.
1673 '''
1674 p = [
1675 self.db.security.getPermission('Register', 'user'),
1676 self.db.security.getPermission('Email Access', None),
1677 self.db.security.getPermission('Create', 'issue'),
1678 self.db.security.getPermission('Create', 'msg'),
1679 ]
1680 self.db.security.role['anonymous'].permissions = p
1681 self._handle_mail(message)
1682 m = set(self.db.user.list())
1683 new = list(m - l)[0]
1684 name = self.db.user.get(new, 'realname')
1685 self.assertEquals(name, 'H€llo')
1687 def testUnknownUser(self):
1688 l = set(self.db.user.list())
1689 message = '''Content-Type: text/plain;
1690 charset="iso-8859-1"
1691 From: Nonexisting User <nonexisting@bork.bork.bork>
1692 To: issue_tracker@your.tracker.email.domain.example
1693 Message-Id: <dummy_test_message_id>
1694 Subject: [issue] Testing nonexisting user...
1696 This is a test submission of a new issue.
1697 '''
1698 handler = self._create_mailgw(message)
1699 # we want a bounce message:
1700 handler.trapExceptions = 1
1701 ret = handler.main(StringIO(message))
1702 self.compareMessages(self._get_mail(),
1703 '''FROM: Roundup issue tracker <roundup-admin@your.tracker.email.domain.example>
1704 TO: nonexisting@bork.bork.bork
1705 From nobody Tue Jul 14 12:04:11 2009
1706 Content-Type: multipart/mixed; boundary="===============0639262320=="
1707 MIME-Version: 1.0
1708 Subject: Failed issue tracker submission
1709 To: nonexisting@bork.bork.bork
1710 From: Roundup issue tracker <roundup-admin@your.tracker.email.domain.example>
1711 Date: Tue, 14 Jul 2009 12:04:11 +0000
1712 Precedence: bulk
1713 X-Roundup-Name: Roundup issue tracker
1714 X-Roundup-Loop: hello
1715 X-Roundup-Version: 1.4.8
1716 MIME-Version: 1.0
1718 --===============0639262320==
1719 Content-Type: text/plain; charset="us-ascii"
1720 MIME-Version: 1.0
1721 Content-Transfer-Encoding: 7bit
1725 You are not a registered user. Please register at:
1727 http://tracker.example/cgi-bin/roundup.cgi/bugs/user?template=register
1729 ...before sending mail to the tracker.
1731 Unknown address: nonexisting@bork.bork.bork
1733 --===============0639262320==
1734 Content-Type: text/plain; charset="us-ascii"
1735 MIME-Version: 1.0
1736 Content-Transfer-Encoding: 7bit
1738 Content-Type: text/plain;
1739 charset="iso-8859-1"
1740 From: Nonexisting User <nonexisting@bork.bork.bork>
1741 To: issue_tracker@your.tracker.email.domain.example
1742 Message-Id: <dummy_test_message_id>
1743 Subject: [issue] Testing nonexisting user...
1745 This is a test submission of a new issue.
1747 --===============0639262320==--
1748 ''')
1750 def testEnc01(self):
1751 self.db.user.set(self.mary_id,
1752 realname='\xe4\xf6\xfc\xc4\xd6\xdc\xdf, Mary'.decode
1753 ('latin-1').encode('utf-8'))
1754 self.doNewIssue()
1755 self._handle_mail('''Content-Type: text/plain;
1756 charset="iso-8859-1"
1757 From: mary <mary@test.test>
1758 To: issue_tracker@your.tracker.email.domain.example
1759 Message-Id: <followup_dummy_id>
1760 In-Reply-To: <dummy_test_message_id>
1761 Subject: [issue1] Testing...
1762 Content-Type: text/plain;
1763 charset="iso-8859-1"
1764 Content-Transfer-Encoding: quoted-printable
1766 A message with encoding (encoded oe =F6)
1768 ''')
1769 self.compareMessages(self._get_mail(),
1770 '''FROM: roundup-admin@your.tracker.email.domain.example
1771 TO: chef@bork.bork.bork, richard@test.test
1772 Content-Type: text/plain; charset="utf-8"
1773 Subject: [issue1] Testing...
1774 To: chef@bork.bork.bork, richard@test.test
1775 From: =?utf-8?b?w6TDtsO8w4TDlsOcw58sIE1hcnk=?=
1776 <issue_tracker@your.tracker.email.domain.example>
1777 Reply-To: Roundup issue tracker
1778 <issue_tracker@your.tracker.email.domain.example>
1779 MIME-Version: 1.0
1780 Message-Id: <followup_dummy_id>
1781 In-Reply-To: <dummy_test_message_id>
1782 X-Roundup-Name: Roundup issue tracker
1783 X-Roundup-Loop: hello
1784 X-Roundup-Issue-Status: chatting
1785 Content-Transfer-Encoding: quoted-printable
1788 =C3=A4=C3=B6=C3=BC=C3=84=C3=96=C3=9C=C3=9F, Mary <mary@test.test> added the=
1789 comment:
1791 A message with encoding (encoded oe =C3=B6)
1793 ----------
1794 status: unread -> chatting
1796 _______________________________________________________________________
1797 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1798 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1799 _______________________________________________________________________
1800 ''')
1802 def testEncNonUTF8(self):
1803 self.doNewIssue()
1804 self.instance.config.EMAIL_CHARSET = 'iso-8859-1'
1805 self._handle_mail('''Content-Type: text/plain;
1806 charset="iso-8859-1"
1807 From: mary <mary@test.test>
1808 To: issue_tracker@your.tracker.email.domain.example
1809 Message-Id: <followup_dummy_id>
1810 In-Reply-To: <dummy_test_message_id>
1811 Subject: [issue1] Testing...
1812 Content-Type: text/plain;
1813 charset="iso-8859-1"
1814 Content-Transfer-Encoding: quoted-printable
1816 A message with encoding (encoded oe =F6)
1818 ''')
1819 self.compareMessages(self._get_mail(),
1820 '''FROM: roundup-admin@your.tracker.email.domain.example
1821 TO: chef@bork.bork.bork, richard@test.test
1822 Content-Type: text/plain; charset="iso-8859-1"
1823 Subject: [issue1] Testing...
1824 To: chef@bork.bork.bork, richard@test.test
1825 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
1826 Reply-To: Roundup issue tracker
1827 <issue_tracker@your.tracker.email.domain.example>
1828 MIME-Version: 1.0
1829 Message-Id: <followup_dummy_id>
1830 In-Reply-To: <dummy_test_message_id>
1831 X-Roundup-Name: Roundup issue tracker
1832 X-Roundup-Loop: hello
1833 X-Roundup-Issue-Status: chatting
1834 Content-Transfer-Encoding: quoted-printable
1837 Contrary, Mary <mary@test.test> added the comment:
1839 A message with encoding (encoded oe =F6)
1841 ----------
1842 status: unread -> chatting
1844 _______________________________________________________________________
1845 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1846 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1847 _______________________________________________________________________
1848 ''')
1851 def testMultipartEnc01(self):
1852 self.doNewIssue()
1853 self._handle_mail('''Content-Type: text/plain;
1854 charset="iso-8859-1"
1855 From: mary <mary@test.test>
1856 To: issue_tracker@your.tracker.email.domain.example
1857 Message-Id: <followup_dummy_id>
1858 In-Reply-To: <dummy_test_message_id>
1859 Subject: [issue1] Testing...
1860 Content-Type: multipart/mixed;
1861 boundary="----_=_NextPart_000_01"
1863 This message is in MIME format. Since your mail reader does not understand
1864 this format, some or all of this message may not be legible.
1866 ------_=_NextPart_000_01
1867 Content-Type: text/plain;
1868 charset="iso-8859-1"
1869 Content-Transfer-Encoding: quoted-printable
1871 A message with first part encoded (encoded oe =F6)
1873 ''')
1874 self.compareMessages(self._get_mail(),
1875 '''FROM: roundup-admin@your.tracker.email.domain.example
1876 TO: chef@bork.bork.bork, richard@test.test
1877 Content-Type: text/plain; charset="utf-8"
1878 Subject: [issue1] Testing...
1879 To: chef@bork.bork.bork, richard@test.test
1880 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
1881 Reply-To: Roundup issue tracker
1882 <issue_tracker@your.tracker.email.domain.example>
1883 MIME-Version: 1.0
1884 Message-Id: <followup_dummy_id>
1885 In-Reply-To: <dummy_test_message_id>
1886 X-Roundup-Name: Roundup issue tracker
1887 X-Roundup-Loop: hello
1888 X-Roundup-Issue-Status: chatting
1889 Content-Transfer-Encoding: quoted-printable
1892 Contrary, Mary <mary@test.test> added the comment:
1894 A message with first part encoded (encoded oe =C3=B6)
1896 ----------
1897 status: unread -> chatting
1899 _______________________________________________________________________
1900 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1901 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1902 _______________________________________________________________________
1903 ''')
1905 def testContentDisposition(self):
1906 self.doNewIssue()
1907 self._handle_mail('''Content-Type: text/plain;
1908 charset="iso-8859-1"
1909 From: mary <mary@test.test>
1910 To: issue_tracker@your.tracker.email.domain.example
1911 Message-Id: <followup_dummy_id>
1912 In-Reply-To: <dummy_test_message_id>
1913 Subject: [issue1] Testing...
1914 Content-Type: multipart/mixed; boundary="bCsyhTFzCvuiizWE"
1915 Content-Disposition: inline
1918 --bCsyhTFzCvuiizWE
1919 Content-Type: text/plain; charset=us-ascii
1920 Content-Disposition: inline
1922 test attachment binary
1924 --bCsyhTFzCvuiizWE
1925 Content-Type: application/octet-stream
1926 Content-Disposition: attachment; filename="main.dvi"
1927 Content-Transfer-Encoding: base64
1929 SnVzdCBhIHRlc3QgAQo=
1931 --bCsyhTFzCvuiizWE--
1932 ''')
1933 messages = self.db.issue.get('1', 'messages')
1934 messages.sort()
1935 file = self.db.file.getnode (self.db.msg.get(messages[-1], 'files')[0])
1936 self.assertEqual(file.name, 'main.dvi')
1937 self.assertEqual(file.content, 'Just a test \001\n')
1939 def testFollowupStupidQuoting(self):
1940 self.doNewIssue()
1942 self._handle_mail('''Content-Type: text/plain;
1943 charset="iso-8859-1"
1944 From: richard <richard@test.test>
1945 To: issue_tracker@your.tracker.email.domain.example
1946 Message-Id: <followup_dummy_id>
1947 In-Reply-To: <dummy_test_message_id>
1948 Subject: Re: "[issue1] Testing... "
1950 This is a followup
1951 ''')
1952 self.compareMessages(self._get_mail(),
1953 '''FROM: roundup-admin@your.tracker.email.domain.example
1954 TO: chef@bork.bork.bork
1955 Content-Type: text/plain; charset="utf-8"
1956 Subject: [issue1] Testing...
1957 To: chef@bork.bork.bork
1958 From: richard <issue_tracker@your.tracker.email.domain.example>
1959 Reply-To: Roundup issue tracker
1960 <issue_tracker@your.tracker.email.domain.example>
1961 MIME-Version: 1.0
1962 Message-Id: <followup_dummy_id>
1963 In-Reply-To: <dummy_test_message_id>
1964 X-Roundup-Name: Roundup issue tracker
1965 X-Roundup-Loop: hello
1966 X-Roundup-Issue-Status: chatting
1967 Content-Transfer-Encoding: quoted-printable
1970 richard <richard@test.test> added the comment:
1972 This is a followup
1974 ----------
1975 status: unread -> chatting
1977 _______________________________________________________________________
1978 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1979 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1980 _______________________________________________________________________
1981 ''')
1983 def testEmailQuoting(self):
1984 self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
1985 self.innerTestQuoting('''This is a followup
1986 ''')
1988 def testEmailQuotingRemove(self):
1989 self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
1990 self.innerTestQuoting('''Blah blah wrote:
1991 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
1992 > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
1993 >
1995 This is a followup
1996 ''')
1998 def innerTestQuoting(self, expect):
1999 nodeid = self.doNewIssue()
2001 messages = self.db.issue.get(nodeid, 'messages')
2003 self._handle_mail('''Content-Type: text/plain;
2004 charset="iso-8859-1"
2005 From: richard <richard@test.test>
2006 To: issue_tracker@your.tracker.email.domain.example
2007 Message-Id: <followup_dummy_id>
2008 In-Reply-To: <dummy_test_message_id>
2009 Subject: Re: [issue1] Testing...
2011 Blah blah wrote:
2012 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
2013 > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
2014 >
2016 This is a followup
2017 ''')
2018 # figure the new message id
2019 newmessages = self.db.issue.get(nodeid, 'messages')
2020 for msg in messages:
2021 newmessages.remove(msg)
2022 messageid = newmessages[0]
2024 self.compareMessages(self.db.msg.get(messageid, 'content'), expect)
2026 def testUserLookup(self):
2027 i = self.db.user.create(username='user1', address='user1@foo.com')
2028 self.assertEqual(uidFromAddress(self.db, ('', 'user1@foo.com'), 0), i)
2029 self.assertEqual(uidFromAddress(self.db, ('', 'USER1@foo.com'), 0), i)
2030 i = self.db.user.create(username='user2', address='USER2@foo.com')
2031 self.assertEqual(uidFromAddress(self.db, ('', 'USER2@foo.com'), 0), i)
2032 self.assertEqual(uidFromAddress(self.db, ('', 'user2@foo.com'), 0), i)
2034 def testUserAlternateLookup(self):
2035 i = self.db.user.create(username='user1', address='user1@foo.com',
2036 alternate_addresses='user1@bar.com')
2037 self.assertEqual(uidFromAddress(self.db, ('', 'user1@bar.com'), 0), i)
2038 self.assertEqual(uidFromAddress(self.db, ('', 'USER1@bar.com'), 0), i)
2040 def testUserCreate(self):
2041 i = uidFromAddress(self.db, ('', 'user@foo.com'), 1)
2042 self.assertNotEqual(uidFromAddress(self.db, ('', 'user@bar.com'), 1), i)
2044 def testRFC2822(self):
2045 ascii_header = "[issue243] This is a \"test\" - with 'quotation' marks"
2046 unicode_header = '[issue244] \xd0\xb0\xd0\xbd\xd0\xb4\xd1\x80\xd0\xb5\xd0\xb9'
2047 unicode_encoded = '=?utf-8?q?[issue244]_=D0=B0=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?='
2048 self.assertEqual(rfc2822.encode_header(ascii_header), ascii_header)
2049 self.assertEqual(rfc2822.encode_header(unicode_header), unicode_encoded)
2051 def testRegistrationConfirmation(self):
2052 otk = "Aj4euk4LZSAdwePohj90SME5SpopLETL"
2053 self.db.getOTKManager().set(otk, username='johannes')
2054 self._handle_mail('''Content-Type: text/plain;
2055 charset="iso-8859-1"
2056 From: Chef <chef@bork.bork.bork>
2057 To: issue_tracker@your.tracker.email.domain.example
2058 Cc: richard@test.test
2059 Message-Id: <dummy_test_message_id>
2060 Subject: Re: Complete your registration to Roundup issue tracker
2061 -- key %s
2063 This is a test confirmation of registration.
2064 ''' % otk)
2065 self.db.user.lookup('johannes')
2067 def testFollowupOnNonIssue(self):
2068 self.db.keyword.create(name='Foo')
2069 self._handle_mail('''Content-Type: text/plain;
2070 charset="iso-8859-1"
2071 From: richard <richard@test.test>
2072 To: issue_tracker@your.tracker.email.domain.example
2073 Message-Id: <followup_dummy_id>
2074 In-Reply-To: <dummy_test_message_id>
2075 Subject: [keyword1] Testing... [name=Bar]
2077 ''')
2078 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
2080 def testResentFrom(self):
2081 nodeid = self._handle_mail('''Content-Type: text/plain;
2082 charset="iso-8859-1"
2083 From: Chef <chef@bork.bork.bork>
2084 Resent-From: mary <mary@test.test>
2085 To: issue_tracker@your.tracker.email.domain.example
2086 Cc: richard@test.test
2087 Message-Id: <dummy_test_message_id>
2088 Subject: [issue] Testing...
2090 This is a test submission of a new issue.
2091 ''')
2092 assert not os.path.exists(SENDMAILDEBUG)
2093 l = self.db.issue.get(nodeid, 'nosy')
2094 l.sort()
2095 self.assertEqual(l, [self.richard_id, self.mary_id])
2096 return nodeid
2098 def testDejaVu(self):
2099 self.assertRaises(IgnoreLoop, self._handle_mail,
2100 '''Content-Type: text/plain;
2101 charset="iso-8859-1"
2102 From: Chef <chef@bork.bork.bork>
2103 X-Roundup-Loop: hello
2104 To: issue_tracker@your.tracker.email.domain.example
2105 Cc: richard@test.test
2106 Message-Id: <dummy_test_message_id>
2107 Subject: Re: [issue] Testing...
2109 Hi, I've been mis-configured to loop messages back to myself.
2110 ''')
2112 def testItsBulkStupid(self):
2113 self.assertRaises(IgnoreBulk, self._handle_mail,
2114 '''Content-Type: text/plain;
2115 charset="iso-8859-1"
2116 From: Chef <chef@bork.bork.bork>
2117 Precedence: bulk
2118 To: issue_tracker@your.tracker.email.domain.example
2119 Cc: richard@test.test
2120 Message-Id: <dummy_test_message_id>
2121 Subject: Re: [issue] Testing...
2123 Hi, I'm on holidays, and this is a dumb auto-responder.
2124 ''')
2126 def testAutoReplyEmailsAreIgnored(self):
2127 self.assertRaises(IgnoreBulk, self._handle_mail,
2128 '''Content-Type: text/plain;
2129 charset="iso-8859-1"
2130 From: Chef <chef@bork.bork.bork>
2131 To: issue_tracker@your.tracker.email.domain.example
2132 Cc: richard@test.test
2133 Message-Id: <dummy_test_message_id>
2134 Subject: Re: [issue] Out of office AutoReply: Back next week
2136 Hi, I am back in the office next week
2137 ''')
2139 def testNoSubject(self):
2140 self.assertRaises(MailUsageError, self._handle_mail,
2141 '''Content-Type: text/plain;
2142 charset="iso-8859-1"
2143 From: Chef <chef@bork.bork.bork>
2144 To: issue_tracker@your.tracker.email.domain.example
2145 Cc: richard@test.test
2146 Reply-To: chef@bork.bork.bork
2147 Message-Id: <dummy_test_message_id>
2149 ''')
2151 #
2152 # TEST FOR INVALID DESIGNATOR HANDLING
2153 #
2154 def testInvalidDesignator(self):
2155 self.assertRaises(MailUsageError, self._handle_mail,
2156 '''Content-Type: text/plain;
2157 charset="iso-8859-1"
2158 From: Chef <chef@bork.bork.bork>
2159 To: issue_tracker@your.tracker.email.domain.example
2160 Subject: [frobulated] testing
2161 Cc: richard@test.test
2162 Reply-To: chef@bork.bork.bork
2163 Message-Id: <dummy_test_message_id>
2165 ''')
2166 self.assertRaises(MailUsageError, self._handle_mail,
2167 '''Content-Type: text/plain;
2168 charset="iso-8859-1"
2169 From: Chef <chef@bork.bork.bork>
2170 To: issue_tracker@your.tracker.email.domain.example
2171 Subject: [issue12345] testing
2172 Cc: richard@test.test
2173 Reply-To: chef@bork.bork.bork
2174 Message-Id: <dummy_test_message_id>
2176 ''')
2178 def testInvalidClassLoose(self):
2179 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
2180 nodeid = self._handle_mail('''Content-Type: text/plain;
2181 charset="iso-8859-1"
2182 From: Chef <chef@bork.bork.bork>
2183 To: issue_tracker@your.tracker.email.domain.example
2184 Subject: [frobulated] testing
2185 Cc: richard@test.test
2186 Reply-To: chef@bork.bork.bork
2187 Message-Id: <dummy_test_message_id>
2189 ''')
2190 assert not os.path.exists(SENDMAILDEBUG)
2191 self.assertEqual(self.db.issue.get(nodeid, 'title'),
2192 '[frobulated] testing')
2194 def testInvalidClassLooseReply(self):
2195 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
2196 nodeid = self._handle_mail('''Content-Type: text/plain;
2197 charset="iso-8859-1"
2198 From: Chef <chef@bork.bork.bork>
2199 To: issue_tracker@your.tracker.email.domain.example
2200 Subject: Re: [frobulated] testing
2201 Cc: richard@test.test
2202 Reply-To: chef@bork.bork.bork
2203 Message-Id: <dummy_test_message_id>
2205 ''')
2206 assert not os.path.exists(SENDMAILDEBUG)
2207 self.assertEqual(self.db.issue.get(nodeid, 'title'),
2208 '[frobulated] testing')
2210 def testInvalidClassLoose(self):
2211 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
2212 nodeid = self._handle_mail('''Content-Type: text/plain;
2213 charset="iso-8859-1"
2214 From: Chef <chef@bork.bork.bork>
2215 To: issue_tracker@your.tracker.email.domain.example
2216 Subject: [issue1234] testing
2217 Cc: richard@test.test
2218 Reply-To: chef@bork.bork.bork
2219 Message-Id: <dummy_test_message_id>
2221 ''')
2222 assert not os.path.exists(SENDMAILDEBUG)
2223 self.assertEqual(self.db.issue.get(nodeid, 'title'),
2224 '[issue1234] testing')
2226 def testClassLooseOK(self):
2227 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
2228 self.db.keyword.create(name='Foo')
2229 nodeid = self._handle_mail('''Content-Type: text/plain;
2230 charset="iso-8859-1"
2231 From: Chef <chef@bork.bork.bork>
2232 To: issue_tracker@your.tracker.email.domain.example
2233 Subject: [keyword1] Testing... [name=Bar]
2234 Cc: richard@test.test
2235 Reply-To: chef@bork.bork.bork
2236 Message-Id: <dummy_test_message_id>
2238 ''')
2239 assert not os.path.exists(SENDMAILDEBUG)
2240 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
2242 def testClassStrictInvalid(self):
2243 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'strict'
2244 self.instance.config.MAILGW_DEFAULT_CLASS = ''
2246 message = '''Content-Type: text/plain;
2247 charset="iso-8859-1"
2248 From: Chef <chef@bork.bork.bork>
2249 To: issue_tracker@your.tracker.email.domain.example
2250 Subject: Testing...
2251 Cc: richard@test.test
2252 Reply-To: chef@bork.bork.bork
2253 Message-Id: <dummy_test_message_id>
2255 '''
2256 self.assertRaises(MailUsageError, self._handle_mail, message)
2258 def testClassStrictValid(self):
2259 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'strict'
2260 self.instance.config.MAILGW_DEFAULT_CLASS = ''
2262 nodeid = self._handle_mail('''Content-Type: text/plain;
2263 charset="iso-8859-1"
2264 From: Chef <chef@bork.bork.bork>
2265 To: issue_tracker@your.tracker.email.domain.example
2266 Subject: [issue] Testing...
2267 Cc: richard@test.test
2268 Reply-To: chef@bork.bork.bork
2269 Message-Id: <dummy_test_message_id>
2271 ''')
2273 assert not os.path.exists(SENDMAILDEBUG)
2274 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
2276 #
2277 # TEST FOR INVALID COMMANDS HANDLING
2278 #
2279 def testInvalidCommands(self):
2280 self.assertRaises(MailUsageError, self._handle_mail,
2281 '''Content-Type: text/plain;
2282 charset="iso-8859-1"
2283 From: Chef <chef@bork.bork.bork>
2284 To: issue_tracker@your.tracker.email.domain.example
2285 Subject: testing [frobulated]
2286 Cc: richard@test.test
2287 Reply-To: chef@bork.bork.bork
2288 Message-Id: <dummy_test_message_id>
2290 ''')
2292 def testInvalidCommandPassthrough(self):
2293 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'none'
2294 nodeid = self._handle_mail('''Content-Type: text/plain;
2295 charset="iso-8859-1"
2296 From: Chef <chef@bork.bork.bork>
2297 To: issue_tracker@your.tracker.email.domain.example
2298 Subject: testing [frobulated]
2299 Cc: richard@test.test
2300 Reply-To: chef@bork.bork.bork
2301 Message-Id: <dummy_test_message_id>
2303 ''')
2304 assert not os.path.exists(SENDMAILDEBUG)
2305 self.assertEqual(self.db.issue.get(nodeid, 'title'),
2306 'testing [frobulated]')
2308 def testInvalidCommandPassthroughLoose(self):
2309 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'loose'
2310 nodeid = self._handle_mail('''Content-Type: text/plain;
2311 charset="iso-8859-1"
2312 From: Chef <chef@bork.bork.bork>
2313 To: issue_tracker@your.tracker.email.domain.example
2314 Subject: testing [frobulated]
2315 Cc: richard@test.test
2316 Reply-To: chef@bork.bork.bork
2317 Message-Id: <dummy_test_message_id>
2319 ''')
2320 assert not os.path.exists(SENDMAILDEBUG)
2321 self.assertEqual(self.db.issue.get(nodeid, 'title'),
2322 'testing [frobulated]')
2324 def testInvalidCommandPassthroughLooseOK(self):
2325 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'loose'
2326 nodeid = self._handle_mail('''Content-Type: text/plain;
2327 charset="iso-8859-1"
2328 From: Chef <chef@bork.bork.bork>
2329 To: issue_tracker@your.tracker.email.domain.example
2330 Subject: testing [assignedto=mary]
2331 Cc: richard@test.test
2332 Reply-To: chef@bork.bork.bork
2333 Message-Id: <dummy_test_message_id>
2335 ''')
2336 assert not os.path.exists(SENDMAILDEBUG)
2337 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing')
2338 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), self.mary_id)
2340 def testCommandDelimiters(self):
2341 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
2342 nodeid = self._handle_mail('''Content-Type: text/plain;
2343 charset="iso-8859-1"
2344 From: Chef <chef@bork.bork.bork>
2345 To: issue_tracker@your.tracker.email.domain.example
2346 Subject: testing {assignedto=mary}
2347 Cc: richard@test.test
2348 Reply-To: chef@bork.bork.bork
2349 Message-Id: <dummy_test_message_id>
2351 ''')
2352 assert not os.path.exists(SENDMAILDEBUG)
2353 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing')
2354 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), self.mary_id)
2356 def testPrefixDelimiters(self):
2357 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
2358 self.db.keyword.create(name='Foo')
2359 self._handle_mail('''Content-Type: text/plain;
2360 charset="iso-8859-1"
2361 From: richard <richard@test.test>
2362 To: issue_tracker@your.tracker.email.domain.example
2363 Message-Id: <followup_dummy_id>
2364 In-Reply-To: <dummy_test_message_id>
2365 Subject: {keyword1} Testing... {name=Bar}
2367 ''')
2368 assert not os.path.exists(SENDMAILDEBUG)
2369 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
2371 def testCommandDelimitersIgnore(self):
2372 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
2373 nodeid = self._handle_mail('''Content-Type: text/plain;
2374 charset="iso-8859-1"
2375 From: Chef <chef@bork.bork.bork>
2376 To: issue_tracker@your.tracker.email.domain.example
2377 Subject: testing [assignedto=mary]
2378 Cc: richard@test.test
2379 Reply-To: chef@bork.bork.bork
2380 Message-Id: <dummy_test_message_id>
2382 ''')
2383 assert not os.path.exists(SENDMAILDEBUG)
2384 self.assertEqual(self.db.issue.get(nodeid, 'title'),
2385 'testing [assignedto=mary]')
2386 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), None)
2388 def testReplytoMatch(self):
2389 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
2390 nodeid = self.doNewIssue()
2391 nodeid2 = self._handle_mail('''Content-Type: text/plain;
2392 charset="iso-8859-1"
2393 From: Chef <chef@bork.bork.bork>
2394 To: issue_tracker@your.tracker.email.domain.example
2395 Message-Id: <dummy_test_message_id2>
2396 In-Reply-To: <dummy_test_message_id>
2397 Subject: Testing...
2399 Followup message.
2400 ''')
2402 nodeid3 = self._handle_mail('''Content-Type: text/plain;
2403 charset="iso-8859-1"
2404 From: Chef <chef@bork.bork.bork>
2405 To: issue_tracker@your.tracker.email.domain.example
2406 Message-Id: <dummy_test_message_id3>
2407 In-Reply-To: <dummy_test_message_id2>
2408 Subject: Testing...
2410 Yet another message in the same thread/issue.
2411 ''')
2413 self.assertEqual(nodeid, nodeid2)
2414 self.assertEqual(nodeid, nodeid3)
2416 def testHelpSubject(self):
2417 message = '''Content-Type: text/plain;
2418 charset="iso-8859-1"
2419 From: Chef <chef@bork.bork.bork>
2420 To: issue_tracker@your.tracker.email.domain.example
2421 Message-Id: <dummy_test_message_id2>
2422 In-Reply-To: <dummy_test_message_id>
2423 Subject: hElp
2426 '''
2427 self.assertRaises(MailUsageHelp, self._handle_mail, message)
2429 def testMaillistSubject(self):
2430 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '[]'
2431 self.db.keyword.create(name='Foo')
2432 self._handle_mail('''Content-Type: text/plain;
2433 charset="iso-8859-1"
2434 From: Chef <chef@bork.bork.bork>
2435 To: issue_tracker@your.tracker.email.domain.example
2436 Subject: [mailinglist-name] [keyword1] Testing.. [name=Bar]
2437 Cc: richard@test.test
2438 Reply-To: chef@bork.bork.bork
2439 Message-Id: <dummy_test_message_id>
2441 ''')
2443 assert not os.path.exists(SENDMAILDEBUG)
2444 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
2446 def testUnknownPrefixSubject(self):
2447 self.db.keyword.create(name='Foo')
2448 self._handle_mail('''Content-Type: text/plain;
2449 charset="iso-8859-1"
2450 From: Chef <chef@bork.bork.bork>
2451 To: issue_tracker@your.tracker.email.domain.example
2452 Subject: VeryStrangeRe: [keyword1] Testing.. [name=Bar]
2453 Cc: richard@test.test
2454 Reply-To: chef@bork.bork.bork
2455 Message-Id: <dummy_test_message_id>
2457 ''')
2459 assert not os.path.exists(SENDMAILDEBUG)
2460 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
2462 def testOneCharSubject(self):
2463 message = '''Content-Type: text/plain;
2464 charset="iso-8859-1"
2465 From: Chef <chef@bork.bork.bork>
2466 To: issue_tracker@your.tracker.email.domain.example
2467 Subject: b
2468 Cc: richard@test.test
2469 Reply-To: chef@bork.bork.bork
2470 Message-Id: <dummy_test_message_id>
2472 '''
2473 try:
2474 self._handle_mail(message)
2475 except MailUsageError:
2476 self.fail('MailUsageError raised')
2478 def testIssueidLast(self):
2479 nodeid1 = self.doNewIssue()
2480 nodeid2 = self._handle_mail('''Content-Type: text/plain;
2481 charset="iso-8859-1"
2482 From: mary <mary@test.test>
2483 To: issue_tracker@your.tracker.email.domain.example
2484 Message-Id: <followup_dummy_id>
2485 In-Reply-To: <dummy_test_message_id>
2486 Subject: New title [issue1]
2488 This is a second followup
2489 ''')
2491 assert nodeid1 == nodeid2
2492 self.assertEqual(self.db.issue.get(nodeid2, 'title'), "Testing...")
2494 def testSecurityMessagePermissionContent(self):
2495 id = self.doNewIssue()
2496 issue = self.db.issue.getnode (id)
2497 self.db.security.addRole(name='Nomsg')
2498 self.db.security.addPermissionToRole('Nomsg', 'Email Access')
2499 for cl in 'issue', 'file', 'keyword':
2500 for p in 'View', 'Edit', 'Create':
2501 self.db.security.addPermissionToRole('Nomsg', p, cl)
2502 self.db.user.set(self.mary_id, roles='Nomsg')
2503 nodeid = self._handle_mail('''Content-Type: text/plain;
2504 charset="iso-8859-1"
2505 From: Chef <chef@bork.bork.bork>
2506 To: issue_tracker@your.tracker.email.domain.example
2507 Message-Id: <dummy_test_message_id_2>
2508 Subject: [issue%(id)s] Testing... [nosy=+mary]
2510 Just a test reply
2511 '''%locals())
2512 assert os.path.exists(SENDMAILDEBUG)
2513 self.compareMessages(self._get_mail(),
2514 '''FROM: roundup-admin@your.tracker.email.domain.example
2515 TO: chef@bork.bork.bork, richard@test.test
2516 Content-Type: text/plain; charset="utf-8"
2517 Subject: [issue1] Testing...
2518 To: richard@test.test
2519 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
2520 Reply-To: Roundup issue tracker
2521 <issue_tracker@your.tracker.email.domain.example>
2522 MIME-Version: 1.0
2523 Message-Id: <dummy_test_message_id_2>
2524 In-Reply-To: <dummy_test_message_id>
2525 X-Roundup-Name: Roundup issue tracker
2526 X-Roundup-Loop: hello
2527 X-Roundup-Issue-Status: chatting
2528 Content-Transfer-Encoding: quoted-printable
2531 Bork, Chef <chef@bork.bork.bork> added the comment:
2533 Just a test reply
2535 ----------
2536 nosy: +mary
2537 status: unread -> chatting
2539 _______________________________________________________________________
2540 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
2541 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
2542 _______________________________________________________________________
2543 ''')
2545 def testOutlookAttachment(self):
2546 message = '''X-MimeOLE: Produced By Microsoft Exchange V6.5
2547 Content-class: urn:content-classes:message
2548 MIME-Version: 1.0
2549 Content-Type: multipart/mixed;
2550 boundary="----_=_NextPart_001_01CACA65.40A51CBC"
2551 Subject: Example of a failed outlook attachment e-mail
2552 Date: Tue, 23 Mar 2010 01:43:44 -0700
2553 Message-ID: <CA37F17219784343816CA6613D2E339205E7D0F9@nrcwstexb1.nrc.ca>
2554 X-MS-Has-Attach: yes
2555 X-MS-TNEF-Correlator:
2556 Thread-Topic: Example of a failed outlook attachment e-mail
2557 Thread-Index: AcrKJo/t3pUBBwTpSwWNE3LE67UBDQ==
2558 From: "Hugh" <richard@test.test>
2559 To: <richard@test.test>
2560 X-OriginalArrivalTime: 23 Mar 2010 08:45:57.0350 (UTC) FILETIME=[41893860:01CACA65]
2562 This is a multi-part message in MIME format.
2564 ------_=_NextPart_001_01CACA65.40A51CBC
2565 Content-Type: multipart/alternative;
2566 boundary="----_=_NextPart_002_01CACA65.40A51CBC"
2569 ------_=_NextPart_002_01CACA65.40A51CBC
2570 Content-Type: text/plain;
2571 charset="us-ascii"
2572 Content-Transfer-Encoding: quoted-printable
2575 Hi Richard,
2577 I suppose this isn't the exact message that was sent but is a resend of
2578 one of my trial messages that failed. For your benefit I changed the
2579 subject line and am adding these words to the message body. Should
2580 still be as problematic, but if you like I can resend an exact copy of a
2581 failed message changing nothing except putting your address instead of
2582 our tracker.
2584 Thanks very much for taking time to look into this. Much appreciated.
2586 <<battery backup>>=20
2588 ------_=_NextPart_002_01CACA65.40A51CBC
2589 Content-Type: text/html;
2590 charset="us-ascii"
2591 Content-Transfer-Encoding: quoted-printable
2593 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
2594 <HTML>
2595 <HEAD>
2596 <META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =
2597 charset=3Dus-ascii">
2598 <META NAME=3D"Generator" CONTENT=3D"MS Exchange Server version =
2599 6.5.7654.12">
2600 <TITLE>Example of a failed outlook attachment e-mail</TITLE>
2601 </HEAD>
2602 <BODY>
2603 <!-- Converted from text/rtf format -->
2604 <BR>
2606 <P><FONT SIZE=3D2 FACE=3D"Arial">Hi Richard,</FONT>
2607 </P>
2609 <P><FONT SIZE=3D2 FACE=3D"Arial">I suppose this isn't the exact message =
2610 that was sent but is a resend of one of my trial messages that =
2611 failed. For your benefit I changed the subject line and am adding =
2612 these words to the message body. Should still be as problematic, =
2613 but if you like I can resend an exact copy of a failed message changing =
2614 nothing except putting your address instead of our tracker.</FONT></P>
2616 <P><FONT SIZE=3D2 FACE=3D"Arial">Thanks very much for taking time to =
2617 look into this. Much appreciated.</FONT>
2618 </P>
2619 <BR>
2621 <P><FONT FACE=3D"Arial" SIZE=3D2 COLOR=3D"#000000"> <<battery =
2622 backup>> </FONT>
2623 </P>
2625 </BODY>
2626 </HTML>
2627 ------_=_NextPart_002_01CACA65.40A51CBC--
2629 ------_=_NextPart_001_01CACA65.40A51CBC
2630 Content-Type: message/rfc822
2631 Content-Transfer-Encoding: 7bit
2633 X-MimeOLE: Produced By Microsoft Exchange V6.5
2634 MIME-Version: 1.0
2635 Content-Type: multipart/alternative;
2636 boundary="----_=_NextPart_003_01CAC15A.29717800"
2637 X-OriginalArrivalTime: 11 Mar 2010 20:33:51.0249 (UTC) FILETIME=[28FEE010:01CAC15A]
2638 Content-class: urn:content-classes:message
2639 Subject: battery backup
2640 Date: Thu, 11 Mar 2010 13:33:43 -0700
2641 Message-ID: <p06240809c7bf02f9624c@[128.114.22.203]>
2642 X-MS-Has-Attach:
2643 X-MS-TNEF-Correlator:
2644 Thread-Topic: battery backup
2645 Thread-Index: AcrBWimtulTrSvBdQ2CcfZ8lyQdxmQ==
2646 From: "Jerry" <jerry@test.test>
2647 To: "Hugh" <hugh@test.test>
2649 This is a multi-part message in MIME format.
2651 ------_=_NextPart_003_01CAC15A.29717800
2652 Content-Type: text/plain;
2653 charset="iso-8859-1"
2654 Content-Transfer-Encoding: quoted-printable
2656 Dear Hugh,
2657 A car batter has an energy capacity of ~ 500Wh. A UPS=20
2658 battery is worse than this.
2660 if we need to provied 100kW for 30 minutes that will take 100 car=20
2661 batteries. This seems like an awful lot of batteries.
2663 Of course I like your idea of making the time 1 minute, so we get to=20
2664 a more modest number of batteries
2666 Jerry
2669 ------_=_NextPart_003_01CAC15A.29717800
2670 Content-Type: text/html;
2671 charset="iso-8859-1"
2672 Content-Transfer-Encoding: quoted-printable
2674 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
2675 <HTML>
2676 <HEAD>
2677 <META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =
2678 charset=3Diso-8859-1">
2679 <META NAME=3D"Generator" CONTENT=3D"MS Exchange Server version =
2680 6.5.7654.12">
2681 <TITLE>battery backup</TITLE>
2682 </HEAD>
2683 <BODY>
2684 <!-- Converted from text/plain format -->
2686 <P><FONT SIZE=3D2>Dear Hugh,</FONT>
2688 <BR> <FONT SIZE=3D2>A car =
2689 batter has an energy capacity of ~ 500Wh. A UPS </FONT>
2691 <BR><FONT SIZE=3D2>battery is worse than this.</FONT>
2692 </P>
2694 <P><FONT SIZE=3D2>if we need to provied 100kW for 30 minutes that will =
2695 take 100 car </FONT>
2697 <BR><FONT SIZE=3D2>batteries. This seems like an awful lot of =
2698 batteries.</FONT>
2699 </P>
2701 <P><FONT SIZE=3D2>Of course I like your idea of making the time 1 =
2702 minute, so we get to </FONT>
2704 <BR><FONT SIZE=3D2>a more modest number of batteries</FONT>
2705 </P>
2707 <P><FONT SIZE=3D2>Jerry</FONT>
2708 </P>
2710 </BODY>
2711 </HTML>
2712 ------_=_NextPart_003_01CAC15A.29717800--
2714 ------_=_NextPart_001_01CACA65.40A51CBC--
2715 '''
2716 nodeid = self._handle_mail(message)
2717 assert not os.path.exists(SENDMAILDEBUG)
2718 msgid = self.db.issue.get(nodeid, 'messages')[0]
2719 self.assert_(self.db.msg.get(msgid, 'content').startswith('Hi Richard'))
2720 self.assertEqual(self.db.msg.get(msgid, 'files'), ['1', '2'])
2721 fileid = self.db.msg.get(msgid, 'files')[0]
2722 self.assertEqual(self.db.file.get(fileid, 'type'), 'text/html')
2723 fileid = self.db.msg.get(msgid, 'files')[1]
2724 self.assertEqual(self.db.file.get(fileid, 'type'), 'message/rfc822')
2726 def testForwardedMessageAttachment(self):
2727 message = '''Return-Path: <rgg@test.test>
2728 Received: from localhost(127.0.0.1), claiming to be "[115.130.26.69]"
2729 via SMTP by localhost, id smtpdAAApLaWrq; Tue Apr 13 23:10:05 2010
2730 Message-ID: <4BC4F9C7.50409@test.test>
2731 Date: Wed, 14 Apr 2010 09:09:59 +1000
2732 From: Rupert Goldie <rgg@test.test>
2733 User-Agent: Thunderbird 2.0.0.24 (Windows/20100228)
2734 MIME-Version: 1.0
2735 To: ekit issues <issues@test.test>
2736 Subject: [Fwd: PHP ERROR (fb)] post limit reached
2737 Content-Type: multipart/mixed; boundary="------------000807090608060304010403"
2739 This is a multi-part message in MIME format.
2740 --------------000807090608060304010403
2741 Content-Type: text/plain; charset=ISO-8859-1; format=flowed
2742 Content-Transfer-Encoding: 7bit
2744 Catch this exception and log it without emailing.
2746 --------------000807090608060304010403
2747 Content-Type: message/rfc822; name="PHP ERROR (fb).eml"
2748 Content-Transfer-Encoding: 7bit
2749 Content-Disposition: inline; filename="PHP ERROR (fb).eml"
2751 Return-Path: <ektravj@test.test>
2752 X-Sieve: CMU Sieve 2.2
2753 via SMTP by crown.off.ekorp.com, id smtpdAAA1JaW1o; Tue Apr 13 23:01:04 2010
2754 X-Virus-Scanned: by amavisd-new at ekit.com
2755 To: facebook-errors@test.test
2756 From: ektravj@test.test
2757 Subject: PHP ERROR (fb)
2758 Message-Id: <20100413230100.D601D27E84@mail2.elax3.ekorp.com>
2759 Date: Tue, 13 Apr 2010 23:01:00 +0000 (UTC)
2761 [13-Apr-2010 22:49:02] PHP Fatal error: Uncaught exception 'Exception' with message 'Facebook Error Message: Feed action request limit reached' in /app/01/www/virtual/fb.ekit.com/htdocs/includes/functions.php:280
2762 Stack trace:
2763 #0 /app/01/www/virtual/fb.ekit.com/htdocs/gateway/ekit/feed/index.php(178): fb_exceptions(Object(FacebookRestClientException))
2764 #1 {main}
2765 thrown in /app/01/www/virtual/fb.ekit.com/htdocs/includes/functions.php on line 280
2768 --------------000807090608060304010403--
2769 '''
2770 nodeid = self._handle_mail(message)
2771 assert not os.path.exists(SENDMAILDEBUG)
2772 msgid = self.db.issue.get(nodeid, 'messages')[0]
2773 self.assertEqual(self.db.msg.get(msgid, 'content'),
2774 'Catch this exception and log it without emailing.')
2775 self.assertEqual(self.db.msg.get(msgid, 'files'), ['1'])
2776 fileid = self.db.msg.get(msgid, 'files')[0]
2777 self.assertEqual(self.db.file.get(fileid, 'type'), 'message/rfc822')
2779 def test_suite():
2780 suite = unittest.TestSuite()
2781 suite.addTest(unittest.makeSuite(MailgwTestCase))
2782 return suite
2784 if __name__ == '__main__':
2785 runner = unittest.TextTestRunner()
2786 unittest.main(testRunner=runner)
2788 # vim: set filetype=python sts=4 sw=4 et si :