47b8eeb77607bb1f67ed1db103c203c9e0b3f651
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 def testMultipartKeepAlternatives(self):
487 self.doNewIssue()
488 self._handle_mail(self.multipart_msg)
489 messages = self.db.issue.get('1', 'messages')
490 messages.sort()
491 msg = self.db.msg.getnode (messages[-1])
492 assert(len(msg.files) == 5)
493 names = {0 : 'first.dvi', 4 : 'second.dvi'}
494 content = {3 : 'test attachment third text/plain\n',
495 4 : 'Just a test\n'}
496 for n, id in enumerate (msg.files):
497 f = self.db.file.getnode (id)
498 self.assertEqual(f.name, names.get (n, 'unnamed'))
499 if n in content :
500 self.assertEqual(f.content, content [n])
501 self.assertEqual(msg.content, 'test attachment second text/plain')
503 def testMultipartDropAlternatives(self):
504 self.doNewIssue()
505 self.db.config.MAILGW_IGNORE_ALTERNATIVES = True
506 self._handle_mail(self.multipart_msg)
507 messages = self.db.issue.get('1', 'messages')
508 messages.sort()
509 msg = self.db.msg.getnode (messages[-1])
510 assert(len(msg.files) == 2)
511 names = {1 : 'second.dvi'}
512 content = {0 : 'test attachment third text/plain\n',
513 1 : 'Just a test\n'}
514 for n, id in enumerate (msg.files):
515 f = self.db.file.getnode (id)
516 self.assertEqual(f.name, names.get (n, 'unnamed'))
517 if n in content :
518 self.assertEqual(f.content, content [n])
519 self.assertEqual(msg.content, 'test attachment second text/plain')
521 def testMultipartCharsetUTF8NoAttach(self):
522 c = 'umlaut \xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c\xc3\x9f'
523 self.doNewIssue()
524 self.db.config.NOSY_MAX_ATTACHMENT_SIZE = 0
525 self._handle_mail(self.multipart_msg_latin1)
526 messages = self.db.issue.get('1', 'messages')
527 messages.sort()
528 msg = self.db.msg.getnode (messages[-1])
529 assert(len(msg.files) == 1)
530 name = 'unnamed'
531 content = '<html>' + c + '</html>\n'
532 for n, id in enumerate (msg.files):
533 f = self.db.file.getnode (id)
534 self.assertEqual(f.name, name)
535 self.assertEqual(f.content, content)
536 self.assertEqual(msg.content, c)
537 self.compareMessages(self._get_mail(),
538 '''FROM: roundup-admin@your.tracker.email.domain.example
539 TO: chef@bork.bork.bork, richard@test.test
540 Content-Type: text/plain; charset="utf-8"
541 Subject: [issue1] Testing...
542 To: chef@bork.bork.bork, richard@test.test
543 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
544 Reply-To: Roundup issue tracker
545 <issue_tracker@your.tracker.email.domain.example>
546 MIME-Version: 1.0
547 Message-Id: <followup_dummy_id>
548 In-Reply-To: <dummy_test_message_id>
549 X-Roundup-Name: Roundup issue tracker
550 X-Roundup-Loop: hello
551 X-Roundup-Issue-Status: chatting
552 X-Roundup-Issue-Files: unnamed
553 Content-Transfer-Encoding: quoted-printable
556 Contrary, Mary <mary@test.test> added the comment:
558 umlaut =C3=A4=C3=B6=C3=BC=C3=84=C3=96=C3=9C=C3=9F
559 File 'unnamed' not attached - you can download it from http://tracker.examp=
560 le/cgi-bin/roundup.cgi/bugs/file1.
562 ----------
563 status: unread -> chatting
565 _______________________________________________________________________
566 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
567 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
568 _______________________________________________________________________
569 ''')
571 def testMultipartCharsetLatin1NoAttach(self):
572 c = 'umlaut \xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c\xc3\x9f'
573 self.doNewIssue()
574 self.db.config.NOSY_MAX_ATTACHMENT_SIZE = 0
575 self.db.config.MAIL_CHARSET = 'iso-8859-1'
576 self._handle_mail(self.multipart_msg_latin1)
577 messages = self.db.issue.get('1', 'messages')
578 messages.sort()
579 msg = self.db.msg.getnode (messages[-1])
580 assert(len(msg.files) == 1)
581 name = 'unnamed'
582 content = '<html>' + c + '</html>\n'
583 for n, id in enumerate (msg.files):
584 f = self.db.file.getnode (id)
585 self.assertEqual(f.name, name)
586 self.assertEqual(f.content, content)
587 self.assertEqual(msg.content, c)
588 self.compareMessages(self._get_mail(),
589 '''FROM: roundup-admin@your.tracker.email.domain.example
590 TO: chef@bork.bork.bork, richard@test.test
591 Content-Type: text/plain; charset="iso-8859-1"
592 Subject: [issue1] Testing...
593 To: chef@bork.bork.bork, richard@test.test
594 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
595 Reply-To: Roundup issue tracker
596 <issue_tracker@your.tracker.email.domain.example>
597 MIME-Version: 1.0
598 Message-Id: <followup_dummy_id>
599 In-Reply-To: <dummy_test_message_id>
600 X-Roundup-Name: Roundup issue tracker
601 X-Roundup-Loop: hello
602 X-Roundup-Issue-Status: chatting
603 X-Roundup-Issue-Files: unnamed
604 Content-Transfer-Encoding: quoted-printable
607 Contrary, Mary <mary@test.test> added the comment:
609 umlaut =E4=F6=FC=C4=D6=DC=DF
610 File 'unnamed' not attached - you can download it from http://tracker.examp=
611 le/cgi-bin/roundup.cgi/bugs/file1.
613 ----------
614 status: unread -> chatting
616 _______________________________________________________________________
617 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
618 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
619 _______________________________________________________________________
620 ''')
622 def testMultipartCharsetUTF8AttachFile(self):
623 c = 'umlaut \xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c\xc3\x9f'
624 self.doNewIssue()
625 self._handle_mail(self.multipart_msg_latin1)
626 messages = self.db.issue.get('1', 'messages')
627 messages.sort()
628 msg = self.db.msg.getnode (messages[-1])
629 assert(len(msg.files) == 1)
630 name = 'unnamed'
631 content = '<html>' + c + '</html>\n'
632 for n, id in enumerate (msg.files):
633 f = self.db.file.getnode (id)
634 self.assertEqual(f.name, name)
635 self.assertEqual(f.content, content)
636 self.assertEqual(msg.content, c)
637 self.compareMessages(self._get_mail(),
638 '''FROM: roundup-admin@your.tracker.email.domain.example
639 TO: chef@bork.bork.bork, richard@test.test
640 Content-Type: multipart/mixed; boundary="utf-8"
641 Subject: [issue1] Testing...
642 To: chef@bork.bork.bork, richard@test.test
643 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
644 Reply-To: Roundup issue tracker
645 <issue_tracker@your.tracker.email.domain.example>
646 MIME-Version: 1.0
647 Message-Id: <followup_dummy_id>
648 In-Reply-To: <dummy_test_message_id>
649 X-Roundup-Name: Roundup issue tracker
650 X-Roundup-Loop: hello
651 X-Roundup-Issue-Status: chatting
652 X-Roundup-Issue-Files: unnamed
653 Content-Transfer-Encoding: quoted-printable
656 --utf-8
657 MIME-Version: 1.0
658 Content-Type: text/plain; charset="utf-8"
659 Content-Transfer-Encoding: quoted-printable
662 Contrary, Mary <mary@test.test> added the comment:
664 umlaut =C3=A4=C3=B6=C3=BC=C3=84=C3=96=C3=9C=C3=9F
666 ----------
667 status: unread -> chatting
669 _______________________________________________________________________
670 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
671 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
672 _______________________________________________________________________
673 --utf-8
674 Content-Type: text/html
675 MIME-Version: 1.0
676 Content-Transfer-Encoding: base64
677 Content-Disposition: attachment;
678 filename="unnamed"
680 PGh0bWw+dW1sYXV0IMOkw7bDvMOEw5bDnMOfPC9odG1sPgo=
682 --utf-8--
683 ''')
685 def testMultipartCharsetLatin1AttachFile(self):
686 c = 'umlaut \xc3\xa4\xc3\xb6\xc3\xbc\xc3\x84\xc3\x96\xc3\x9c\xc3\x9f'
687 self.doNewIssue()
688 self.db.config.MAIL_CHARSET = 'iso-8859-1'
689 self._handle_mail(self.multipart_msg_latin1)
690 messages = self.db.issue.get('1', 'messages')
691 messages.sort()
692 msg = self.db.msg.getnode (messages[-1])
693 assert(len(msg.files) == 1)
694 name = 'unnamed'
695 content = '<html>' + c + '</html>\n'
696 for n, id in enumerate (msg.files):
697 f = self.db.file.getnode (id)
698 self.assertEqual(f.name, name)
699 self.assertEqual(f.content, content)
700 self.assertEqual(msg.content, c)
701 self.compareMessages(self._get_mail(),
702 '''FROM: roundup-admin@your.tracker.email.domain.example
703 TO: chef@bork.bork.bork, richard@test.test
704 Content-Type: multipart/mixed; boundary="utf-8"
705 Subject: [issue1] Testing...
706 To: chef@bork.bork.bork, richard@test.test
707 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
708 Reply-To: Roundup issue tracker
709 <issue_tracker@your.tracker.email.domain.example>
710 MIME-Version: 1.0
711 Message-Id: <followup_dummy_id>
712 In-Reply-To: <dummy_test_message_id>
713 X-Roundup-Name: Roundup issue tracker
714 X-Roundup-Loop: hello
715 X-Roundup-Issue-Status: chatting
716 X-Roundup-Issue-Files: unnamed
717 Content-Transfer-Encoding: quoted-printable
720 --utf-8
721 MIME-Version: 1.0
722 Content-Type: text/plain; charset="iso-8859-1"
723 Content-Transfer-Encoding: quoted-printable
726 Contrary, Mary <mary@test.test> added the comment:
728 umlaut =E4=F6=FC=C4=D6=DC=DF
730 ----------
731 status: unread -> chatting
733 _______________________________________________________________________
734 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
735 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
736 _______________________________________________________________________
737 --utf-8
738 Content-Type: text/html
739 MIME-Version: 1.0
740 Content-Transfer-Encoding: base64
741 Content-Disposition: attachment;
742 filename="unnamed"
744 PGh0bWw+dW1sYXV0IMOkw7bDvMOEw5bDnMOfPC9odG1sPgo=
746 --utf-8--
747 ''')
749 def testSimpleFollowup(self):
750 self.doNewIssue()
751 self._handle_mail('''Content-Type: text/plain;
752 charset="iso-8859-1"
753 From: mary <mary@test.test>
754 To: issue_tracker@your.tracker.email.domain.example
755 Message-Id: <followup_dummy_id>
756 In-Reply-To: <dummy_test_message_id>
757 Subject: [issue1] Testing...
759 This is a second followup
760 ''')
761 self.compareMessages(self._get_mail(),
762 '''FROM: roundup-admin@your.tracker.email.domain.example
763 TO: chef@bork.bork.bork, richard@test.test
764 Content-Type: text/plain; charset="utf-8"
765 Subject: [issue1] Testing...
766 To: chef@bork.bork.bork, richard@test.test
767 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
768 Reply-To: Roundup issue tracker
769 <issue_tracker@your.tracker.email.domain.example>
770 MIME-Version: 1.0
771 Message-Id: <followup_dummy_id>
772 In-Reply-To: <dummy_test_message_id>
773 X-Roundup-Name: Roundup issue tracker
774 X-Roundup-Loop: hello
775 X-Roundup-Issue-Status: chatting
776 Content-Transfer-Encoding: quoted-printable
779 Contrary, Mary <mary@test.test> added the comment:
781 This is a second followup
783 ----------
784 status: unread -> chatting
786 _______________________________________________________________________
787 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
788 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
789 _______________________________________________________________________
790 ''')
792 def testFollowup(self):
793 self.doNewIssue()
795 self._handle_mail('''Content-Type: text/plain;
796 charset="iso-8859-1"
797 From: richard <richard@test.test>
798 To: issue_tracker@your.tracker.email.domain.example
799 Message-Id: <followup_dummy_id>
800 In-Reply-To: <dummy_test_message_id>
801 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
803 This is a followup
804 ''')
805 l = self.db.issue.get('1', 'nosy')
806 l.sort()
807 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
808 self.john_id])
810 self.compareMessages(self._get_mail(),
811 '''FROM: roundup-admin@your.tracker.email.domain.example
812 TO: chef@bork.bork.bork, john@test.test, mary@test.test
813 Content-Type: text/plain; charset="utf-8"
814 Subject: [issue1] Testing...
815 To: chef@bork.bork.bork, john@test.test, mary@test.test
816 From: richard <issue_tracker@your.tracker.email.domain.example>
817 Reply-To: Roundup issue tracker
818 <issue_tracker@your.tracker.email.domain.example>
819 MIME-Version: 1.0
820 Message-Id: <followup_dummy_id>
821 In-Reply-To: <dummy_test_message_id>
822 X-Roundup-Name: Roundup issue tracker
823 X-Roundup-Loop: hello
824 X-Roundup-Issue-Status: chatting
825 Content-Transfer-Encoding: quoted-printable
828 richard <richard@test.test> added the comment:
830 This is a followup
832 ----------
833 assignedto: -> mary
834 nosy: +john, mary
835 status: unread -> chatting
837 _______________________________________________________________________
838 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
839 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
840 _______________________________________________________________________
841 ''')
843 def testFollowupNoSubjectChange(self):
844 self.db.config.MAILGW_SUBJECT_UPDATES_TITLE = 'no'
845 self.doNewIssue()
847 self._handle_mail('''Content-Type: text/plain;
848 charset="iso-8859-1"
849 From: richard <richard@test.test>
850 To: issue_tracker@your.tracker.email.domain.example
851 Message-Id: <followup_dummy_id>
852 In-Reply-To: <dummy_test_message_id>
853 Subject: [issue1] Wrzlbrmft... [assignedto=mary; nosy=+john]
855 This is a followup
856 ''')
857 l = self.db.issue.get('1', 'nosy')
858 l.sort()
859 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
860 self.john_id])
862 self.compareMessages(self._get_mail(),
863 '''FROM: roundup-admin@your.tracker.email.domain.example
864 TO: chef@bork.bork.bork, john@test.test, mary@test.test
865 Content-Type: text/plain; charset="utf-8"
866 Subject: [issue1] Testing...
867 To: chef@bork.bork.bork, john@test.test, mary@test.test
868 From: richard <issue_tracker@your.tracker.email.domain.example>
869 Reply-To: Roundup issue tracker
870 <issue_tracker@your.tracker.email.domain.example>
871 MIME-Version: 1.0
872 Message-Id: <followup_dummy_id>
873 In-Reply-To: <dummy_test_message_id>
874 X-Roundup-Name: Roundup issue tracker
875 X-Roundup-Loop: hello
876 X-Roundup-Issue-Status: chatting
877 Content-Transfer-Encoding: quoted-printable
880 richard <richard@test.test> added the comment:
882 This is a followup
884 ----------
885 assignedto: -> mary
886 nosy: +john, mary
887 status: unread -> chatting
889 _______________________________________________________________________
890 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
891 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
892 _______________________________________________________________________
893 ''')
894 self.assertEqual(self.db.issue.get('1','title'), 'Testing...')
896 def testFollowupExplicitSubjectChange(self):
897 self.doNewIssue()
899 self._handle_mail('''Content-Type: text/plain;
900 charset="iso-8859-1"
901 From: richard <richard@test.test>
902 To: issue_tracker@your.tracker.email.domain.example
903 Message-Id: <followup_dummy_id>
904 In-Reply-To: <dummy_test_message_id>
905 Subject: [issue1] Wrzlbrmft... [assignedto=mary; nosy=+john; title=new title]
907 This is a followup
908 ''')
909 l = self.db.issue.get('1', 'nosy')
910 l.sort()
911 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
912 self.john_id])
914 self.compareMessages(self._get_mail(),
915 '''FROM: roundup-admin@your.tracker.email.domain.example
916 TO: chef@bork.bork.bork, john@test.test, mary@test.test
917 Content-Type: text/plain; charset="utf-8"
918 Subject: [issue1] new title
919 To: chef@bork.bork.bork, john@test.test, mary@test.test
920 From: richard <issue_tracker@your.tracker.email.domain.example>
921 Reply-To: Roundup issue tracker
922 <issue_tracker@your.tracker.email.domain.example>
923 MIME-Version: 1.0
924 Message-Id: <followup_dummy_id>
925 In-Reply-To: <dummy_test_message_id>
926 X-Roundup-Name: Roundup issue tracker
927 X-Roundup-Loop: hello
928 X-Roundup-Issue-Status: chatting
929 Content-Transfer-Encoding: quoted-printable
932 richard <richard@test.test> added the comment:
934 This is a followup
936 ----------
937 assignedto: -> mary
938 nosy: +john, mary
939 status: unread -> chatting
940 title: Testing... -> new title
942 _______________________________________________________________________
943 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
944 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
945 _______________________________________________________________________
946 ''')
948 def testNosyGeneration(self):
949 self.db.issue.create(title='test')
951 # create a nosy message
952 msg = self.db.msg.create(content='This is a test',
953 author=self.richard_id, messageid='<dummy_test_message_id>')
954 self.db.journaltag = 'richard'
955 l = self.db.issue.create(title='test', messages=[msg],
956 nosy=[self.chef_id, self.mary_id, self.john_id])
958 self.compareMessages(self._get_mail(),
959 '''FROM: roundup-admin@your.tracker.email.domain.example
960 TO: chef@bork.bork.bork, john@test.test, mary@test.test
961 Content-Type: text/plain; charset="utf-8"
962 Subject: [issue2] test
963 To: chef@bork.bork.bork, john@test.test, mary@test.test
964 From: richard <issue_tracker@your.tracker.email.domain.example>
965 Reply-To: Roundup issue tracker
966 <issue_tracker@your.tracker.email.domain.example>
967 MIME-Version: 1.0
968 Message-Id: <dummy_test_message_id>
969 X-Roundup-Name: Roundup issue tracker
970 X-Roundup-Loop: hello
971 X-Roundup-Issue-Status: unread
972 Content-Transfer-Encoding: quoted-printable
975 New submission from richard <richard@test.test>:
977 This is a test
979 ----------
980 messages: 1
981 nosy: Chef, john, mary, richard
982 status: unread
983 title: test
985 _______________________________________________________________________
986 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
987 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue2>
988 _______________________________________________________________________
989 ''')
991 def testPropertyChangeOnly(self):
992 self.doNewIssue()
993 oldvalues = self.db.getnode('issue', '1').copy()
994 oldvalues['assignedto'] = None
995 # reconstruct old behaviour: This would reuse the
996 # database-handle from the doNewIssue above which has committed
997 # as user "Chef". So we close and reopen the db as that user.
998 #self.db.close() actually don't close 'cos this empties memorydb
999 self.db = self.instance.open('Chef')
1000 self.db.issue.set('1', assignedto=self.chef_id)
1001 self.db.commit()
1002 self.db.issue.nosymessage('1', None, oldvalues)
1004 new_mail = ""
1005 for line in self._get_mail().split("\n"):
1006 if "Message-Id: " in line:
1007 continue
1008 if "Date: " in line:
1009 continue
1010 new_mail += line+"\n"
1012 self.compareMessages(new_mail, """
1013 FROM: roundup-admin@your.tracker.email.domain.example
1014 TO: chef@bork.bork.bork, richard@test.test
1015 Content-Type: text/plain; charset="utf-8"
1016 Subject: [issue1] Testing...
1017 To: chef@bork.bork.bork, richard@test.test
1018 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
1019 X-Roundup-Name: Roundup issue tracker
1020 X-Roundup-Loop: hello
1021 X-Roundup-Issue-Status: unread
1022 X-Roundup-Version: 1.3.3
1023 In-Reply-To: <dummy_test_message_id>
1024 MIME-Version: 1.0
1025 Reply-To: Roundup issue tracker
1026 <issue_tracker@your.tracker.email.domain.example>
1027 Content-Transfer-Encoding: quoted-printable
1030 Change by Bork, Chef <chef@bork.bork.bork>:
1033 ----------
1034 assignedto: -> Chef
1036 _______________________________________________________________________
1037 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1038 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1039 _______________________________________________________________________
1040 """)
1043 #
1044 # FOLLOWUP TITLE MATCH
1045 #
1046 def testFollowupTitleMatch(self):
1047 self.doNewIssue()
1048 self._handle_mail('''Content-Type: text/plain;
1049 charset="iso-8859-1"
1050 From: richard <richard@test.test>
1051 To: issue_tracker@your.tracker.email.domain.example
1052 Message-Id: <followup_dummy_id>
1053 Subject: Re: Testing... [assignedto=mary; nosy=+john]
1055 This is a followup
1056 ''')
1057 self.compareMessages(self._get_mail(),
1058 '''FROM: roundup-admin@your.tracker.email.domain.example
1059 TO: chef@bork.bork.bork, john@test.test, mary@test.test
1060 Content-Type: text/plain; charset="utf-8"
1061 Subject: [issue1] Testing...
1062 To: chef@bork.bork.bork, john@test.test, mary@test.test
1063 From: richard <issue_tracker@your.tracker.email.domain.example>
1064 Reply-To: Roundup issue tracker
1065 <issue_tracker@your.tracker.email.domain.example>
1066 MIME-Version: 1.0
1067 Message-Id: <followup_dummy_id>
1068 In-Reply-To: <dummy_test_message_id>
1069 X-Roundup-Name: Roundup issue tracker
1070 X-Roundup-Loop: hello
1071 X-Roundup-Issue-Status: chatting
1072 Content-Transfer-Encoding: quoted-printable
1075 richard <richard@test.test> added the comment:
1077 This is a followup
1079 ----------
1080 assignedto: -> mary
1081 nosy: +john, mary
1082 status: unread -> chatting
1084 _______________________________________________________________________
1085 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1086 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1087 _______________________________________________________________________
1088 ''')
1090 def testFollowupTitleMatchMultiRe(self):
1091 nodeid1 = self.doNewIssue()
1092 nodeid2 = self._handle_mail('''Content-Type: text/plain;
1093 charset="iso-8859-1"
1094 From: richard <richard@test.test>
1095 To: issue_tracker@your.tracker.email.domain.example
1096 Message-Id: <followup_dummy_id>
1097 Subject: Re: Testing... [assignedto=mary; nosy=+john]
1099 This is a followup
1100 ''')
1102 nodeid3 = self._handle_mail('''Content-Type: text/plain;
1103 charset="iso-8859-1"
1104 From: richard <richard@test.test>
1105 To: issue_tracker@your.tracker.email.domain.example
1106 Message-Id: <followup2_dummy_id>
1107 Subject: Ang: Re: Testing...
1109 This is a followup
1110 ''')
1111 self.assertEqual(nodeid1, nodeid2)
1112 self.assertEqual(nodeid1, nodeid3)
1114 def testFollowupTitleMatchNever(self):
1115 nodeid = self.doNewIssue()
1116 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'never'
1117 self.assertNotEqual(self._handle_mail('''Content-Type: text/plain;
1118 charset="iso-8859-1"
1119 From: richard <richard@test.test>
1120 To: issue_tracker@your.tracker.email.domain.example
1121 Message-Id: <followup_dummy_id>
1122 Subject: Re: Testing...
1124 This is a followup
1125 '''), nodeid)
1127 def testFollowupTitleMatchNeverInterval(self):
1128 nodeid = self.doNewIssue()
1129 # force failure of the interval
1130 time.sleep(2)
1131 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation 00:00:01'
1132 self.assertNotEqual(self._handle_mail('''Content-Type: text/plain;
1133 charset="iso-8859-1"
1134 From: richard <richard@test.test>
1135 To: issue_tracker@your.tracker.email.domain.example
1136 Message-Id: <followup_dummy_id>
1137 Subject: Re: Testing...
1139 This is a followup
1140 '''), nodeid)
1143 def testFollowupTitleMatchInterval(self):
1144 nodeid = self.doNewIssue()
1145 self.db.config.MAILGW_SUBJECT_CONTENT_MATCH = 'creation +1d'
1146 self.assertEqual(self._handle_mail('''Content-Type: text/plain;
1147 charset="iso-8859-1"
1148 From: richard <richard@test.test>
1149 To: issue_tracker@your.tracker.email.domain.example
1150 Message-Id: <followup_dummy_id>
1151 Subject: Re: Testing...
1153 This is a followup
1154 '''), nodeid)
1157 def testFollowupNosyAuthor(self):
1158 self.doNewIssue()
1159 self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
1160 self._handle_mail('''Content-Type: text/plain;
1161 charset="iso-8859-1"
1162 From: john@test.test
1163 To: issue_tracker@your.tracker.email.domain.example
1164 Message-Id: <followup_dummy_id>
1165 In-Reply-To: <dummy_test_message_id>
1166 Subject: [issue1] Testing...
1168 This is a followup
1169 ''')
1171 self.compareMessages(self._get_mail(),
1172 '''FROM: roundup-admin@your.tracker.email.domain.example
1173 TO: chef@bork.bork.bork, richard@test.test
1174 Content-Type: text/plain; charset="utf-8"
1175 Subject: [issue1] Testing...
1176 To: chef@bork.bork.bork, richard@test.test
1177 From: John Doe <issue_tracker@your.tracker.email.domain.example>
1178 Reply-To: Roundup issue tracker
1179 <issue_tracker@your.tracker.email.domain.example>
1180 MIME-Version: 1.0
1181 Message-Id: <followup_dummy_id>
1182 In-Reply-To: <dummy_test_message_id>
1183 X-Roundup-Name: Roundup issue tracker
1184 X-Roundup-Loop: hello
1185 X-Roundup-Issue-Status: chatting
1186 Content-Transfer-Encoding: quoted-printable
1189 John Doe <john@test.test> added the comment:
1191 This is a followup
1193 ----------
1194 nosy: +john
1195 status: unread -> chatting
1197 _______________________________________________________________________
1198 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1199 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1200 _______________________________________________________________________
1202 ''')
1204 def testFollowupNosyRecipients(self):
1205 self.doNewIssue()
1206 self.db.config.ADD_RECIPIENTS_TO_NOSY = 'yes'
1207 self._handle_mail('''Content-Type: text/plain;
1208 charset="iso-8859-1"
1209 From: richard@test.test
1210 To: issue_tracker@your.tracker.email.domain.example
1211 Cc: john@test.test
1212 Message-Id: <followup_dummy_id>
1213 In-Reply-To: <dummy_test_message_id>
1214 Subject: [issue1] Testing...
1216 This is a followup
1217 ''')
1218 self.compareMessages(self._get_mail(),
1219 '''FROM: roundup-admin@your.tracker.email.domain.example
1220 TO: chef@bork.bork.bork
1221 Content-Type: text/plain; charset="utf-8"
1222 Subject: [issue1] Testing...
1223 To: chef@bork.bork.bork
1224 From: richard <issue_tracker@your.tracker.email.domain.example>
1225 Reply-To: Roundup issue tracker
1226 <issue_tracker@your.tracker.email.domain.example>
1227 MIME-Version: 1.0
1228 Message-Id: <followup_dummy_id>
1229 In-Reply-To: <dummy_test_message_id>
1230 X-Roundup-Name: Roundup issue tracker
1231 X-Roundup-Loop: hello
1232 X-Roundup-Issue-Status: chatting
1233 Content-Transfer-Encoding: quoted-printable
1236 richard <richard@test.test> added the comment:
1238 This is a followup
1240 ----------
1241 nosy: +john
1242 status: unread -> chatting
1244 _______________________________________________________________________
1245 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1246 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1247 _______________________________________________________________________
1249 ''')
1251 def testFollowupNosyAuthorAndCopy(self):
1252 self.doNewIssue()
1253 self.db.config.ADD_AUTHOR_TO_NOSY = 'yes'
1254 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
1255 self._handle_mail('''Content-Type: text/plain;
1256 charset="iso-8859-1"
1257 From: john@test.test
1258 To: issue_tracker@your.tracker.email.domain.example
1259 Message-Id: <followup_dummy_id>
1260 In-Reply-To: <dummy_test_message_id>
1261 Subject: [issue1] Testing...
1263 This is a followup
1264 ''')
1265 self.compareMessages(self._get_mail(),
1266 '''FROM: roundup-admin@your.tracker.email.domain.example
1267 TO: chef@bork.bork.bork, john@test.test, richard@test.test
1268 Content-Type: text/plain; charset="utf-8"
1269 Subject: [issue1] Testing...
1270 To: chef@bork.bork.bork, john@test.test, richard@test.test
1271 From: John Doe <issue_tracker@your.tracker.email.domain.example>
1272 Reply-To: Roundup issue tracker
1273 <issue_tracker@your.tracker.email.domain.example>
1274 MIME-Version: 1.0
1275 Message-Id: <followup_dummy_id>
1276 In-Reply-To: <dummy_test_message_id>
1277 X-Roundup-Name: Roundup issue tracker
1278 X-Roundup-Loop: hello
1279 X-Roundup-Issue-Status: chatting
1280 Content-Transfer-Encoding: quoted-printable
1283 John Doe <john@test.test> added the comment:
1285 This is a followup
1287 ----------
1288 nosy: +john
1289 status: unread -> chatting
1291 _______________________________________________________________________
1292 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1293 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1294 _______________________________________________________________________
1296 ''')
1298 def testFollowupNoNosyAuthor(self):
1299 self.doNewIssue()
1300 self.instance.config.ADD_AUTHOR_TO_NOSY = 'no'
1301 self._handle_mail('''Content-Type: text/plain;
1302 charset="iso-8859-1"
1303 From: john@test.test
1304 To: issue_tracker@your.tracker.email.domain.example
1305 Message-Id: <followup_dummy_id>
1306 In-Reply-To: <dummy_test_message_id>
1307 Subject: [issue1] Testing...
1309 This is a followup
1310 ''')
1311 self.compareMessages(self._get_mail(),
1312 '''FROM: roundup-admin@your.tracker.email.domain.example
1313 TO: chef@bork.bork.bork, richard@test.test
1314 Content-Type: text/plain; charset="utf-8"
1315 Subject: [issue1] Testing...
1316 To: chef@bork.bork.bork, richard@test.test
1317 From: John Doe <issue_tracker@your.tracker.email.domain.example>
1318 Reply-To: Roundup issue tracker
1319 <issue_tracker@your.tracker.email.domain.example>
1320 MIME-Version: 1.0
1321 Message-Id: <followup_dummy_id>
1322 In-Reply-To: <dummy_test_message_id>
1323 X-Roundup-Name: Roundup issue tracker
1324 X-Roundup-Loop: hello
1325 X-Roundup-Issue-Status: chatting
1326 Content-Transfer-Encoding: quoted-printable
1329 John Doe <john@test.test> added the comment:
1331 This is a followup
1333 ----------
1334 status: unread -> chatting
1336 _______________________________________________________________________
1337 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1338 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1339 _______________________________________________________________________
1341 ''')
1343 def testFollowupNoNosyRecipients(self):
1344 self.doNewIssue()
1345 self.instance.config.ADD_RECIPIENTS_TO_NOSY = 'no'
1346 self._handle_mail('''Content-Type: text/plain;
1347 charset="iso-8859-1"
1348 From: richard@test.test
1349 To: issue_tracker@your.tracker.email.domain.example
1350 Cc: john@test.test
1351 Message-Id: <followup_dummy_id>
1352 In-Reply-To: <dummy_test_message_id>
1353 Subject: [issue1] Testing...
1355 This is a followup
1356 ''')
1357 self.compareMessages(self._get_mail(),
1358 '''FROM: roundup-admin@your.tracker.email.domain.example
1359 TO: chef@bork.bork.bork
1360 Content-Type: text/plain; charset="utf-8"
1361 Subject: [issue1] Testing...
1362 To: chef@bork.bork.bork
1363 From: richard <issue_tracker@your.tracker.email.domain.example>
1364 Reply-To: Roundup issue tracker
1365 <issue_tracker@your.tracker.email.domain.example>
1366 MIME-Version: 1.0
1367 Message-Id: <followup_dummy_id>
1368 In-Reply-To: <dummy_test_message_id>
1369 X-Roundup-Name: Roundup issue tracker
1370 X-Roundup-Loop: hello
1371 X-Roundup-Issue-Status: chatting
1372 Content-Transfer-Encoding: quoted-printable
1375 richard <richard@test.test> added the comment:
1377 This is a followup
1379 ----------
1380 status: unread -> chatting
1382 _______________________________________________________________________
1383 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1384 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1385 _______________________________________________________________________
1387 ''')
1389 def testFollowupEmptyMessage(self):
1390 self.doNewIssue()
1392 self._handle_mail('''Content-Type: text/plain;
1393 charset="iso-8859-1"
1394 From: richard <richard@test.test>
1395 To: issue_tracker@your.tracker.email.domain.example
1396 Message-Id: <followup_dummy_id>
1397 In-Reply-To: <dummy_test_message_id>
1398 Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
1400 ''')
1401 l = self.db.issue.get('1', 'nosy')
1402 l.sort()
1403 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
1404 self.john_id])
1406 # should be no file created (ie. no message)
1407 assert not os.path.exists(SENDMAILDEBUG)
1409 def testFollowupEmptyMessageNoSubject(self):
1410 self.doNewIssue()
1412 self._handle_mail('''Content-Type: text/plain;
1413 charset="iso-8859-1"
1414 From: richard <richard@test.test>
1415 To: issue_tracker@your.tracker.email.domain.example
1416 Message-Id: <followup_dummy_id>
1417 In-Reply-To: <dummy_test_message_id>
1418 Subject: [issue1] [assignedto=mary; nosy=+john]
1420 ''')
1421 l = self.db.issue.get('1', 'nosy')
1422 l.sort()
1423 self.assertEqual(l, [self.chef_id, self.richard_id, self.mary_id,
1424 self.john_id])
1426 # should be no file created (ie. no message)
1427 assert not os.path.exists(SENDMAILDEBUG)
1429 def testNosyRemove(self):
1430 self.doNewIssue()
1432 self._handle_mail('''Content-Type: text/plain;
1433 charset="iso-8859-1"
1434 From: richard <richard@test.test>
1435 To: issue_tracker@your.tracker.email.domain.example
1436 Message-Id: <followup_dummy_id>
1437 In-Reply-To: <dummy_test_message_id>
1438 Subject: [issue1] Testing... [nosy=-richard]
1440 ''')
1441 l = self.db.issue.get('1', 'nosy')
1442 l.sort()
1443 self.assertEqual(l, [self.chef_id])
1445 # NO NOSY MESSAGE SHOULD BE SENT!
1446 assert not os.path.exists(SENDMAILDEBUG)
1448 def testNewUserAuthor(self):
1449 self.db.commit()
1450 l = self.db.user.list()
1451 l.sort()
1452 message = '''Content-Type: text/plain;
1453 charset="iso-8859-1"
1454 From: fubar <fubar@bork.bork.bork>
1455 To: issue_tracker@your.tracker.email.domain.example
1456 Message-Id: <dummy_test_message_id>
1457 Subject: [issue] Testing...
1459 This is a test submission of a new issue.
1460 '''
1461 self.db.security.role['anonymous'].permissions=[]
1462 anonid = self.db.user.lookup('anonymous')
1463 self.db.user.set(anonid, roles='Anonymous')
1464 try:
1465 self._handle_mail(message)
1466 except Unauthorized, value:
1467 body_diff = self.compareMessages(str(value), """
1468 You are not a registered user.
1470 Unknown address: fubar@bork.bork.bork
1471 """)
1472 assert not body_diff, body_diff
1473 else:
1474 raise AssertionError, "Unathorized not raised when handling mail"
1476 # Add Web Access role to anonymous, and try again to make sure
1477 # we get a "please register at:" message this time.
1478 p = [
1479 self.db.security.getPermission('Register', 'user'),
1480 self.db.security.getPermission('Web Access', None),
1481 ]
1482 self.db.security.role['anonymous'].permissions=p
1483 try:
1484 self._handle_mail(message)
1485 except Unauthorized, value:
1486 body_diff = self.compareMessages(str(value), """
1487 You are not a registered user. Please register at:
1489 http://tracker.example/cgi-bin/roundup.cgi/bugs/user?template=register
1491 ...before sending mail to the tracker.
1493 Unknown address: fubar@bork.bork.bork
1494 """)
1495 assert not body_diff, body_diff
1496 else:
1497 raise AssertionError, "Unathorized not raised when handling mail"
1499 # Make sure list of users is the same as before.
1500 m = self.db.user.list()
1501 m.sort()
1502 self.assertEqual(l, m)
1504 # now with the permission
1505 p = [
1506 self.db.security.getPermission('Register', 'user'),
1507 self.db.security.getPermission('Email Access', None),
1508 ]
1509 self.db.security.role['anonymous'].permissions=p
1510 self._handle_mail(message)
1511 m = self.db.user.list()
1512 m.sort()
1513 self.assertNotEqual(l, m)
1515 def testNewUserAuthorEncodedName(self):
1516 l = set(self.db.user.list())
1517 # From: name has Euro symbol in it
1518 message = '''Content-Type: text/plain;
1519 charset="iso-8859-1"
1520 From: =?utf8?b?SOKCrGxsbw==?= <fubar@bork.bork.bork>
1521 To: issue_tracker@your.tracker.email.domain.example
1522 Message-Id: <dummy_test_message_id>
1523 Subject: [issue] Testing...
1525 This is a test submission of a new issue.
1526 '''
1527 p = [
1528 self.db.security.getPermission('Register', 'user'),
1529 self.db.security.getPermission('Email Access', None),
1530 self.db.security.getPermission('Create', 'issue'),
1531 self.db.security.getPermission('Create', 'msg'),
1532 ]
1533 self.db.security.role['anonymous'].permissions = p
1534 self._handle_mail(message)
1535 m = set(self.db.user.list())
1536 new = list(m - l)[0]
1537 name = self.db.user.get(new, 'realname')
1538 self.assertEquals(name, 'H€llo')
1540 def testUnknownUser(self):
1541 l = set(self.db.user.list())
1542 message = '''Content-Type: text/plain;
1543 charset="iso-8859-1"
1544 From: Nonexisting User <nonexisting@bork.bork.bork>
1545 To: issue_tracker@your.tracker.email.domain.example
1546 Message-Id: <dummy_test_message_id>
1547 Subject: [issue] Testing nonexisting user...
1549 This is a test submission of a new issue.
1550 '''
1551 handler = self._create_mailgw(message)
1552 # we want a bounce message:
1553 handler.trapExceptions = 1
1554 ret = handler.main(StringIO(message))
1555 self.compareMessages(self._get_mail(),
1556 '''FROM: Roundup issue tracker <roundup-admin@your.tracker.email.domain.example>
1557 TO: nonexisting@bork.bork.bork
1558 From nobody Tue Jul 14 12:04:11 2009
1559 Content-Type: multipart/mixed; boundary="===============0639262320=="
1560 MIME-Version: 1.0
1561 Subject: Failed issue tracker submission
1562 To: nonexisting@bork.bork.bork
1563 From: Roundup issue tracker <roundup-admin@your.tracker.email.domain.example>
1564 Date: Tue, 14 Jul 2009 12:04:11 +0000
1565 Precedence: bulk
1566 X-Roundup-Name: Roundup issue tracker
1567 X-Roundup-Loop: hello
1568 X-Roundup-Version: 1.4.8
1569 MIME-Version: 1.0
1571 --===============0639262320==
1572 Content-Type: text/plain; charset="us-ascii"
1573 MIME-Version: 1.0
1574 Content-Transfer-Encoding: 7bit
1578 You are not a registered user. Please register at:
1580 http://tracker.example/cgi-bin/roundup.cgi/bugs/user?template=register
1582 ...before sending mail to the tracker.
1584 Unknown address: nonexisting@bork.bork.bork
1586 --===============0639262320==
1587 Content-Type: text/plain; charset="us-ascii"
1588 MIME-Version: 1.0
1589 Content-Transfer-Encoding: 7bit
1591 Content-Type: text/plain;
1592 charset="iso-8859-1"
1593 From: Nonexisting User <nonexisting@bork.bork.bork>
1594 To: issue_tracker@your.tracker.email.domain.example
1595 Message-Id: <dummy_test_message_id>
1596 Subject: [issue] Testing nonexisting user...
1598 This is a test submission of a new issue.
1600 --===============0639262320==--
1601 ''')
1603 def testEnc01(self):
1604 self.db.user.set(self.mary_id,
1605 realname='\xe4\xf6\xfc\xc4\xd6\xdc\xdf, Mary'.decode
1606 ('latin-1').encode('utf-8'))
1607 self.doNewIssue()
1608 self._handle_mail('''Content-Type: text/plain;
1609 charset="iso-8859-1"
1610 From: mary <mary@test.test>
1611 To: issue_tracker@your.tracker.email.domain.example
1612 Message-Id: <followup_dummy_id>
1613 In-Reply-To: <dummy_test_message_id>
1614 Subject: [issue1] Testing...
1615 Content-Type: text/plain;
1616 charset="iso-8859-1"
1617 Content-Transfer-Encoding: quoted-printable
1619 A message with encoding (encoded oe =F6)
1621 ''')
1622 self.compareMessages(self._get_mail(),
1623 '''FROM: roundup-admin@your.tracker.email.domain.example
1624 TO: chef@bork.bork.bork, richard@test.test
1625 Content-Type: text/plain; charset="utf-8"
1626 Subject: [issue1] Testing...
1627 To: chef@bork.bork.bork, richard@test.test
1628 From: =?utf-8?b?w6TDtsO8w4TDlsOcw58sIE1hcnk=?=
1629 <issue_tracker@your.tracker.email.domain.example>
1630 Reply-To: Roundup issue tracker
1631 <issue_tracker@your.tracker.email.domain.example>
1632 MIME-Version: 1.0
1633 Message-Id: <followup_dummy_id>
1634 In-Reply-To: <dummy_test_message_id>
1635 X-Roundup-Name: Roundup issue tracker
1636 X-Roundup-Loop: hello
1637 X-Roundup-Issue-Status: chatting
1638 Content-Transfer-Encoding: quoted-printable
1641 =C3=A4=C3=B6=C3=BC=C3=84=C3=96=C3=9C=C3=9F, Mary <mary@test.test> added the=
1642 comment:
1644 A message with encoding (encoded oe =C3=B6)
1646 ----------
1647 status: unread -> chatting
1649 _______________________________________________________________________
1650 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1651 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1652 _______________________________________________________________________
1653 ''')
1655 def testEncNonUTF8(self):
1656 self.doNewIssue()
1657 self.instance.config.EMAIL_CHARSET = 'iso-8859-1'
1658 self._handle_mail('''Content-Type: text/plain;
1659 charset="iso-8859-1"
1660 From: mary <mary@test.test>
1661 To: issue_tracker@your.tracker.email.domain.example
1662 Message-Id: <followup_dummy_id>
1663 In-Reply-To: <dummy_test_message_id>
1664 Subject: [issue1] Testing...
1665 Content-Type: text/plain;
1666 charset="iso-8859-1"
1667 Content-Transfer-Encoding: quoted-printable
1669 A message with encoding (encoded oe =F6)
1671 ''')
1672 self.compareMessages(self._get_mail(),
1673 '''FROM: roundup-admin@your.tracker.email.domain.example
1674 TO: chef@bork.bork.bork, richard@test.test
1675 Content-Type: text/plain; charset="iso-8859-1"
1676 Subject: [issue1] Testing...
1677 To: chef@bork.bork.bork, richard@test.test
1678 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
1679 Reply-To: Roundup issue tracker
1680 <issue_tracker@your.tracker.email.domain.example>
1681 MIME-Version: 1.0
1682 Message-Id: <followup_dummy_id>
1683 In-Reply-To: <dummy_test_message_id>
1684 X-Roundup-Name: Roundup issue tracker
1685 X-Roundup-Loop: hello
1686 X-Roundup-Issue-Status: chatting
1687 Content-Transfer-Encoding: quoted-printable
1690 Contrary, Mary <mary@test.test> added the comment:
1692 A message with encoding (encoded oe =F6)
1694 ----------
1695 status: unread -> chatting
1697 _______________________________________________________________________
1698 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1699 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1700 _______________________________________________________________________
1701 ''')
1704 def testMultipartEnc01(self):
1705 self.doNewIssue()
1706 self._handle_mail('''Content-Type: text/plain;
1707 charset="iso-8859-1"
1708 From: mary <mary@test.test>
1709 To: issue_tracker@your.tracker.email.domain.example
1710 Message-Id: <followup_dummy_id>
1711 In-Reply-To: <dummy_test_message_id>
1712 Subject: [issue1] Testing...
1713 Content-Type: multipart/mixed;
1714 boundary="----_=_NextPart_000_01"
1716 This message is in MIME format. Since your mail reader does not understand
1717 this format, some or all of this message may not be legible.
1719 ------_=_NextPart_000_01
1720 Content-Type: text/plain;
1721 charset="iso-8859-1"
1722 Content-Transfer-Encoding: quoted-printable
1724 A message with first part encoded (encoded oe =F6)
1726 ''')
1727 self.compareMessages(self._get_mail(),
1728 '''FROM: roundup-admin@your.tracker.email.domain.example
1729 TO: chef@bork.bork.bork, richard@test.test
1730 Content-Type: text/plain; charset="utf-8"
1731 Subject: [issue1] Testing...
1732 To: chef@bork.bork.bork, richard@test.test
1733 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
1734 Reply-To: Roundup issue tracker
1735 <issue_tracker@your.tracker.email.domain.example>
1736 MIME-Version: 1.0
1737 Message-Id: <followup_dummy_id>
1738 In-Reply-To: <dummy_test_message_id>
1739 X-Roundup-Name: Roundup issue tracker
1740 X-Roundup-Loop: hello
1741 X-Roundup-Issue-Status: chatting
1742 Content-Transfer-Encoding: quoted-printable
1745 Contrary, Mary <mary@test.test> added the comment:
1747 A message with first part encoded (encoded oe =C3=B6)
1749 ----------
1750 status: unread -> chatting
1752 _______________________________________________________________________
1753 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1754 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1755 _______________________________________________________________________
1756 ''')
1758 def testContentDisposition(self):
1759 self.doNewIssue()
1760 self._handle_mail('''Content-Type: text/plain;
1761 charset="iso-8859-1"
1762 From: mary <mary@test.test>
1763 To: issue_tracker@your.tracker.email.domain.example
1764 Message-Id: <followup_dummy_id>
1765 In-Reply-To: <dummy_test_message_id>
1766 Subject: [issue1] Testing...
1767 Content-Type: multipart/mixed; boundary="bCsyhTFzCvuiizWE"
1768 Content-Disposition: inline
1771 --bCsyhTFzCvuiizWE
1772 Content-Type: text/plain; charset=us-ascii
1773 Content-Disposition: inline
1775 test attachment binary
1777 --bCsyhTFzCvuiizWE
1778 Content-Type: application/octet-stream
1779 Content-Disposition: attachment; filename="main.dvi"
1780 Content-Transfer-Encoding: base64
1782 SnVzdCBhIHRlc3QgAQo=
1784 --bCsyhTFzCvuiizWE--
1785 ''')
1786 messages = self.db.issue.get('1', 'messages')
1787 messages.sort()
1788 file = self.db.file.getnode (self.db.msg.get(messages[-1], 'files')[0])
1789 self.assertEqual(file.name, 'main.dvi')
1790 self.assertEqual(file.content, 'Just a test \001\n')
1792 def testFollowupStupidQuoting(self):
1793 self.doNewIssue()
1795 self._handle_mail('''Content-Type: text/plain;
1796 charset="iso-8859-1"
1797 From: richard <richard@test.test>
1798 To: issue_tracker@your.tracker.email.domain.example
1799 Message-Id: <followup_dummy_id>
1800 In-Reply-To: <dummy_test_message_id>
1801 Subject: Re: "[issue1] Testing... "
1803 This is a followup
1804 ''')
1805 self.compareMessages(self._get_mail(),
1806 '''FROM: roundup-admin@your.tracker.email.domain.example
1807 TO: chef@bork.bork.bork
1808 Content-Type: text/plain; charset="utf-8"
1809 Subject: [issue1] Testing...
1810 To: chef@bork.bork.bork
1811 From: richard <issue_tracker@your.tracker.email.domain.example>
1812 Reply-To: Roundup issue tracker
1813 <issue_tracker@your.tracker.email.domain.example>
1814 MIME-Version: 1.0
1815 Message-Id: <followup_dummy_id>
1816 In-Reply-To: <dummy_test_message_id>
1817 X-Roundup-Name: Roundup issue tracker
1818 X-Roundup-Loop: hello
1819 X-Roundup-Issue-Status: chatting
1820 Content-Transfer-Encoding: quoted-printable
1823 richard <richard@test.test> added the comment:
1825 This is a followup
1827 ----------
1828 status: unread -> chatting
1830 _______________________________________________________________________
1831 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
1832 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
1833 _______________________________________________________________________
1834 ''')
1836 def testEmailQuoting(self):
1837 self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'no'
1838 self.innerTestQuoting('''This is a followup
1839 ''')
1841 def testEmailQuotingRemove(self):
1842 self.instance.config.EMAIL_KEEP_QUOTED_TEXT = 'yes'
1843 self.innerTestQuoting('''Blah blah wrote:
1844 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
1845 > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
1846 >
1848 This is a followup
1849 ''')
1851 def innerTestQuoting(self, expect):
1852 nodeid = self.doNewIssue()
1854 messages = self.db.issue.get(nodeid, 'messages')
1856 self._handle_mail('''Content-Type: text/plain;
1857 charset="iso-8859-1"
1858 From: richard <richard@test.test>
1859 To: issue_tracker@your.tracker.email.domain.example
1860 Message-Id: <followup_dummy_id>
1861 In-Reply-To: <dummy_test_message_id>
1862 Subject: Re: [issue1] Testing...
1864 Blah blah wrote:
1865 > Blah bklaskdfj sdf asdf jlaskdf skj sdkfjl asdf
1866 > skdjlkjsdfalsdkfjasdlfkj dlfksdfalksd fj
1867 >
1869 This is a followup
1870 ''')
1871 # figure the new message id
1872 newmessages = self.db.issue.get(nodeid, 'messages')
1873 for msg in messages:
1874 newmessages.remove(msg)
1875 messageid = newmessages[0]
1877 self.compareMessages(self.db.msg.get(messageid, 'content'), expect)
1879 def testUserLookup(self):
1880 i = self.db.user.create(username='user1', address='user1@foo.com')
1881 self.assertEqual(uidFromAddress(self.db, ('', 'user1@foo.com'), 0), i)
1882 self.assertEqual(uidFromAddress(self.db, ('', 'USER1@foo.com'), 0), i)
1883 i = self.db.user.create(username='user2', address='USER2@foo.com')
1884 self.assertEqual(uidFromAddress(self.db, ('', 'USER2@foo.com'), 0), i)
1885 self.assertEqual(uidFromAddress(self.db, ('', 'user2@foo.com'), 0), i)
1887 def testUserAlternateLookup(self):
1888 i = self.db.user.create(username='user1', address='user1@foo.com',
1889 alternate_addresses='user1@bar.com')
1890 self.assertEqual(uidFromAddress(self.db, ('', 'user1@bar.com'), 0), i)
1891 self.assertEqual(uidFromAddress(self.db, ('', 'USER1@bar.com'), 0), i)
1893 def testUserCreate(self):
1894 i = uidFromAddress(self.db, ('', 'user@foo.com'), 1)
1895 self.assertNotEqual(uidFromAddress(self.db, ('', 'user@bar.com'), 1), i)
1897 def testRFC2822(self):
1898 ascii_header = "[issue243] This is a \"test\" - with 'quotation' marks"
1899 unicode_header = '[issue244] \xd0\xb0\xd0\xbd\xd0\xb4\xd1\x80\xd0\xb5\xd0\xb9'
1900 unicode_encoded = '=?utf-8?q?[issue244]_=D0=B0=D0=BD=D0=B4=D1=80=D0=B5=D0=B9?='
1901 self.assertEqual(rfc2822.encode_header(ascii_header), ascii_header)
1902 self.assertEqual(rfc2822.encode_header(unicode_header), unicode_encoded)
1904 def testRegistrationConfirmation(self):
1905 otk = "Aj4euk4LZSAdwePohj90SME5SpopLETL"
1906 self.db.getOTKManager().set(otk, username='johannes')
1907 self._handle_mail('''Content-Type: text/plain;
1908 charset="iso-8859-1"
1909 From: Chef <chef@bork.bork.bork>
1910 To: issue_tracker@your.tracker.email.domain.example
1911 Cc: richard@test.test
1912 Message-Id: <dummy_test_message_id>
1913 Subject: Re: Complete your registration to Roundup issue tracker
1914 -- key %s
1916 This is a test confirmation of registration.
1917 ''' % otk)
1918 self.db.user.lookup('johannes')
1920 def testFollowupOnNonIssue(self):
1921 self.db.keyword.create(name='Foo')
1922 self._handle_mail('''Content-Type: text/plain;
1923 charset="iso-8859-1"
1924 From: richard <richard@test.test>
1925 To: issue_tracker@your.tracker.email.domain.example
1926 Message-Id: <followup_dummy_id>
1927 In-Reply-To: <dummy_test_message_id>
1928 Subject: [keyword1] Testing... [name=Bar]
1930 ''')
1931 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
1933 def testResentFrom(self):
1934 nodeid = self._handle_mail('''Content-Type: text/plain;
1935 charset="iso-8859-1"
1936 From: Chef <chef@bork.bork.bork>
1937 Resent-From: mary <mary@test.test>
1938 To: issue_tracker@your.tracker.email.domain.example
1939 Cc: richard@test.test
1940 Message-Id: <dummy_test_message_id>
1941 Subject: [issue] Testing...
1943 This is a test submission of a new issue.
1944 ''')
1945 assert not os.path.exists(SENDMAILDEBUG)
1946 l = self.db.issue.get(nodeid, 'nosy')
1947 l.sort()
1948 self.assertEqual(l, [self.richard_id, self.mary_id])
1949 return nodeid
1951 def testDejaVu(self):
1952 self.assertRaises(IgnoreLoop, self._handle_mail,
1953 '''Content-Type: text/plain;
1954 charset="iso-8859-1"
1955 From: Chef <chef@bork.bork.bork>
1956 X-Roundup-Loop: hello
1957 To: issue_tracker@your.tracker.email.domain.example
1958 Cc: richard@test.test
1959 Message-Id: <dummy_test_message_id>
1960 Subject: Re: [issue] Testing...
1962 Hi, I've been mis-configured to loop messages back to myself.
1963 ''')
1965 def testItsBulkStupid(self):
1966 self.assertRaises(IgnoreBulk, self._handle_mail,
1967 '''Content-Type: text/plain;
1968 charset="iso-8859-1"
1969 From: Chef <chef@bork.bork.bork>
1970 Precedence: bulk
1971 To: issue_tracker@your.tracker.email.domain.example
1972 Cc: richard@test.test
1973 Message-Id: <dummy_test_message_id>
1974 Subject: Re: [issue] Testing...
1976 Hi, I'm on holidays, and this is a dumb auto-responder.
1977 ''')
1979 def testAutoReplyEmailsAreIgnored(self):
1980 self.assertRaises(IgnoreBulk, self._handle_mail,
1981 '''Content-Type: text/plain;
1982 charset="iso-8859-1"
1983 From: Chef <chef@bork.bork.bork>
1984 To: issue_tracker@your.tracker.email.domain.example
1985 Cc: richard@test.test
1986 Message-Id: <dummy_test_message_id>
1987 Subject: Re: [issue] Out of office AutoReply: Back next week
1989 Hi, I am back in the office next week
1990 ''')
1992 def testNoSubject(self):
1993 self.assertRaises(MailUsageError, self._handle_mail,
1994 '''Content-Type: text/plain;
1995 charset="iso-8859-1"
1996 From: Chef <chef@bork.bork.bork>
1997 To: issue_tracker@your.tracker.email.domain.example
1998 Cc: richard@test.test
1999 Reply-To: chef@bork.bork.bork
2000 Message-Id: <dummy_test_message_id>
2002 ''')
2004 #
2005 # TEST FOR INVALID DESIGNATOR HANDLING
2006 #
2007 def testInvalidDesignator(self):
2008 self.assertRaises(MailUsageError, self._handle_mail,
2009 '''Content-Type: text/plain;
2010 charset="iso-8859-1"
2011 From: Chef <chef@bork.bork.bork>
2012 To: issue_tracker@your.tracker.email.domain.example
2013 Subject: [frobulated] testing
2014 Cc: richard@test.test
2015 Reply-To: chef@bork.bork.bork
2016 Message-Id: <dummy_test_message_id>
2018 ''')
2019 self.assertRaises(MailUsageError, self._handle_mail,
2020 '''Content-Type: text/plain;
2021 charset="iso-8859-1"
2022 From: Chef <chef@bork.bork.bork>
2023 To: issue_tracker@your.tracker.email.domain.example
2024 Subject: [issue12345] testing
2025 Cc: richard@test.test
2026 Reply-To: chef@bork.bork.bork
2027 Message-Id: <dummy_test_message_id>
2029 ''')
2031 def testInvalidClassLoose(self):
2032 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
2033 nodeid = self._handle_mail('''Content-Type: text/plain;
2034 charset="iso-8859-1"
2035 From: Chef <chef@bork.bork.bork>
2036 To: issue_tracker@your.tracker.email.domain.example
2037 Subject: [frobulated] testing
2038 Cc: richard@test.test
2039 Reply-To: chef@bork.bork.bork
2040 Message-Id: <dummy_test_message_id>
2042 ''')
2043 assert not os.path.exists(SENDMAILDEBUG)
2044 self.assertEqual(self.db.issue.get(nodeid, 'title'),
2045 '[frobulated] testing')
2047 def testInvalidClassLooseReply(self):
2048 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
2049 nodeid = self._handle_mail('''Content-Type: text/plain;
2050 charset="iso-8859-1"
2051 From: Chef <chef@bork.bork.bork>
2052 To: issue_tracker@your.tracker.email.domain.example
2053 Subject: Re: [frobulated] testing
2054 Cc: richard@test.test
2055 Reply-To: chef@bork.bork.bork
2056 Message-Id: <dummy_test_message_id>
2058 ''')
2059 assert not os.path.exists(SENDMAILDEBUG)
2060 self.assertEqual(self.db.issue.get(nodeid, 'title'),
2061 '[frobulated] testing')
2063 def testInvalidClassLoose(self):
2064 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
2065 nodeid = self._handle_mail('''Content-Type: text/plain;
2066 charset="iso-8859-1"
2067 From: Chef <chef@bork.bork.bork>
2068 To: issue_tracker@your.tracker.email.domain.example
2069 Subject: [issue1234] testing
2070 Cc: richard@test.test
2071 Reply-To: chef@bork.bork.bork
2072 Message-Id: <dummy_test_message_id>
2074 ''')
2075 assert not os.path.exists(SENDMAILDEBUG)
2076 self.assertEqual(self.db.issue.get(nodeid, 'title'),
2077 '[issue1234] testing')
2079 def testClassLooseOK(self):
2080 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
2081 self.db.keyword.create(name='Foo')
2082 nodeid = self._handle_mail('''Content-Type: text/plain;
2083 charset="iso-8859-1"
2084 From: Chef <chef@bork.bork.bork>
2085 To: issue_tracker@your.tracker.email.domain.example
2086 Subject: [keyword1] Testing... [name=Bar]
2087 Cc: richard@test.test
2088 Reply-To: chef@bork.bork.bork
2089 Message-Id: <dummy_test_message_id>
2091 ''')
2092 assert not os.path.exists(SENDMAILDEBUG)
2093 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
2095 def testClassStrictInvalid(self):
2096 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'strict'
2097 self.instance.config.MAILGW_DEFAULT_CLASS = ''
2099 message = '''Content-Type: text/plain;
2100 charset="iso-8859-1"
2101 From: Chef <chef@bork.bork.bork>
2102 To: issue_tracker@your.tracker.email.domain.example
2103 Subject: Testing...
2104 Cc: richard@test.test
2105 Reply-To: chef@bork.bork.bork
2106 Message-Id: <dummy_test_message_id>
2108 '''
2109 self.assertRaises(MailUsageError, self._handle_mail, message)
2111 def testClassStrictValid(self):
2112 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'strict'
2113 self.instance.config.MAILGW_DEFAULT_CLASS = ''
2115 nodeid = self._handle_mail('''Content-Type: text/plain;
2116 charset="iso-8859-1"
2117 From: Chef <chef@bork.bork.bork>
2118 To: issue_tracker@your.tracker.email.domain.example
2119 Subject: [issue] Testing...
2120 Cc: richard@test.test
2121 Reply-To: chef@bork.bork.bork
2122 Message-Id: <dummy_test_message_id>
2124 ''')
2126 assert not os.path.exists(SENDMAILDEBUG)
2127 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'Testing...')
2129 #
2130 # TEST FOR INVALID COMMANDS HANDLING
2131 #
2132 def testInvalidCommands(self):
2133 self.assertRaises(MailUsageError, self._handle_mail,
2134 '''Content-Type: text/plain;
2135 charset="iso-8859-1"
2136 From: Chef <chef@bork.bork.bork>
2137 To: issue_tracker@your.tracker.email.domain.example
2138 Subject: testing [frobulated]
2139 Cc: richard@test.test
2140 Reply-To: chef@bork.bork.bork
2141 Message-Id: <dummy_test_message_id>
2143 ''')
2145 def testInvalidCommandPassthrough(self):
2146 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'none'
2147 nodeid = self._handle_mail('''Content-Type: text/plain;
2148 charset="iso-8859-1"
2149 From: Chef <chef@bork.bork.bork>
2150 To: issue_tracker@your.tracker.email.domain.example
2151 Subject: testing [frobulated]
2152 Cc: richard@test.test
2153 Reply-To: chef@bork.bork.bork
2154 Message-Id: <dummy_test_message_id>
2156 ''')
2157 assert not os.path.exists(SENDMAILDEBUG)
2158 self.assertEqual(self.db.issue.get(nodeid, 'title'),
2159 'testing [frobulated]')
2161 def testInvalidCommandPassthroughLoose(self):
2162 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'loose'
2163 nodeid = self._handle_mail('''Content-Type: text/plain;
2164 charset="iso-8859-1"
2165 From: Chef <chef@bork.bork.bork>
2166 To: issue_tracker@your.tracker.email.domain.example
2167 Subject: testing [frobulated]
2168 Cc: richard@test.test
2169 Reply-To: chef@bork.bork.bork
2170 Message-Id: <dummy_test_message_id>
2172 ''')
2173 assert not os.path.exists(SENDMAILDEBUG)
2174 self.assertEqual(self.db.issue.get(nodeid, 'title'),
2175 'testing [frobulated]')
2177 def testInvalidCommandPassthroughLooseOK(self):
2178 self.instance.config.MAILGW_SUBJECT_SUFFIX_PARSING = 'loose'
2179 nodeid = self._handle_mail('''Content-Type: text/plain;
2180 charset="iso-8859-1"
2181 From: Chef <chef@bork.bork.bork>
2182 To: issue_tracker@your.tracker.email.domain.example
2183 Subject: testing [assignedto=mary]
2184 Cc: richard@test.test
2185 Reply-To: chef@bork.bork.bork
2186 Message-Id: <dummy_test_message_id>
2188 ''')
2189 assert not os.path.exists(SENDMAILDEBUG)
2190 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing')
2191 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), self.mary_id)
2193 def testCommandDelimiters(self):
2194 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
2195 nodeid = self._handle_mail('''Content-Type: text/plain;
2196 charset="iso-8859-1"
2197 From: Chef <chef@bork.bork.bork>
2198 To: issue_tracker@your.tracker.email.domain.example
2199 Subject: testing {assignedto=mary}
2200 Cc: richard@test.test
2201 Reply-To: chef@bork.bork.bork
2202 Message-Id: <dummy_test_message_id>
2204 ''')
2205 assert not os.path.exists(SENDMAILDEBUG)
2206 self.assertEqual(self.db.issue.get(nodeid, 'title'), 'testing')
2207 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), self.mary_id)
2209 def testPrefixDelimiters(self):
2210 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
2211 self.db.keyword.create(name='Foo')
2212 self._handle_mail('''Content-Type: text/plain;
2213 charset="iso-8859-1"
2214 From: richard <richard@test.test>
2215 To: issue_tracker@your.tracker.email.domain.example
2216 Message-Id: <followup_dummy_id>
2217 In-Reply-To: <dummy_test_message_id>
2218 Subject: {keyword1} Testing... {name=Bar}
2220 ''')
2221 assert not os.path.exists(SENDMAILDEBUG)
2222 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
2224 def testCommandDelimitersIgnore(self):
2225 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '{}'
2226 nodeid = self._handle_mail('''Content-Type: text/plain;
2227 charset="iso-8859-1"
2228 From: Chef <chef@bork.bork.bork>
2229 To: issue_tracker@your.tracker.email.domain.example
2230 Subject: testing [assignedto=mary]
2231 Cc: richard@test.test
2232 Reply-To: chef@bork.bork.bork
2233 Message-Id: <dummy_test_message_id>
2235 ''')
2236 assert not os.path.exists(SENDMAILDEBUG)
2237 self.assertEqual(self.db.issue.get(nodeid, 'title'),
2238 'testing [assignedto=mary]')
2239 self.assertEqual(self.db.issue.get(nodeid, 'assignedto'), None)
2241 def testReplytoMatch(self):
2242 self.instance.config.MAILGW_SUBJECT_PREFIX_PARSING = 'loose'
2243 nodeid = self.doNewIssue()
2244 nodeid2 = self._handle_mail('''Content-Type: text/plain;
2245 charset="iso-8859-1"
2246 From: Chef <chef@bork.bork.bork>
2247 To: issue_tracker@your.tracker.email.domain.example
2248 Message-Id: <dummy_test_message_id2>
2249 In-Reply-To: <dummy_test_message_id>
2250 Subject: Testing...
2252 Followup message.
2253 ''')
2255 nodeid3 = self._handle_mail('''Content-Type: text/plain;
2256 charset="iso-8859-1"
2257 From: Chef <chef@bork.bork.bork>
2258 To: issue_tracker@your.tracker.email.domain.example
2259 Message-Id: <dummy_test_message_id3>
2260 In-Reply-To: <dummy_test_message_id2>
2261 Subject: Testing...
2263 Yet another message in the same thread/issue.
2264 ''')
2266 self.assertEqual(nodeid, nodeid2)
2267 self.assertEqual(nodeid, nodeid3)
2269 def testHelpSubject(self):
2270 message = '''Content-Type: text/plain;
2271 charset="iso-8859-1"
2272 From: Chef <chef@bork.bork.bork>
2273 To: issue_tracker@your.tracker.email.domain.example
2274 Message-Id: <dummy_test_message_id2>
2275 In-Reply-To: <dummy_test_message_id>
2276 Subject: hElp
2279 '''
2280 self.assertRaises(MailUsageHelp, self._handle_mail, message)
2282 def testMaillistSubject(self):
2283 self.instance.config.MAILGW_SUBJECT_SUFFIX_DELIMITERS = '[]'
2284 self.db.keyword.create(name='Foo')
2285 self._handle_mail('''Content-Type: text/plain;
2286 charset="iso-8859-1"
2287 From: Chef <chef@bork.bork.bork>
2288 To: issue_tracker@your.tracker.email.domain.example
2289 Subject: [mailinglist-name] [keyword1] Testing.. [name=Bar]
2290 Cc: richard@test.test
2291 Reply-To: chef@bork.bork.bork
2292 Message-Id: <dummy_test_message_id>
2294 ''')
2296 assert not os.path.exists(SENDMAILDEBUG)
2297 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
2299 def testUnknownPrefixSubject(self):
2300 self.db.keyword.create(name='Foo')
2301 self._handle_mail('''Content-Type: text/plain;
2302 charset="iso-8859-1"
2303 From: Chef <chef@bork.bork.bork>
2304 To: issue_tracker@your.tracker.email.domain.example
2305 Subject: VeryStrangeRe: [keyword1] Testing.. [name=Bar]
2306 Cc: richard@test.test
2307 Reply-To: chef@bork.bork.bork
2308 Message-Id: <dummy_test_message_id>
2310 ''')
2312 assert not os.path.exists(SENDMAILDEBUG)
2313 self.assertEqual(self.db.keyword.get('1', 'name'), 'Bar')
2315 def testOneCharSubject(self):
2316 message = '''Content-Type: text/plain;
2317 charset="iso-8859-1"
2318 From: Chef <chef@bork.bork.bork>
2319 To: issue_tracker@your.tracker.email.domain.example
2320 Subject: b
2321 Cc: richard@test.test
2322 Reply-To: chef@bork.bork.bork
2323 Message-Id: <dummy_test_message_id>
2325 '''
2326 try:
2327 self._handle_mail(message)
2328 except MailUsageError:
2329 self.fail('MailUsageError raised')
2331 def testIssueidLast(self):
2332 nodeid1 = self.doNewIssue()
2333 nodeid2 = self._handle_mail('''Content-Type: text/plain;
2334 charset="iso-8859-1"
2335 From: mary <mary@test.test>
2336 To: issue_tracker@your.tracker.email.domain.example
2337 Message-Id: <followup_dummy_id>
2338 In-Reply-To: <dummy_test_message_id>
2339 Subject: New title [issue1]
2341 This is a second followup
2342 ''')
2344 assert nodeid1 == nodeid2
2345 self.assertEqual(self.db.issue.get(nodeid2, 'title'), "Testing...")
2347 def testSecurityMessagePermissionContent(self):
2348 id = self.doNewIssue()
2349 issue = self.db.issue.getnode (id)
2350 self.db.security.addRole(name='Nomsg')
2351 self.db.security.addPermissionToRole('Nomsg', 'Email Access')
2352 for cl in 'issue', 'file', 'keyword':
2353 for p in 'View', 'Edit', 'Create':
2354 self.db.security.addPermissionToRole('Nomsg', p, cl)
2355 self.db.user.set(self.mary_id, roles='Nomsg')
2356 nodeid = self._handle_mail('''Content-Type: text/plain;
2357 charset="iso-8859-1"
2358 From: Chef <chef@bork.bork.bork>
2359 To: issue_tracker@your.tracker.email.domain.example
2360 Message-Id: <dummy_test_message_id_2>
2361 Subject: [issue%(id)s] Testing... [nosy=+mary]
2363 Just a test reply
2364 '''%locals())
2365 assert os.path.exists(SENDMAILDEBUG)
2366 self.compareMessages(self._get_mail(),
2367 '''FROM: roundup-admin@your.tracker.email.domain.example
2368 TO: chef@bork.bork.bork, richard@test.test
2369 Content-Type: text/plain; charset="utf-8"
2370 Subject: [issue1] Testing...
2371 To: richard@test.test
2372 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
2373 Reply-To: Roundup issue tracker
2374 <issue_tracker@your.tracker.email.domain.example>
2375 MIME-Version: 1.0
2376 Message-Id: <dummy_test_message_id_2>
2377 In-Reply-To: <dummy_test_message_id>
2378 X-Roundup-Name: Roundup issue tracker
2379 X-Roundup-Loop: hello
2380 X-Roundup-Issue-Status: chatting
2381 Content-Transfer-Encoding: quoted-printable
2384 Bork, Chef <chef@bork.bork.bork> added the comment:
2386 Just a test reply
2388 ----------
2389 nosy: +mary
2390 status: unread -> chatting
2392 _______________________________________________________________________
2393 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
2394 <http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
2395 _______________________________________________________________________
2396 ''')
2398 def testOutlookAttachment(self):
2399 message = '''X-MimeOLE: Produced By Microsoft Exchange V6.5
2400 Content-class: urn:content-classes:message
2401 MIME-Version: 1.0
2402 Content-Type: multipart/mixed;
2403 boundary="----_=_NextPart_001_01CACA65.40A51CBC"
2404 Subject: Example of a failed outlook attachment e-mail
2405 Date: Tue, 23 Mar 2010 01:43:44 -0700
2406 Message-ID: <CA37F17219784343816CA6613D2E339205E7D0F9@nrcwstexb1.nrc.ca>
2407 X-MS-Has-Attach: yes
2408 X-MS-TNEF-Correlator:
2409 Thread-Topic: Example of a failed outlook attachment e-mail
2410 Thread-Index: AcrKJo/t3pUBBwTpSwWNE3LE67UBDQ==
2411 From: "Hugh" <richard@test.test>
2412 To: <richard@test.test>
2413 X-OriginalArrivalTime: 23 Mar 2010 08:45:57.0350 (UTC) FILETIME=[41893860:01CACA65]
2415 This is a multi-part message in MIME format.
2417 ------_=_NextPart_001_01CACA65.40A51CBC
2418 Content-Type: multipart/alternative;
2419 boundary="----_=_NextPart_002_01CACA65.40A51CBC"
2422 ------_=_NextPart_002_01CACA65.40A51CBC
2423 Content-Type: text/plain;
2424 charset="us-ascii"
2425 Content-Transfer-Encoding: quoted-printable
2428 Hi Richard,
2430 I suppose this isn't the exact message that was sent but is a resend of
2431 one of my trial messages that failed. For your benefit I changed the
2432 subject line and am adding these words to the message body. Should
2433 still be as problematic, but if you like I can resend an exact copy of a
2434 failed message changing nothing except putting your address instead of
2435 our tracker.
2437 Thanks very much for taking time to look into this. Much appreciated.
2439 <<battery backup>>=20
2441 ------_=_NextPart_002_01CACA65.40A51CBC
2442 Content-Type: text/html;
2443 charset="us-ascii"
2444 Content-Transfer-Encoding: quoted-printable
2446 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
2447 <HTML>
2448 <HEAD>
2449 <META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =
2450 charset=3Dus-ascii">
2451 <META NAME=3D"Generator" CONTENT=3D"MS Exchange Server version =
2452 6.5.7654.12">
2453 <TITLE>Example of a failed outlook attachment e-mail</TITLE>
2454 </HEAD>
2455 <BODY>
2456 <!-- Converted from text/rtf format -->
2457 <BR>
2459 <P><FONT SIZE=3D2 FACE=3D"Arial">Hi Richard,</FONT>
2460 </P>
2462 <P><FONT SIZE=3D2 FACE=3D"Arial">I suppose this isn't the exact message =
2463 that was sent but is a resend of one of my trial messages that =
2464 failed. For your benefit I changed the subject line and am adding =
2465 these words to the message body. Should still be as problematic, =
2466 but if you like I can resend an exact copy of a failed message changing =
2467 nothing except putting your address instead of our tracker.</FONT></P>
2469 <P><FONT SIZE=3D2 FACE=3D"Arial">Thanks very much for taking time to =
2470 look into this. Much appreciated.</FONT>
2471 </P>
2472 <BR>
2474 <P><FONT FACE=3D"Arial" SIZE=3D2 COLOR=3D"#000000"> <<battery =
2475 backup>> </FONT>
2476 </P>
2478 </BODY>
2479 </HTML>
2480 ------_=_NextPart_002_01CACA65.40A51CBC--
2482 ------_=_NextPart_001_01CACA65.40A51CBC
2483 Content-Type: message/rfc822
2484 Content-Transfer-Encoding: 7bit
2486 X-MimeOLE: Produced By Microsoft Exchange V6.5
2487 MIME-Version: 1.0
2488 Content-Type: multipart/alternative;
2489 boundary="----_=_NextPart_003_01CAC15A.29717800"
2490 X-OriginalArrivalTime: 11 Mar 2010 20:33:51.0249 (UTC) FILETIME=[28FEE010:01CAC15A]
2491 Content-class: urn:content-classes:message
2492 Subject: battery backup
2493 Date: Thu, 11 Mar 2010 13:33:43 -0700
2494 Message-ID: <p06240809c7bf02f9624c@[128.114.22.203]>
2495 X-MS-Has-Attach:
2496 X-MS-TNEF-Correlator:
2497 Thread-Topic: battery backup
2498 Thread-Index: AcrBWimtulTrSvBdQ2CcfZ8lyQdxmQ==
2499 From: "Jerry" <jerry@test.test>
2500 To: "Hugh" <hugh@test.test>
2502 This is a multi-part message in MIME format.
2504 ------_=_NextPart_003_01CAC15A.29717800
2505 Content-Type: text/plain;
2506 charset="iso-8859-1"
2507 Content-Transfer-Encoding: quoted-printable
2509 Dear Hugh,
2510 A car batter has an energy capacity of ~ 500Wh. A UPS=20
2511 battery is worse than this.
2513 if we need to provied 100kW for 30 minutes that will take 100 car=20
2514 batteries. This seems like an awful lot of batteries.
2516 Of course I like your idea of making the time 1 minute, so we get to=20
2517 a more modest number of batteries
2519 Jerry
2522 ------_=_NextPart_003_01CAC15A.29717800
2523 Content-Type: text/html;
2524 charset="iso-8859-1"
2525 Content-Transfer-Encoding: quoted-printable
2527 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
2528 <HTML>
2529 <HEAD>
2530 <META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =
2531 charset=3Diso-8859-1">
2532 <META NAME=3D"Generator" CONTENT=3D"MS Exchange Server version =
2533 6.5.7654.12">
2534 <TITLE>battery backup</TITLE>
2535 </HEAD>
2536 <BODY>
2537 <!-- Converted from text/plain format -->
2539 <P><FONT SIZE=3D2>Dear Hugh,</FONT>
2541 <BR> <FONT SIZE=3D2>A car =
2542 batter has an energy capacity of ~ 500Wh. A UPS </FONT>
2544 <BR><FONT SIZE=3D2>battery is worse than this.</FONT>
2545 </P>
2547 <P><FONT SIZE=3D2>if we need to provied 100kW for 30 minutes that will =
2548 take 100 car </FONT>
2550 <BR><FONT SIZE=3D2>batteries. This seems like an awful lot of =
2551 batteries.</FONT>
2552 </P>
2554 <P><FONT SIZE=3D2>Of course I like your idea of making the time 1 =
2555 minute, so we get to </FONT>
2557 <BR><FONT SIZE=3D2>a more modest number of batteries</FONT>
2558 </P>
2560 <P><FONT SIZE=3D2>Jerry</FONT>
2561 </P>
2563 </BODY>
2564 </HTML>
2565 ------_=_NextPart_003_01CAC15A.29717800--
2567 ------_=_NextPart_001_01CACA65.40A51CBC--
2568 '''
2569 nodeid = self._handle_mail(message)
2570 assert not os.path.exists(SENDMAILDEBUG)
2571 msgid = self.db.issue.get(nodeid, 'messages')[0]
2572 self.assert_(self.db.msg.get(msgid, 'content').startswith('Hi Richard'))
2573 self.assertEqual(self.db.msg.get(msgid, 'files'), ['1', '2'])
2574 fileid = self.db.msg.get(msgid, 'files')[0]
2575 self.assertEqual(self.db.file.get(fileid, 'type'), 'text/html')
2576 fileid = self.db.msg.get(msgid, 'files')[1]
2577 self.assertEqual(self.db.file.get(fileid, 'type'), 'message/rfc822')
2579 def testForwardedMessageAttachment(self):
2580 message = '''Return-Path: <rgg@test.test>
2581 Received: from localhost(127.0.0.1), claiming to be "[115.130.26.69]"
2582 via SMTP by localhost, id smtpdAAApLaWrq; Tue Apr 13 23:10:05 2010
2583 Message-ID: <4BC4F9C7.50409@test.test>
2584 Date: Wed, 14 Apr 2010 09:09:59 +1000
2585 From: Rupert Goldie <rgg@test.test>
2586 User-Agent: Thunderbird 2.0.0.24 (Windows/20100228)
2587 MIME-Version: 1.0
2588 To: ekit issues <issues@test.test>
2589 Subject: [Fwd: PHP ERROR (fb)] post limit reached
2590 Content-Type: multipart/mixed; boundary="------------000807090608060304010403"
2592 This is a multi-part message in MIME format.
2593 --------------000807090608060304010403
2594 Content-Type: text/plain; charset=ISO-8859-1; format=flowed
2595 Content-Transfer-Encoding: 7bit
2597 Catch this exception and log it without emailing.
2599 --------------000807090608060304010403
2600 Content-Type: message/rfc822; name="PHP ERROR (fb).eml"
2601 Content-Transfer-Encoding: 7bit
2602 Content-Disposition: inline; filename="PHP ERROR (fb).eml"
2604 Return-Path: <ektravj@test.test>
2605 X-Sieve: CMU Sieve 2.2
2606 via SMTP by crown.off.ekorp.com, id smtpdAAA1JaW1o; Tue Apr 13 23:01:04 2010
2607 X-Virus-Scanned: by amavisd-new at ekit.com
2608 To: facebook-errors@test.test
2609 From: ektravj@test.test
2610 Subject: PHP ERROR (fb)
2611 Message-Id: <20100413230100.D601D27E84@mail2.elax3.ekorp.com>
2612 Date: Tue, 13 Apr 2010 23:01:00 +0000 (UTC)
2614 [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
2615 Stack trace:
2616 #0 /app/01/www/virtual/fb.ekit.com/htdocs/gateway/ekit/feed/index.php(178): fb_exceptions(Object(FacebookRestClientException))
2617 #1 {main}
2618 thrown in /app/01/www/virtual/fb.ekit.com/htdocs/includes/functions.php on line 280
2621 --------------000807090608060304010403--
2622 '''
2623 nodeid = self._handle_mail(message)
2624 assert not os.path.exists(SENDMAILDEBUG)
2625 msgid = self.db.issue.get(nodeid, 'messages')[0]
2626 self.assertEqual(self.db.msg.get(msgid, 'content'),
2627 'Catch this exception and log it without emailing.')
2628 self.assertEqual(self.db.msg.get(msgid, 'files'), ['1'])
2629 fileid = self.db.msg.get(msgid, 'files')[0]
2630 self.assertEqual(self.db.file.get(fileid, 'type'), 'message/rfc822')
2632 def test_suite():
2633 suite = unittest.TestSuite()
2634 suite.addTest(unittest.makeSuite(MailgwTestCase))
2635 return suite
2637 if __name__ == '__main__':
2638 runner = unittest.TextTestRunner()
2639 unittest.main(testRunner=runner)
2641 # vim: set filetype=python sts=4 sw=4 et si :