1 #
2 # Copyright (c) 2001 Richard Jones, richard@bofh.asn.au.
3 # This module is free software, and you may redistribute it and/or modify
4 # under the same terms as Python, so long as this copyright message and
5 # disclaimer are retained in their original form.
6 #
7 # This module is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 #
11 # $Id: test_mailgw.py,v 1.17 2002-05-02 07:56:34 richard Exp $
13 import unittest, cStringIO, tempfile, os, shutil, errno, imp, sys, difflib
15 from roundup.mailgw import MailGW
16 from roundup import init, instance
18 # TODO: make this output only enough equal lines for context, not all of
19 # them
20 class DiffHelper:
21 def compareStrings(self, s2, s1):
22 '''Note the reversal of s2 and s1 - difflib.SequenceMatcher wants
23 the first to be the "original" but in the calls in this file,
24 the second arg is the original. Ho hum.
25 '''
26 if s1 == s2:
27 return
28 # under python2.1 we allow a difference of one trailing empty line.
29 if sys.version_info[0:2] == (2,1):
30 if s1+'\n' == s2:
31 return
33 l1=s1.split('\n')
34 l2=s2.split('\n')
35 s = difflib.SequenceMatcher(None, l1, l2)
36 res = ['Generated message not correct (diff follows):']
37 for value, s1s, s1e, s2s, s2e in s.get_opcodes():
38 if value == 'equal':
39 for i in range(s1s, s1e):
40 res.append(' %s'%l1[i])
41 elif value == 'delete':
42 for i in range(s1s, s1e):
43 res.append('- %s'%l1[i])
44 elif value == 'insert':
45 for i in range(s2s, s2e):
46 res.append('+ %s'%l2[i])
47 elif value == 'replace':
48 for i, j in zip(range(s1s, s1e), range(s2s, s2e)):
49 res.append('- %s'%l1[i])
50 res.append('+ %s'%l2[j])
52 raise AssertionError, '\n'.join(res)
54 class MailgwTestCase(unittest.TestCase, DiffHelper):
55 count = 0
56 schema = 'classic'
57 def setUp(self):
58 MailgwTestCase.count = MailgwTestCase.count + 1
59 self.dirname = '_test_%s'%self.count
60 try:
61 shutil.rmtree(self.dirname)
62 except OSError, error:
63 if error.errno not in (errno.ENOENT, errno.ESRCH): raise
64 # create the instance
65 init.init(self.dirname, self.schema, 'anydbm', 'sekrit')
66 # check we can load the package
67 self.instance = instance.open(self.dirname)
68 # and open the database
69 self.db = self.instance.open('sekrit')
70 self.db.user.create(username='Chef', address='chef@bork.bork.bork')
71 self.db.user.create(username='richard', address='richard@test')
72 self.db.user.create(username='mary', address='mary@test')
73 self.db.user.create(username='john', address='john@test',
74 alternate_addresses='jondoe@test\njohn.doe@test')
76 def tearDown(self):
77 if os.path.exists(os.environ['SENDMAILDEBUG']):
78 os.remove(os.environ['SENDMAILDEBUG'])
79 try:
80 shutil.rmtree(self.dirname)
81 except OSError, error:
82 if error.errno not in (errno.ENOENT, errno.ESRCH): raise
84 def testNewIssue(self):
85 message = cStringIO.StringIO('''Content-Type: text/plain;
86 charset="iso-8859-1"
87 From: Chef <chef@bork.bork.bork
88 To: issue_tracker@fill.me.in.
89 Cc: richard@test
90 Message-Id: <dummy_test_message_id>
91 Subject: [issue] Testing...
93 This is a test submission of a new issue.
94 ''')
95 handler = self.instance.MailGW(self.instance, self.db)
96 nodeid = handler.main(message)
97 if os.path.exists(os.environ['SENDMAILDEBUG']):
98 error = open(os.environ['SENDMAILDEBUG']).read()
99 self.assertEqual('no error', error)
100 self.assertEqual(self.db.issue.get(nodeid, 'nosy'), ['2', '3'])
102 def testNewIssueNosy(self):
103 self.instance.ADD_AUTHOR_TO_NOSY = 'yes'
104 message = cStringIO.StringIO('''Content-Type: text/plain;
105 charset="iso-8859-1"
106 From: Chef <chef@bork.bork.bork
107 To: issue_tracker@fill.me.in.
108 Cc: richard@test
109 Message-Id: <dummy_test_message_id>
110 Subject: [issue] Testing...
112 This is a test submission of a new issue.
113 ''')
114 handler = self.instance.MailGW(self.instance, self.db)
115 nodeid = handler.main(message)
116 if os.path.exists(os.environ['SENDMAILDEBUG']):
117 error = open(os.environ['SENDMAILDEBUG']).read()
118 self.assertEqual('no error', error)
119 self.assertEqual(self.db.issue.get(nodeid, 'nosy'), ['2', '3'])
121 def testAlternateAddress(self):
122 message = cStringIO.StringIO('''Content-Type: text/plain;
123 charset="iso-8859-1"
124 From: John Doe <john.doe@test>
125 To: issue_tracker@fill.me.in.
126 Message-Id: <dummy_test_message_id>
127 Subject: [issue] Testing...
129 This is a test submission of a new issue.
130 ''')
131 userlist = self.db.user.list()
132 handler = self.instance.MailGW(self.instance, self.db)
133 handler.main(message)
134 if os.path.exists(os.environ['SENDMAILDEBUG']):
135 error = open(os.environ['SENDMAILDEBUG']).read()
136 self.assertEqual('no error', error)
137 self.assertEqual(userlist, self.db.user.list(),
138 "user created when it shouldn't have been")
140 def testNewIssueNoClass(self):
141 message = cStringIO.StringIO('''Content-Type: text/plain;
142 charset="iso-8859-1"
143 From: Chef <chef@bork.bork.bork
144 To: issue_tracker@fill.me.in.
145 Cc: richard@test
146 Message-Id: <dummy_test_message_id>
147 Subject: Testing...
149 This is a test submission of a new issue.
150 ''')
151 handler = self.instance.MailGW(self.instance, self.db)
152 handler.main(message)
153 if os.path.exists(os.environ['SENDMAILDEBUG']):
154 error = open(os.environ['SENDMAILDEBUG']).read()
155 self.assertEqual('no error', error)
157 def testNewIssueAuthMsg(self):
158 message = cStringIO.StringIO('''Content-Type: text/plain;
159 charset="iso-8859-1"
160 From: Chef <chef@bork.bork.bork
161 To: issue_tracker@fill.me.in.
162 Message-Id: <dummy_test_message_id>
163 Subject: [issue] Testing... [nosy=mary; assignedto=richard]
165 This is a test submission of a new issue.
166 ''')
167 handler = self.instance.MailGW(self.instance, self.db)
168 # TODO: fix the damn config - this is apalling
169 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
170 handler.main(message)
172 self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
173 '''FROM: roundup-admin@fill.me.in.
174 TO: chef@bork.bork.bork, mary@test, richard@test
175 Content-Type: text/plain
176 Subject: [issue1] Testing...
177 To: chef@bork.bork.bork, mary@test, richard@test
178 From: Chef <issue_tracker@fill.me.in.>
179 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
180 MIME-Version: 1.0
181 Message-Id: <dummy_test_message_id>
182 X-Roundup-Name: Roundup issue tracker
183 Content-Transfer-Encoding: quoted-printable
186 New submission from Chef <chef@bork.bork.bork>:
188 This is a test submission of a new issue.
191 ----------
192 assignedto: richard
193 messages: 1
194 nosy: mary, Chef, richard
195 status: unread
196 title: Testing...
197 ___________________________________________________
198 "Roundup issue tracker" <issue_tracker@fill.me.in.>
199 http://some.useful.url/issue1
200 ___________________________________________________
201 ''')
203 # BUG
204 # def testMultipart(self):
205 # '''With more than one part'''
206 # see MultipartEnc tests: but if there is more than one part
207 # we return a multipart/mixed and the boundary contains
208 # the ip address of the test machine.
210 # BUG should test some binary attamchent too.
212 def testFollowup(self):
213 self.testNewIssue()
214 message = cStringIO.StringIO('''Content-Type: text/plain;
215 charset="iso-8859-1"
216 From: richard <richard@test>
217 To: issue_tracker@fill.me.in.
218 Message-Id: <followup_dummy_id>
219 In-Reply-To: <dummy_test_message_id>
220 Subject: [issue1] Testing... [assignedto=mary; nosy=john]
222 This is a followup
223 ''')
224 handler = self.instance.MailGW(self.instance, self.db)
225 handler.main(message)
227 self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
228 '''FROM: roundup-admin@fill.me.in.
229 TO: chef@bork.bork.bork, mary@test, john@test
230 Content-Type: text/plain
231 Subject: [issue1] Testing...
232 To: chef@bork.bork.bork, mary@test, john@test
233 From: richard <issue_tracker@fill.me.in.>
234 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
235 MIME-Version: 1.0
236 Message-Id: <followup_dummy_id>
237 In-Reply-To: <dummy_test_message_id>
238 X-Roundup-Name: Roundup issue tracker
239 Content-Transfer-Encoding: quoted-printable
242 richard <richard@test> added the comment:
244 This is a followup
247 ----------
248 assignedto: -> mary
249 nosy: +mary, john
250 status: unread -> chatting
251 ___________________________________________________
252 "Roundup issue tracker" <issue_tracker@fill.me.in.>
253 http://some.useful.url/issue1
254 ___________________________________________________
255 ''')
257 def testFollowup2(self):
258 self.testNewIssue()
259 message = cStringIO.StringIO('''Content-Type: text/plain;
260 charset="iso-8859-1"
261 From: mary <mary@test>
262 To: issue_tracker@fill.me.in.
263 Message-Id: <followup_dummy_id>
264 In-Reply-To: <dummy_test_message_id>
265 Subject: [issue1] Testing...
267 This is a second followup
268 ''')
269 handler = self.instance.MailGW(self.instance, self.db)
270 handler.main(message)
271 self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
272 '''FROM: roundup-admin@fill.me.in.
273 TO: chef@bork.bork.bork, richard@test
274 Content-Type: text/plain
275 Subject: [issue1] Testing...
276 To: chef@bork.bork.bork, richard@test
277 From: mary <issue_tracker@fill.me.in.>
278 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
279 MIME-Version: 1.0
280 Message-Id: <followup_dummy_id>
281 In-Reply-To: <dummy_test_message_id>
282 X-Roundup-Name: Roundup issue tracker
283 Content-Transfer-Encoding: quoted-printable
286 mary <mary@test> added the comment:
288 This is a second followup
291 ----------
292 status: unread -> chatting
293 ___________________________________________________
294 "Roundup issue tracker" <issue_tracker@fill.me.in.>
295 http://some.useful.url/issue1
296 ___________________________________________________
297 ''')
299 def testFollowupTitleMatch(self):
300 self.testNewIssue()
301 message = cStringIO.StringIO('''Content-Type: text/plain;
302 charset="iso-8859-1"
303 From: richard <richard@test>
304 To: issue_tracker@fill.me.in.
305 Message-Id: <followup_dummy_id>
306 In-Reply-To: <dummy_test_message_id>
307 Subject: Re: Testing... [assignedto=mary; nosy=john]
309 This is a followup
310 ''')
311 handler = self.instance.MailGW(self.instance, self.db)
312 handler.main(message)
314 self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
315 '''FROM: roundup-admin@fill.me.in.
316 TO: chef@bork.bork.bork, mary@test, john@test
317 Content-Type: text/plain
318 Subject: [issue1] Testing...
319 To: chef@bork.bork.bork, mary@test, john@test
320 From: richard <issue_tracker@fill.me.in.>
321 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
322 MIME-Version: 1.0
323 Message-Id: <followup_dummy_id>
324 In-Reply-To: <dummy_test_message_id>
325 X-Roundup-Name: Roundup issue tracker
326 Content-Transfer-Encoding: quoted-printable
329 richard <richard@test> added the comment:
331 This is a followup
334 ----------
335 assignedto: -> mary
336 nosy: +mary, john
337 status: unread -> chatting
338 ___________________________________________________
339 "Roundup issue tracker" <issue_tracker@fill.me.in.>
340 http://some.useful.url/issue1
341 ___________________________________________________
342 ''')
344 def testFollowupNosyAuthor(self):
345 self.testNewIssue()
346 self.instance.ADD_AUTHOR_TO_NOSY = 'yes'
347 message = cStringIO.StringIO('''Content-Type: text/plain;
348 charset="iso-8859-1"
349 From: john@test
350 To: issue_tracker@fill.me.in.
351 Message-Id: <followup_dummy_id>
352 In-Reply-To: <dummy_test_message_id>
353 Subject: [issue1] Testing...
355 This is a followup
356 ''')
357 handler = self.instance.MailGW(self.instance, self.db)
358 handler.main(message)
360 self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
361 '''FROM: roundup-admin@fill.me.in.
362 TO: chef@bork.bork.bork, richard@test
363 Content-Type: text/plain
364 Subject: [issue1] Testing...
365 To: chef@bork.bork.bork, richard@test
366 From: john <issue_tracker@fill.me.in.>
367 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
368 MIME-Version: 1.0
369 Message-Id: <followup_dummy_id>
370 In-Reply-To: <dummy_test_message_id>
371 X-Roundup-Name: Roundup issue tracker
372 Content-Transfer-Encoding: quoted-printable
375 john <john@test> added the comment:
377 This is a followup
380 ----------
381 nosy: +john
382 status: unread -> chatting
383 ___________________________________________________
384 "Roundup issue tracker" <issue_tracker@fill.me.in.>
385 http://some.useful.url/issue1
386 ___________________________________________________
388 ''')
390 def testFollowupNosyRecipients(self):
391 self.testNewIssue()
392 self.instance.ADD_RECIPIENTS_TO_NOSY = 'yes'
393 message = cStringIO.StringIO('''Content-Type: text/plain;
394 charset="iso-8859-1"
395 From: richard@test
396 To: issue_tracker@fill.me.in.
397 Cc: john@test
398 Message-Id: <followup_dummy_id>
399 In-Reply-To: <dummy_test_message_id>
400 Subject: [issue1] Testing...
402 This is a followup
403 ''')
404 handler = self.instance.MailGW(self.instance, self.db)
405 handler.main(message)
407 self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
408 '''FROM: roundup-admin@fill.me.in.
409 TO: chef@bork.bork.bork
410 Content-Type: text/plain
411 Subject: [issue1] Testing...
412 To: chef@bork.bork.bork
413 From: richard <issue_tracker@fill.me.in.>
414 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
415 MIME-Version: 1.0
416 Message-Id: <followup_dummy_id>
417 In-Reply-To: <dummy_test_message_id>
418 X-Roundup-Name: Roundup issue tracker
419 Content-Transfer-Encoding: quoted-printable
422 richard <richard@test> added the comment:
424 This is a followup
427 ----------
428 nosy: +john
429 status: unread -> chatting
430 ___________________________________________________
431 "Roundup issue tracker" <issue_tracker@fill.me.in.>
432 http://some.useful.url/issue1
433 ___________________________________________________
435 ''')
437 def testFollowupNosyAuthorAndCopy(self):
438 self.testNewIssue()
439 self.instance.ADD_AUTHOR_TO_NOSY = 'yes'
440 self.db.config.MESSAGES_TO_AUTHOR = 'yes'
441 message = cStringIO.StringIO('''Content-Type: text/plain;
442 charset="iso-8859-1"
443 From: john@test
444 To: issue_tracker@fill.me.in.
445 Message-Id: <followup_dummy_id>
446 In-Reply-To: <dummy_test_message_id>
447 Subject: [issue1] Testing...
449 This is a followup
450 ''')
451 handler = self.instance.MailGW(self.instance, self.db)
452 handler.main(message)
454 self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
455 '''FROM: roundup-admin@fill.me.in.
456 TO: john@test, chef@bork.bork.bork, richard@test
457 Content-Type: text/plain
458 Subject: [issue1] Testing...
459 To: john@test, chef@bork.bork.bork, richard@test
460 From: john <issue_tracker@fill.me.in.>
461 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
462 MIME-Version: 1.0
463 Message-Id: <followup_dummy_id>
464 In-Reply-To: <dummy_test_message_id>
465 X-Roundup-Name: Roundup issue tracker
466 Content-Transfer-Encoding: quoted-printable
469 john <john@test> added the comment:
471 This is a followup
474 ----------
475 nosy: +john
476 status: unread -> chatting
477 ___________________________________________________
478 "Roundup issue tracker" <issue_tracker@fill.me.in.>
479 http://some.useful.url/issue1
480 ___________________________________________________
482 ''')
484 def testFollowupNoNosyAuthor(self):
485 self.testNewIssue()
486 self.instance.ADD_AUTHOR_TO_NOSY = 'no'
487 message = cStringIO.StringIO('''Content-Type: text/plain;
488 charset="iso-8859-1"
489 From: john@test
490 To: issue_tracker@fill.me.in.
491 Message-Id: <followup_dummy_id>
492 In-Reply-To: <dummy_test_message_id>
493 Subject: [issue1] Testing...
495 This is a followup
496 ''')
497 handler = self.instance.MailGW(self.instance, self.db)
498 handler.main(message)
500 self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
501 '''FROM: roundup-admin@fill.me.in.
502 TO: chef@bork.bork.bork, richard@test
503 Content-Type: text/plain
504 Subject: [issue1] Testing...
505 To: chef@bork.bork.bork, richard@test
506 From: john <issue_tracker@fill.me.in.>
507 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
508 MIME-Version: 1.0
509 Message-Id: <followup_dummy_id>
510 In-Reply-To: <dummy_test_message_id>
511 X-Roundup-Name: Roundup issue tracker
512 Content-Transfer-Encoding: quoted-printable
515 john <john@test> added the comment:
517 This is a followup
520 ----------
521 status: unread -> chatting
522 ___________________________________________________
523 "Roundup issue tracker" <issue_tracker@fill.me.in.>
524 http://some.useful.url/issue1
525 ___________________________________________________
527 ''')
529 def testFollowupNoNosyRecipients(self):
530 self.testNewIssue()
531 self.instance.ADD_RECIPIENTS_TO_NOSY = 'no'
532 message = cStringIO.StringIO('''Content-Type: text/plain;
533 charset="iso-8859-1"
534 From: richard@test
535 To: issue_tracker@fill.me.in.
536 Cc: john@test
537 Message-Id: <followup_dummy_id>
538 In-Reply-To: <dummy_test_message_id>
539 Subject: [issue1] Testing...
541 This is a followup
542 ''')
543 handler = self.instance.MailGW(self.instance, self.db)
544 handler.main(message)
546 self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
547 '''FROM: roundup-admin@fill.me.in.
548 TO: chef@bork.bork.bork
549 Content-Type: text/plain
550 Subject: [issue1] Testing...
551 To: chef@bork.bork.bork
552 From: richard <issue_tracker@fill.me.in.>
553 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
554 MIME-Version: 1.0
555 Message-Id: <followup_dummy_id>
556 In-Reply-To: <dummy_test_message_id>
557 X-Roundup-Name: Roundup issue tracker
558 Content-Transfer-Encoding: quoted-printable
561 richard <richard@test> added the comment:
563 This is a followup
566 ----------
567 status: unread -> chatting
568 ___________________________________________________
569 "Roundup issue tracker" <issue_tracker@fill.me.in.>
570 http://some.useful.url/issue1
571 ___________________________________________________
573 ''')
575 def testEnc01(self):
576 self.testNewIssue()
577 message = cStringIO.StringIO('''Content-Type: text/plain;
578 charset="iso-8859-1"
579 From: mary <mary@test>
580 To: issue_tracker@fill.me.in.
581 Message-Id: <followup_dummy_id>
582 In-Reply-To: <dummy_test_message_id>
583 Subject: [issue1] Testing...
584 Content-Type: text/plain;
585 charset="iso-8859-1"
586 Content-Transfer-Encoding: quoted-printable
588 A message with encoding (encoded oe =F6)
590 ''')
591 handler = self.instance.MailGW(self.instance, self.db)
592 handler.main(message)
593 self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
594 '''FROM: roundup-admin@fill.me.in.
595 TO: chef@bork.bork.bork, richard@test
596 Content-Type: text/plain
597 Subject: [issue1] Testing...
598 To: chef@bork.bork.bork, richard@test
599 From: mary <issue_tracker@fill.me.in.>
600 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
601 MIME-Version: 1.0
602 Message-Id: <followup_dummy_id>
603 In-Reply-To: <dummy_test_message_id>
604 X-Roundup-Name: Roundup issue tracker
605 Content-Transfer-Encoding: quoted-printable
608 mary <mary@test> added the comment:
610 A message with encoding (encoded oe =F6)
612 ----------
613 status: unread -> chatting
614 ___________________________________________________
615 "Roundup issue tracker" <issue_tracker@fill.me.in.>
616 http://some.useful.url/issue1
617 ___________________________________________________
618 ''')
621 def testMultipartEnc01(self):
622 self.testNewIssue()
623 message = cStringIO.StringIO('''Content-Type: text/plain;
624 charset="iso-8859-1"
625 From: mary <mary@test>
626 To: issue_tracker@fill.me.in.
627 Message-Id: <followup_dummy_id>
628 In-Reply-To: <dummy_test_message_id>
629 Subject: [issue1] Testing...
630 Content-Type: multipart/mixed;
631 boundary="----_=_NextPart_000_01"
633 This message is in MIME format. Since your mail reader does not understand
634 this format, some or all of this message may not be legible.
636 ------_=_NextPart_000_01
637 Content-Type: text/plain;
638 charset="iso-8859-1"
639 Content-Transfer-Encoding: quoted-printable
641 A message with first part encoded (encoded oe =F6)
643 ''')
644 handler = self.instance.MailGW(self.instance, self.db)
645 handler.main(message)
646 self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
647 '''FROM: roundup-admin@fill.me.in.
648 TO: chef@bork.bork.bork, richard@test
649 Content-Type: text/plain
650 Subject: [issue1] Testing...
651 To: chef@bork.bork.bork, richard@test
652 From: mary <issue_tracker@fill.me.in.>
653 Reply-To: Roundup issue tracker <issue_tracker@fill.me.in.>
654 MIME-Version: 1.0
655 Message-Id: <followup_dummy_id>
656 In-Reply-To: <dummy_test_message_id>
657 X-Roundup-Name: Roundup issue tracker
658 Content-Transfer-Encoding: quoted-printable
661 mary <mary@test> added the comment:
663 A message with first part encoded (encoded oe =F6)
665 ----------
666 status: unread -> chatting
667 ___________________________________________________
668 "Roundup issue tracker" <issue_tracker@fill.me.in.>
669 http://some.useful.url/issue1
670 ___________________________________________________
671 ''')
673 class ExtMailgwTestCase(MailgwTestCase):
674 schema = 'extended'
676 def suite():
677 l = [unittest.makeSuite(MailgwTestCase),
678 unittest.makeSuite(ExtMailgwTestCase, 'test')
679 ]
680 return unittest.TestSuite(l)
683 #
684 # $Log: not supported by cvs2svn $
685 # Revision 1.16 2002/03/19 21:58:11 grubert
686 # . for python2.1 test_mailgw compareString allows an extra trailing empty line (for quopri.
687 #
688 # Revision 1.15 2002/03/19 06:37:00 richard
689 # Made the email checking spit out a diff - much easier to spot the problem!
690 #
691 # Revision 1.14 2002/03/18 18:32:00 rochecompaan
692 # All messages sent to the nosy list are now encoded as quoted-printable.
693 #
694 # Revision 1.13 2002/02/15 07:08:45 richard
695 # . Alternate email addresses are now available for users. See the MIGRATION
696 # file for info on how to activate the feature.
697 #
698 # Revision 1.12 2002/02/15 00:13:38 richard
699 # . #503204 ] mailgw needs a default class
700 # - partially done - the setting of additional properties can wait for a
701 # better configuration system.
702 #
703 # Revision 1.11 2002/02/14 23:38:12 richard
704 # Fixed the unit tests for the mailgw re: the x-roundup-name header.
705 # Also made the test runner more user-friendly:
706 # ./run_tests - detect all tests in test/test_<name>.py and run them
707 # ./run_tests <name> - run only test/test_<name>.py
708 # eg ./run_tests mailgw - run the mailgw test from test/test_mailgw.py
709 #
710 # Revision 1.10 2002/02/12 08:08:55 grubert
711 # . Clean up mail handling, multipart handling.
712 #
713 # Revision 1.9 2002/02/05 14:15:29 grubert
714 # . respect encodings in non multipart messages.
715 #
716 # Revision 1.8 2002/02/04 09:40:21 grubert
717 # . add test for multipart messages with first part being encoded.
718 #
719 # Revision 1.7 2002/01/22 11:54:45 rochecompaan
720 # Fixed status change in mail gateway.
721 #
722 # Revision 1.6 2002/01/21 10:05:48 rochecompaan
723 # Feature:
724 # . the mail gateway now responds with an error message when invalid
725 # values for arguments are specified for link or multilink properties
726 # . modified unit test to check nosy and assignedto when specified as
727 # arguments
728 #
729 # Fixed:
730 # . fixed setting nosy as argument in subject line
731 #
732 # Revision 1.5 2002/01/15 00:12:40 richard
733 # #503340 ] creating issue with [asignedto=p.ohly]
734 #
735 # Revision 1.4 2002/01/14 07:12:15 richard
736 # removed file writing from tests...
737 #
738 # Revision 1.3 2002/01/14 02:20:15 richard
739 # . changed all config accesses so they access either the instance or the
740 # config attriubute on the db. This means that all config is obtained from
741 # instance_config instead of the mish-mash of classes. This will make
742 # switching to a ConfigParser setup easier too, I hope.
743 #
744 # At a minimum, this makes migration a _little_ easier (a lot easier in the
745 # 0.5.0 switch, I hope!)
746 #
747 # Revision 1.2 2002/01/11 23:22:29 richard
748 # . #502437 ] rogue reactor and unittest
749 # in short, the nosy reactor was modifying the nosy list. That code had
750 # been there for a long time, and I suspsect it was there because we
751 # weren't generating the nosy list correctly in other places of the code.
752 # We're now doing that, so the nosy-modifying code can go away from the
753 # nosy reactor.
754 #
755 # Revision 1.1 2002/01/02 02:31:38 richard
756 # Sorry for the huge checkin message - I was only intending to implement #496356
757 # but I found a number of places where things had been broken by transactions:
758 # . modified ROUNDUPDBSENDMAILDEBUG to be SENDMAILDEBUG and hold a filename
759 # for _all_ roundup-generated smtp messages to be sent to.
760 # . the transaction cache had broken the roundupdb.Class set() reactors
761 # . newly-created author users in the mailgw weren't being committed to the db
762 #
763 # Stuff that made it into CHANGES.txt (ie. the stuff I was actually working
764 # on when I found that stuff :):
765 # . #496356 ] Use threading in messages
766 # . detectors were being registered multiple times
767 # . added tests for mailgw
768 # . much better attaching of erroneous messages in the mail gateway
769 #
770 #
771 #
772 #
773 # vim: set filetype=python ts=4 sw=4 et si