Code

Attempt to generate more human-readable addresses in email
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Mon, 1 Feb 2010 03:59:02 +0000 (03:59 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Mon, 1 Feb 2010 03:59:02 +0000 (03:59 +0000)
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/roundup/trunk@4442 57a73879-2fb5-44c3-a270-3262357dd7e2

CHANGES.txt
roundup/mailer.py
roundup/roundupdb.py
test/test_mailer.py [new file with mode: 0644]

index 2262b94fe172730542c3d47e91835fba314fd731..e311524ab9914681496739b5d2e014c01edb560d 100644 (file)
@@ -25,6 +25,8 @@ Fixes:
 - Display 'today' in the account user's timezone, thanks David Wolever
 - Fix file handle leak in some web interfaces with logging turned on,
   fixes issue1675845
 - Display 'today' in the account user's timezone, thanks David Wolever
 - Fix file handle leak in some web interfaces with logging turned on,
   fixes issue1675845
+- Attempt to generate more human-readable addresses in email, fixes
+  issue2550632
 
 
 2009-12-21 1.4.11 (r4413)
 
 
 2009-12-21 1.4.11 (r4413)
index f1a1af3bdf45a20f469dd7132b022449cf922df1..729aaeab4d7200fbef196db904d53497f59fbde4 100644 (file)
@@ -9,7 +9,7 @@ from cStringIO import StringIO
 from roundup import __version__
 from roundup.date import get_timezone
 
 from roundup import __version__
 from roundup.date import get_timezone
 
-from email.Utils import formatdate, formataddr
+from email.Utils import formatdate, formataddr, specialsre, escapesre
 from email.Message import Message
 from email.Header import Header
 from email.MIMEText import MIMEText
 from email.Message import Message
 from email.Header import Header
 from email.MIMEText import MIMEText
@@ -25,6 +25,21 @@ def encode_quopri(msg):
     del msg['Content-Transfer-Encoding']
     msg['Content-Transfer-Encoding'] = 'quoted-printable'
 
     del msg['Content-Transfer-Encoding']
     msg['Content-Transfer-Encoding'] = 'quoted-printable'
 
+def nice_sender_header(name, address, charset):
+    # construct an address header so it's as human-readable as possible
+    # even in the presence of a non-ASCII name part
+    h = Header(charset=charset)
+    # the important bits of formataddr()
+    if specialsre.search(name):
+        name = '"%s"'%escapesre.sub(r'\\\g<0>', name)
+    try:
+        name.encode('ASCII')
+        h.append(name, 'ASCII')
+    except UnicodeEncodeError:
+        h.append(name)
+    h.append('<%s>'%address, 'ASCII')
+    return str(h)
+
 class Mailer:
     """Roundup-specific mail sending."""
     def __init__(self, config):
 class Mailer:
     """Roundup-specific mail sending."""
     def __init__(self, config):
@@ -65,11 +80,7 @@ class Mailer:
             name = author[0]
         else:
             name = unicode(author[0], 'utf-8')
             name = author[0]
         else:
             name = unicode(author[0], 'utf-8')
-        try:
-            name = name.encode('ascii')
-        except UnicodeError:
-            name = Header(name, charset).encode()
-        author = formataddr((name, author[1]))
+        author = nice_sender_header(name, author[1], charset)
 
         if multipart:
             message = MIMEMultipart()
 
         if multipart:
             message = MIMEMultipart()
index 9e241e9309e1516aa3ab46406f5b21066cf30999..80f4ee108eea9a71cc814822ccb18862c8115e05 100644 (file)
@@ -35,7 +35,8 @@ from roundup import password, date, hyperdb
 from roundup.i18n import _
 
 # MessageSendError is imported for backwards compatibility
 from roundup.i18n import _
 
 # MessageSendError is imported for backwards compatibility
-from roundup.mailer import Mailer, MessageSendError, encode_quopri
+from roundup.mailer import Mailer, MessageSendError, encode_quopri, \
+    nice_sender_header
 
 class Database:
 
 
 class Database:
 
@@ -406,9 +407,10 @@ class IssueClass:
         else:
             sendto = [sendto]
 
         else:
             sendto = [sendto]
 
+        # tracker sender info
         tracker_name = unicode(self.db.config.TRACKER_NAME, 'utf-8')
         tracker_name = unicode(self.db.config.TRACKER_NAME, 'utf-8')
-        tracker_name = formataddr((tracker_name, from_address))
-        tracker_name = Header(tracker_name, charset)
+        tracker_name = nice_sender_header(tracker_name, from_address,
+            charset)
 
         # now send one or more messages
         # TODO: I believe we have to create a new message each time as we
 
         # now send one or more messages
         # TODO: I believe we have to create a new message each time as we
diff --git a/test/test_mailer.py b/test/test_mailer.py
new file mode 100644 (file)
index 0000000..95d0df4
--- /dev/null
@@ -0,0 +1,24 @@
+#-*- encoding: utf8 -*-
+import unittest
+
+from roundup import mailer
+
+class EncodingTestCase(unittest.TestCase):
+    def test(self):
+        a = lambda n, a, c, o: self.assertEquals(mailer.nice_sender_header(n,
+            a, c), o)
+        a('ascii', 'ascii@test.com', 'latin1', 'ascii <ascii@test.com>')
+        a(u'cafĂ©', 'ascii@test.com', 'latin1',
+            '=?latin1?q?caf=E9?= <ascii@test.com>')
+        a('as"ii', 'ascii@test.com', 'latin1', '"as\\"ii" <ascii@test.com>')
+
+def test_suite():
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(EncodingTestCase))
+    return suite
+
+if __name__ == '__main__':
+    runner = unittest.TextTestRunner()
+    unittest.main(testRunner=runner)
+
+# vim: set et sts=4 sw=4 :