[tor-commits] [bridgedb/develop] Fix unicode encoding errors in outgoing SMTP transport.

isis at torproject.org isis at torproject.org
Thu Apr 17 05:10:03 UTC 2014


commit fcaf0a5a4401d9f85bd16b550edfefaa2ef50559
Author: Isis Lovecruft <isis at torproject.org>
Date:   Tue Apr 8 23:30:27 2014 +0000

    Fix unicode encoding errors in outgoing SMTP transport.
    
      * REFACTOR bridgedb.EmailServer.composeEmail() to use io.BytesIO.
---
 lib/bridgedb/EmailServer.py |   83 +++++++++++++++++++++++--------------------
 1 file changed, 44 insertions(+), 39 deletions(-)

diff --git a/lib/bridgedb/EmailServer.py b/lib/bridgedb/EmailServer.py
index e1aa57e..db2cf80 100644
--- a/lib/bridgedb/EmailServer.py
+++ b/lib/bridgedb/EmailServer.py
@@ -8,9 +8,9 @@
 from __future__ import unicode_literals
 
 from email import message
-from io import StringIO
 import gettext
 import gpgme
+import io
 import logging
 import re
 import rfc822
@@ -315,6 +315,47 @@ def getLocaleFromRequest(request):
         lang = lang[0]
     return I18n.getLang(lang) 
 
+def composeEmail(fromAddr, clientAddr, subject, body,
+                 msgID=None, gpgContext=None):
+
+    if not subject.startswith("Re:"):
+        subject = "Re: %s" % subject
+
+    msg = smtp.rfc822.Message(io.StringIO())
+    msg.setdefault("From", fromAddr)
+    msg.setdefault("To", clientAddr)
+    msg.setdefault("Message-ID", smtp.messageid())
+    msg.setdefault("Subject", subject)
+    if msgID:
+        msg.setdefault("In-Reply-To", msgID)
+    msg.setdefault("Date", smtp.rfc822date())
+    msg.setdefault('Content-Type', 'text/plain; charset="utf-8"')
+    headers = [': '.join(m) for m in msg.items()]
+
+    mail = io.BytesIO()
+    mail.writelines(buffer("\r\n".join(headers)))
+    mail.writelines(buffer("\r\n"))
+    mail.writelines(buffer("\r\n"))
+
+    if not gpgContext:
+        mail.write(buffer(body))
+    else:
+        signature, siglist = gpgSignMessage(gpgContext, body)
+        if signature:
+            mail.writelines(buffer(signature))
+    mail.seek(0)
+
+    # Only log the email text (including all headers) if SAFE_LOGGING is
+    # disabled:
+    if not safelog.safe_logging:
+        logging.debug("Email contents:\n\n%s" % mail.read())
+        mail.seek(0)
+    else:
+        logging.debug("Email text for %r created." % clientAddr)
+
+    return clientAddr, mail
+
+
 class MailContext(object):
     """Helper object that holds information used by email subsystem."""
 
@@ -439,45 +480,9 @@ def addSMTPServer(cfg, dist, sched):
     lc.start(1800, now=False)
     return factory
 
-def composeEmail(fromAddr, clientAddr, subject, body, msgID=False,
-        gpgContext=None):
 
-    msg = message.Message()
-    msg.add_header("From", fromAddr)
-    msg.add_header("To", clientAddr)
-    msg.add_header("Message-ID", smtp.messageid())
-    if not subject.startswith("Re:"): subject = "Re: %s"%subject
-    msg.add_header("Subject", subject)
-    if msgID:
-        msg.add_header("In-Reply-To", msgID)
-    msg.add_header("Date", smtp.rfc822date())
-    msg.set_default_type("text/plain")
-    headers = [': '.join(m) for m in msg.items()]
-    mail = StringIO("\r\n".join(headers))
-    mail.writelines(unicode(msg.as_string()))
-
-    # gpg-clearsign messages
-    if gpgContext:
-        signature = StringIO()
-        plaintext = StringIO(body)
-        sigs = gpgContext.sign(plaintext, signature, gpgme.SIG_MODE_CLEAR)
-        if (len(sigs) != 1):
-            logging.warn('Failed to sign message!')
-        signature.seek(0)
-        [mail.write(l) for l in signature]
-    else:
-        mail.write(body)
 
-    # Only log the email text (including all headers) if SAFE_LOGGING is
-    # disabled:
-    if not safelog.safe_logging:
-        mail.seek(0)
-        logging.debug("Email contents:\n%s" % mail.read())
-    else:
-        logging.debug("Email text for %r created." % clientAddr)
-    mail.seek(0)
 
-    return clientAddr, mail
 
 def getGPGContext(cfg):
     """Import a key from a file and initialise a context for GnuPG operations.
@@ -520,8 +525,8 @@ def getGPGContext(cfg):
         ctx.signers = [ctx.get_key(fingerprint)]
 
         logging.info("Testing signature created with GnuPG key...")
-        message = StringIO('Test')
-        new_sigs = ctx.sign(message, StringIO(), gpgme.SIG_MODE_CLEAR)
+        message = io.StringIO('Test')
+        new_sigs = ctx.sign(message, io.StringIO(), gpgme.SIG_MODE_CLEAR)
         if not len(new_sigs) == 1:
             raise gpgme.GpgmeError(
                 "Testing was unable to produce a signature with GnuPG key.")





More information about the tor-commits mailing list