Code

Yet another fix to the mail gateway, messages got *all* files of
authorschlatterbeck <schlatterbeck@57a73879-2fb5-44c3-a270-3262357dd7e2>
Mon, 6 Jun 2011 20:00:17 +0000 (20:00 +0000)
committerschlatterbeck <schlatterbeck@57a73879-2fb5-44c3-a270-3262357dd7e2>
Mon, 6 Jun 2011 20:00:17 +0000 (20:00 +0000)
an issue, not just the new ones. Thanks to Rafal Bisingier for
reporting and proposing a fix. The regression test was updated.
Fix version numbers in upgrade documentation, the file-unlink defect
was in 1.4.17 not 1.4.16. Thanks to Rafal Bisingier.

git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/roundup/trunk@4617 57a73879-2fb5-44c3-a270-3262357dd7e2

CHANGES.txt
roundup/mailgw.py
test/test_mailgw.py

index b72dc12c473cebb411762bf23121002a8d52b7dc..641dc608946381b151e8996319ec1b69572d27db 100644 (file)
@@ -13,6 +13,11 @@ Fixed:
   (Ralf)
 - Fix version numbers in upgrade documentation, the file-unlink defect
   was in 1.4.17 not 1.4.16. Thanks to Rafal Bisingier. (Ralf)
+- Fix encoded email header parsing if multiple encoded and non-encoded
+  parts are present. RFC2047 specifies that spacing is removed only
+  between encoded parts, we always removed the space. Note that this bug
+  was present before mail gateway refactoring :-) Thanks for thorough
+  testing of mail gateway code by Rafal Bisingier. (Ralf)
 
 2011-05-29 1.4.18 (r4610)
 
index b90c98865ef4bb90a929ebc3869670989ff82480..2da86bb01decaf7754d9938726f63f17b6b89f48 100644 (file)
@@ -247,6 +247,22 @@ class Message(mimetools.Message):
             parts.append(part)
         return parts
 
+    def _decode_header_to_utf8(self, hdr):
+        l = []
+        prev_encoded = False
+        for part, encoding in decode_header(hdr):
+            if encoding:
+                part = part.decode(encoding)
+            # RFC 2047 specifies that between encoded parts spaces are
+            # swallowed while at the borders from encoded to non-encoded
+            # or vice-versa we must preserve a space. Multiple adjacent
+            # non-encoded parts should not occur.
+            if l and prev_encoded != bool(encoding):
+                l.append(' ')
+            prev_encoded = bool(encoding)
+            l.append(part)
+        return ''.join([s.encode('utf-8') for s in l])
+
     def getheader(self, name, default=None):
         hdr = mimetools.Message.getheader(self, name, default)
         # TODO are there any other False values possible?
@@ -257,24 +273,13 @@ class Message(mimetools.Message):
             return ''
         if hdr:
             hdr = hdr.replace('\n','') # Inserted by rfc822.readheaders
-        # historically this method has returned utf-8 encoded string
-        l = []
-        for part, encoding in decode_header(hdr):
-            if encoding:
-                part = part.decode(encoding)
-            l.append(part)
-        return ''.join([s.encode('utf-8') for s in l])
+        return self._decode_header_to_utf8(hdr)
 
     def getaddrlist(self, name):
         # overload to decode the name part of the address
         l = []
         for (name, addr) in mimetools.Message.getaddrlist(self, name):
-            p = []
-            for part, encoding in decode_header(name):
-                if encoding:
-                    part = part.decode(encoding)
-                p.append(part)
-            name = ''.join([s.encode('utf-8') for s in p])
+            name = self._decode_header_to_utf8(name)
             l.append((name, addr))
         return l
 
index fa72040e6ae9658427e607e4b845e7beedffaf50..0cd78d486ac1e41e849dc649a093847239827679 100644 (file)
@@ -1823,6 +1823,35 @@ This is a test submission of a new issue.
         name = self.db.user.get(new, 'realname')
         self.assertEquals(name, 'H€llo')
 
+    def testNewUserAuthorMixedEncodedName(self):
+        l = set(self.db.user.list())
+        # From: name has Euro symbol in it
+        message = '''Content-Type: text/plain;
+  charset="iso-8859-1"
+From: Firstname =?utf-8?b?w6TDtsOf?= Last <fubar@bork.bork.bork>
+To: issue_tracker@your.tracker.email.domain.example
+Message-Id: <dummy_test_message_id>
+Subject: [issue] Test =?utf-8?b?w4TDlsOc?= umlauts
+ X1
+ X2
+
+This is a test submission of a new issue.
+'''
+        p = [
+            self.db.security.getPermission('Register', 'user'),
+            self.db.security.getPermission('Email Access', None),
+            self.db.security.getPermission('Create', 'issue'),
+            self.db.security.getPermission('Create', 'msg'),
+        ]
+        self.db.security.role['anonymous'].permissions = p
+        self._handle_mail(message)
+        title = self.db.issue.get('1', 'title')
+        self.assertEquals(title, 'Test \xc3\x84\xc3\x96\xc3\x9c umlauts X1 X2')
+        m = set(self.db.user.list())
+        new = list(m - l)[0]
+        name = self.db.user.get(new, 'realname')
+        self.assertEquals(name, 'Firstname \xc3\xa4\xc3\xb6\xc3\x9f Last')
+
     def testUnknownUser(self):
         l = set(self.db.user.list())
         message = '''Content-Type: text/plain;