Index: trac/Notify.py
===================================================================
--- trac/Notify.py	(revision 58)
+++ trac/Notify.py	(working copy)
@@ -23,6 +23,7 @@
 import md5
 import time
 import smtplib
+import re
 
 
 class Notify:
@@ -78,6 +79,14 @@
     def __init__(self, env):
         Notify.__init__(self, env)
 
+        from email.Charset import Charset, SHORTEST, QP, BASE64
+        self._charset = Charset()
+        self._charset.header_encoding = BASE64
+        self._charset.body_encoding = BASE64
+        self._charset.input_charset = self._charset.output_charset = 'utf-8'
+        self._charset.input_codec = self._charset.output_codec = 'utf-8'
+        self._addr_re = re.compile("^\s*(.*)\s+<([\w\d_\-\.]+@[\w\d_\-\.]+)>\s*$");
+
         # Get the email addresses of all known users
         self.email_map = {}
         for username, name, email in self.env.get_known_users(self.db):
@@ -113,6 +122,29 @@
         emails = [x[1] for x in  email.Utils.getaddresses([str(txt)])]
         return filter(lambda x: x.find('@') > -1, emails)
 
+    def format_header(self, name, email=None):
+        from email.Header import Header
+        try:
+            name = unicode(name, 'ascii')
+        except UnicodeDecodeError:
+            name = Header(name, self._charset)
+        if not email:
+            return name
+        else:
+            return "%s <%s>" % (name, email)
+
+    def add_headers(self, msg, headers):
+        for h in headers:
+            value = headers[h]
+            if isinstance(value, tuple):
+                msg[h] = self.format_header(value[0], value[1])
+                continue
+            mo = self._addr_re.match(value)
+            if mo:
+                msg[h] = self.format_header(mo.group(1), mo.group(2))
+                continue
+            msg[h] = self.format_header(value)
+
     def begin_send(self):
         self.server = smtplib.SMTP(self.smtp_server, self.smtp_port)
         if self.user_name:
@@ -120,23 +152,27 @@
 
     def send(self, rcpt, mime_headers={}):
         from email.MIMEText import MIMEText
-        from email.Header import Header
-        from email.Utils import formatdate
+        from email.Utils import formatdate, formataddr
+
         body = self.hdf.render(self.template_name)
+        projname = self.config.get('project','name')
+
+        headers = {}
+        headers['X-Mailer'] = 'Trac %s, by Edgewall Software' % __version__
+        headers['X-Trac-Version'] =  __version__
+        headers['X-Trac-Project'] =  projname
+        headers['X-URL'] = self.config.get('project','url')
+        headers['Subject'] = self.subject
+        headers['From'] = (projname, self.from_email)
+        headers['Sender'] = self.from_email
+        headers['Reply-To'] = self.replyto_email
+        headers['To'] = rcpt
+        headers['Date'] = formatdate()
+
         msg = MIMEText(body, 'plain', 'utf-8')
-        msg['X-Mailer'] = 'Trac %s, by Edgewall Software' % __version__
-        msg['X-Trac-Version'] =  __version__
-        projname = self.config.get('project','name')
-        msg['X-Trac-Project'] =  projname
-        msg['X-URL'] =  self.config.get('project','url')
-        msg['Subject'] = Header(self.subject, 'utf-8')
-        msg['From'] = '%s <%s>' % (projname, self.from_email)
-        msg['Sender'] = self.from_email
-        msg['Reply-To'] = self.replyto_email
-        msg['To'] = rcpt
-        msg['Date'] = formatdate()
-        for hdr in mime_headers.keys():
-            msg[hdr] = mime_headers[hdr]
+        self.add_headers(msg, headers);
+        self.add_headers(msg, mime_headers);
+
         self.env.log.debug("Sending SMTP notification to %s on port %d"
                            % (self.smtp_server, self.smtp_port))
         self.server.sendmail(self.from_email, [rcpt], msg.as_string())

