Code

extended date syntax to make range searches even more useful
[roundup.git] / test / test_mailgw.py
index 469b4cfbafb2f34b7ac4742b5f60ec8b437050f2..138059bafc64a083a9285da2ba8c7c9a83b9b69d 100644 (file)
@@ -8,9 +8,10 @@
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 #
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 #
-# $Id: test_mailgw.py,v 1.35 2002-12-10 00:46:55 richard Exp $
+# $Id: test_mailgw.py,v 1.44 2003-04-17 06:51:44 richard Exp $
 
 import unittest, cStringIO, tempfile, os, shutil, errno, imp, sys, difflib
 
 import unittest, cStringIO, tempfile, os, shutil, errno, imp, sys, difflib
+import rfc822
 
 # Note: Should parse emails according to RFC2822 instead of performing a
 # literal string comparision.  Parsing the messages allows the tests to work for
 
 # Note: Should parse emails according to RFC2822 instead of performing a
 # literal string comparision.  Parsing the messages allows the tests to work for
@@ -20,7 +21,7 @@ import unittest, cStringIO, tempfile, os, shutil, errno, imp, sys, difflib
 #except ImportError :
 #    import rfc822 as email
 
 #except ImportError :
 #    import rfc822 as email
 
-from roundup.mailgw import MailGW, Unauthorized
+from roundup.mailgw import MailGW, Unauthorized, uidFromAddress
 from roundup import init, instance
 
 # TODO: make this output only enough equal lines for context, not all of
 from roundup import init, instance
 
 # TODO: make this output only enough equal lines for context, not all of
@@ -31,19 +32,13 @@ class DiffHelper:
            the first to be the "original" but in the calls in this file,
            the second arg is the original. Ho hum.
         '''
            the first to be the "original" but in the calls in this file,
            the second arg is the original. Ho hum.
         '''
-        if s1 == s2:
+        # we have to special-case the Date: header here 'cos we can't test
+        # for it properly
+        l1=s1.strip().split('\n')
+        l2=[x for x in s2.strip().split('\n') if not x.startswith('Date: ')]
+        if l1 == l2:
             return
 
             return
 
-        # under python2.[12] we allow a difference of one trailing empty line.
-        if sys.version_info[0:2] == (2,1):
-            if s1+'\n' == s2:
-                return
-        if sys.version_info[0:2] == (2,2):
-            if s1 == s2+'\n':
-                return
-        
-        l1=s1.split('\n')
-        l2=s2.split('\n')
         s = difflib.SequenceMatcher(None, l1, l2)
         res = ['Generated message not correct (diff follows):']
         for value, s1s, s1e, s2s, s2e in s.get_opcodes():
         s = difflib.SequenceMatcher(None, l1, l2)
         res = ['Generated message not correct (diff follows):']
         for value, s1s, s1e, s2s, s2e in s.get_opcodes():
@@ -74,7 +69,8 @@ class MailgwTestCase(unittest.TestCase, DiffHelper):
         except OSError, error:
             if error.errno not in (errno.ENOENT, errno.ESRCH): raise
         # create the instance
         except OSError, error:
             if error.errno not in (errno.ENOENT, errno.ESRCH): raise
         # create the instance
-        init.install(self.dirname, 'classic', 'anydbm')
+        init.install(self.dirname, 'templates/classic')
+        init.write_select_db(self.dirname, 'anydbm')
         init.initialise(self.dirname, 'sekrit')
         # check we can load the package
         self.instance = instance.open(self.dirname)
         init.initialise(self.dirname, 'sekrit')
         # check we can load the package
         self.instance = instance.open(self.dirname)
@@ -203,7 +199,7 @@ This is a test submission of a new issue.
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, mary@test, richard@test
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, mary@test, richard@test
-Content-Type: text/plain
+Content-Type: text/plain; charset=utf-8
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, mary@test, richard@test
 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, mary@test, richard@test
 From: "Bork, Chef" <issue_tracker@your.tracker.email.domain.example>
@@ -219,7 +215,6 @@ New submission from Bork, Chef <chef@bork.bork.bork>:
 
 This is a test submission of a new issue.
 
 
 This is a test submission of a new issue.
 
-
 ----------
 assignedto: richard
 messages: 1
 ----------
 assignedto: richard
 messages: 1
@@ -228,7 +223,7 @@ status: unread
 title: Testing...
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
 title: Testing...
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
-http://your.tracker.url.example/issue1
+<http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
 _______________________________________________________________________
 ''')
 
 _______________________________________________________________________
 ''')
 
@@ -259,7 +254,7 @@ This is a second followup
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, richard@test
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, richard@test
-Content-Type: text/plain
+Content-Type: text/plain; charset=utf-8
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, richard@test
 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, richard@test
 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
@@ -276,12 +271,11 @@ Contrary, Mary <mary@test> added the comment:
 
 This is a second followup
 
 
 This is a second followup
 
-
 ----------
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
 ----------
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
-http://your.tracker.url.example/issue1
+<http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
 _______________________________________________________________________
 ''')
 
 _______________________________________________________________________
 ''')
 
@@ -308,7 +302,7 @@ This is a followup
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, john@test, mary@test
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, john@test, mary@test
-Content-Type: text/plain
+Content-Type: text/plain; charset=utf-8
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, john@test, mary@test
 From: richard <issue_tracker@your.tracker.email.domain.example>
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, john@test, mary@test
 From: richard <issue_tracker@your.tracker.email.domain.example>
@@ -325,14 +319,13 @@ richard <richard@test> added the comment:
 
 This is a followup
 
 
 This is a followup
 
-
 ----------
 assignedto:  -> mary
 nosy: +john, mary
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
 ----------
 assignedto:  -> mary
 nosy: +john, mary
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
-http://your.tracker.url.example/issue1
+<http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
 _______________________________________________________________________
 ''')
 
 _______________________________________________________________________
 ''')
 
@@ -355,7 +348,7 @@ This is a followup
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, john@test, mary@test
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, john@test, mary@test
-Content-Type: text/plain
+Content-Type: text/plain; charset=utf-8
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, john@test, mary@test
 From: richard <issue_tracker@your.tracker.email.domain.example>
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, john@test, mary@test
 From: richard <issue_tracker@your.tracker.email.domain.example>
@@ -372,14 +365,13 @@ richard <richard@test> added the comment:
 
 This is a followup
 
 
 This is a followup
 
-
 ----------
 assignedto:  -> mary
 nosy: +john, mary
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
 ----------
 assignedto:  -> mary
 nosy: +john, mary
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
-http://your.tracker.url.example/issue1
+<http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
 _______________________________________________________________________
 ''')
 
 _______________________________________________________________________
 ''')
 
@@ -403,7 +395,7 @@ This is a followup
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, richard@test
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, richard@test
-Content-Type: text/plain
+Content-Type: text/plain; charset=utf-8
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, richard@test
 From: John Doe <issue_tracker@your.tracker.email.domain.example>
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, richard@test
 From: John Doe <issue_tracker@your.tracker.email.domain.example>
@@ -420,13 +412,12 @@ John Doe <john@test> added the comment:
 
 This is a followup
 
 
 This is a followup
 
-
 ----------
 nosy: +john
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
 ----------
 nosy: +john
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
-http://your.tracker.url.example/issue1
+<http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
 _______________________________________________________________________
 
 ''')
 _______________________________________________________________________
 
 ''')
@@ -452,7 +443,7 @@ This is a followup
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork
-Content-Type: text/plain
+Content-Type: text/plain; charset=utf-8
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork
 From: richard <issue_tracker@your.tracker.email.domain.example>
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork
 From: richard <issue_tracker@your.tracker.email.domain.example>
@@ -469,13 +460,12 @@ richard <richard@test> added the comment:
 
 This is a followup
 
 
 This is a followup
 
-
 ----------
 nosy: +john
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
 ----------
 nosy: +john
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
-http://your.tracker.url.example/issue1
+<http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
 _______________________________________________________________________
 
 ''')
 _______________________________________________________________________
 
 ''')
@@ -501,7 +491,7 @@ This is a followup
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, john@test, richard@test
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, john@test, richard@test
-Content-Type: text/plain
+Content-Type: text/plain; charset=utf-8
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, john@test, richard@test
 From: John Doe <issue_tracker@your.tracker.email.domain.example>
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, john@test, richard@test
 From: John Doe <issue_tracker@your.tracker.email.domain.example>
@@ -518,13 +508,12 @@ John Doe <john@test> added the comment:
 
 This is a followup
 
 
 This is a followup
 
-
 ----------
 nosy: +john
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
 ----------
 nosy: +john
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
-http://your.tracker.url.example/issue1
+<http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
 _______________________________________________________________________
 
 ''')
 _______________________________________________________________________
 
 ''')
@@ -549,7 +538,7 @@ This is a followup
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, richard@test
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, richard@test
-Content-Type: text/plain
+Content-Type: text/plain; charset=utf-8
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, richard@test
 From: John Doe <issue_tracker@your.tracker.email.domain.example>
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, richard@test
 From: John Doe <issue_tracker@your.tracker.email.domain.example>
@@ -566,12 +555,11 @@ John Doe <john@test> added the comment:
 
 This is a followup
 
 
 This is a followup
 
-
 ----------
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
 ----------
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
-http://your.tracker.url.example/issue1
+<http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
 _______________________________________________________________________
 
 ''')
 _______________________________________________________________________
 
 ''')
@@ -597,7 +585,7 @@ This is a followup
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork
-Content-Type: text/plain
+Content-Type: text/plain; charset=utf-8
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork
 From: richard <issue_tracker@your.tracker.email.domain.example>
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork
 From: richard <issue_tracker@your.tracker.email.domain.example>
@@ -614,16 +602,37 @@ richard <richard@test> added the comment:
 
 This is a followup
 
 
 This is a followup
 
-
 ----------
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
 ----------
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
-http://your.tracker.url.example/issue1
+<http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
 _______________________________________________________________________
 
 ''')
 
 _______________________________________________________________________
 
 ''')
 
+    def testFollowupEmptyMessage(self):
+        self.doNewIssue()
+
+        message = cStringIO.StringIO('''Content-Type: text/plain;
+  charset="iso-8859-1"
+From: richard <richard@test>
+To: issue_tracker@your.tracker.email.domain.example
+Message-Id: <followup_dummy_id>
+In-Reply-To: <dummy_test_message_id>
+Subject: [issue1] Testing... [assignedto=mary; nosy=+john]
+
+''')
+        handler = self.instance.MailGW(self.instance, self.db)
+        handler.trapExceptions = 0
+        handler.main(message)
+        l = self.db.issue.get('1', 'nosy')
+        l.sort()
+        self.assertEqual(l, ['3', '4', '5', '6'])
+
+        # should be no file created (ie. no message)
+        assert not os.path.exists(os.environ['SENDMAILDEBUG'])
+
     def testNosyRemove(self):
         self.doNewIssue()
 
     def testNosyRemove(self):
         self.doNewIssue()
 
@@ -649,7 +658,7 @@ Subject: [issue1] Testing... [nosy=-richard]
     def testNewUserAuthor(self):
         # first without the permission
         # heh... just ignore the API for a second ;)
     def testNewUserAuthor(self):
         # first without the permission
         # heh... just ignore the API for a second ;)
-        self.db.security.role['Anonymous'].permissions=[]
+        self.db.security.role['anonymous'].permissions=[]
         anonid = self.db.user.lookup('anonymous')
         self.db.user.set(anonid, roles='Anonymous')
 
         anonid = self.db.user.lookup('anonymous')
         self.db.user.set(anonid, roles='Anonymous')
 
@@ -675,7 +684,7 @@ This is a test submission of a new issue.
 
         # now with the permission
         p = self.db.security.getPermission('Email Registration')
 
         # now with the permission
         p = self.db.security.getPermission('Email Registration')
-        self.db.security.role['Anonymous'].permissions=[p]
+        self.db.security.role['anonymous'].permissions=[p]
         handler = self.instance.MailGW(self.instance, self.db)
         handler.trapExceptions = 0
         message = cStringIO.StringIO(s)
         handler = self.instance.MailGW(self.instance, self.db)
         handler.trapExceptions = 0
         message = cStringIO.StringIO(s)
@@ -706,7 +715,7 @@ A message with encoding (encoded oe =F6)
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, richard@test
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, richard@test
-Content-Type: text/plain
+Content-Type: text/plain; charset=utf-8
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, richard@test
 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, richard@test
 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
@@ -721,13 +730,13 @@ Content-Transfer-Encoding: quoted-printable
 
 Contrary, Mary <mary@test> added the comment:
 
 
 Contrary, Mary <mary@test> added the comment:
 
-A message with encoding (encoded oe =F6)
+A message with encoding (encoded oe =C3=B6)
 
 ----------
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
 
 ----------
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
-http://your.tracker.url.example/issue1
+<http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
 _______________________________________________________________________
 ''')
 
 _______________________________________________________________________
 ''')
 
@@ -761,7 +770,7 @@ A message with first part encoded (encoded oe =F6)
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, richard@test
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork, richard@test
-Content-Type: text/plain
+Content-Type: text/plain; charset=utf-8
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, richard@test
 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork, richard@test
 From: "Contrary, Mary" <issue_tracker@your.tracker.email.domain.example>
@@ -776,16 +785,51 @@ Content-Transfer-Encoding: quoted-printable
 
 Contrary, Mary <mary@test> added the comment:
 
 
 Contrary, Mary <mary@test> added the comment:
 
-A message with first part encoded (encoded oe =F6)
+A message with first part encoded (encoded oe =C3=B6)
 
 ----------
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
 
 ----------
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
-http://your.tracker.url.example/issue1
+<http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
 _______________________________________________________________________
 ''')
 
 _______________________________________________________________________
 ''')
 
+    def testContentDisposition(self):
+        self.doNewIssue()
+        message = cStringIO.StringIO('''Content-Type: text/plain;
+  charset="iso-8859-1"
+From: mary <mary@test>
+To: issue_tracker@your.tracker.email.domain.example
+Message-Id: <followup_dummy_id>
+In-Reply-To: <dummy_test_message_id>
+Subject: [issue1] Testing...
+Content-Type: multipart/mixed; boundary="bCsyhTFzCvuiizWE" 
+Content-Disposition: inline 
+--bCsyhTFzCvuiizWE 
+Content-Type: text/plain; charset=us-ascii 
+Content-Disposition: inline 
+
+test attachment binary 
+
+--bCsyhTFzCvuiizWE 
+Content-Type: application/octet-stream 
+Content-Disposition: attachment; filename="main.dvi" 
+
+xxxxxx 
+
+--bCsyhTFzCvuiizWE--
+''')
+        handler = self.instance.MailGW(self.instance, self.db)
+        handler.trapExceptions = 0
+        handler.main(message)
+        messages = self.db.issue.get('1', 'messages')
+        messages.sort()
+        file = self.db.msg.get(messages[-1], 'files')[0]
+        self.assertEqual(self.db.file.get(file, 'name'), 'main.dvi')
+
     def testFollowupStupidQuoting(self):
         self.doNewIssue()
 
     def testFollowupStupidQuoting(self):
         self.doNewIssue()
 
@@ -806,7 +850,7 @@ This is a followup
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork
         self.compareStrings(open(os.environ['SENDMAILDEBUG']).read(),
 '''FROM: roundup-admin@your.tracker.email.domain.example
 TO: chef@bork.bork.bork
-Content-Type: text/plain
+Content-Type: text/plain; charset=utf-8
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork
 From: richard <issue_tracker@your.tracker.email.domain.example>
 Subject: [issue1] Testing...
 To: chef@bork.bork.bork
 From: richard <issue_tracker@your.tracker.email.domain.example>
@@ -823,12 +867,11 @@ richard <richard@test> added the comment:
 
 This is a followup
 
 
 This is a followup
 
-
 ----------
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
 ----------
 status: unread -> chatting
 _______________________________________________________________________
 Roundup issue tracker <issue_tracker@your.tracker.email.domain.example>
-http://your.tracker.url.example/issue1
+<http://tracker.example/cgi-bin/roundup.cgi/bugs/issue1>
 _______________________________________________________________________
 ''')
 
 _______________________________________________________________________
 ''')
 
@@ -879,6 +922,18 @@ This is a followup
 
         self.compareStrings(self.db.msg.get(messageid, 'content'), expect)
 
 
         self.compareStrings(self.db.msg.get(messageid, 'content'), expect)
 
+    def testUserLookup(self):
+        i = self.db.user.create(username='user1', address='user1@foo.com')
+        self.assertEqual(uidFromAddress(self.db, ('', 'user1@foo.com'), 0), i)
+        self.assertEqual(uidFromAddress(self.db, ('', 'USER1@foo.com'), 0), i)
+        i = self.db.user.create(username='user2', address='USER2@foo.com')
+        self.assertEqual(uidFromAddress(self.db, ('', 'USER2@foo.com'), 0), i)
+        self.assertEqual(uidFromAddress(self.db, ('', 'user2@foo.com'), 0), i)
+
+    def testUserCreate(self):
+        i = uidFromAddress(self.db, ('', 'user@foo.com'), 1)
+        self.assertNotEqual(uidFromAddress(self.db, ('', 'user@bar.com'), 1), i)
+
 def suite():
     l = [unittest.makeSuite(MailgwTestCase),
     ]
 def suite():
     l = [unittest.makeSuite(MailgwTestCase),
     ]