commit 1138daa8e1202d1649a70c7b238ac7ebcade23a8 Author: Damian Johnson atagar@torproject.org Date: Fri Jan 10 16:13:01 2020 -0800
Replace rfc822 with email.message
Hardest part of this migration yet. Python 2's deprecated rfc8222 module was removed in python 3. Unfortunately Isis used a catch-all here, covering the fact that this code has always been a bit broken (due to overriding our 'addr' import with a local variable)...
Traceback (most recent call last): File "/home/atagar/Desktop/tor/bridgedb/bridgedb/test/test_email_autoresponder.py", line 353, in test_SMTPAutoresponder_getMailFrom_givemebridges_at_seriously recipient = str(self.responder.getMailFrom()) File "/home/atagar/Desktop/tor/bridgedb/bridgedb/distributors/email/autoresponder.py", line 535, in getMailFrom raise addr.BadEmail(allRecipients) builtins.AttributeError: 'str' object has no attribute 'BadEmail'
Finally the single test that exercises this code path works...
before: FAILED (skips=109, failures=24, errors=225, successes=623) after: FAILED (skips=109, failures=23, errors=225, successes=624) --- bridgedb/distributors/email/autoresponder.py | 19 ++++++++++--------- bridgedb/distributors/email/server.py | 12 ++++-------- bridgedb/test/test_email_dkim.py | 4 ++-- bridgedb/test/test_email_server.py | 6 +++--- 4 files changed, 19 insertions(+), 22 deletions(-)
diff --git a/bridgedb/distributors/email/autoresponder.py b/bridgedb/distributors/email/autoresponder.py index 1d2b618..3711eae 100644 --- a/bridgedb/distributors/email/autoresponder.py +++ b/bridgedb/distributors/email/autoresponder.py @@ -39,6 +39,7 @@ Functionality for autoresponding to incoming emails. from __future__ import unicode_literals from __future__ import print_function
+import email import io import logging import time @@ -439,8 +440,8 @@ class SMTPAutoresponder(smtp.SMTPClient):
if not body: return # The client was already warned.
- messageID = self.incoming.message.getheader("Message-ID", None) - subject = self.incoming.message.getheader("Subject", None) + messageID = self.incoming.message.get("Message-ID", None) + subject = self.incoming.message.get("Subject", None) response = generateResponse(recipient, client, body, subject, messageID, self.incoming.context.gpgSignFunc) @@ -461,13 +462,13 @@ class SMTPAutoresponder(smtp.SMTPClient): """ clients = [] addrHeader = None - try: fromAddr = self.incoming.message.getaddr("From")[1] + try: fromAddr = email.utils.parseaddr(self.incoming.message.get("From"))[1] except (IndexError, TypeError, AttributeError): pass else: addrHeader = fromAddr
if not addrHeader: logging.warn("No From header on incoming mail.") - try: senderHeader = self.incoming.message.getaddr("Sender")[1] + try: senderHeader = email.utils.parseaddr(self.incoming.message.get("Sender"))[1] except (IndexError, TypeError, AttributeError): pass else: addrHeader = senderHeader if not addrHeader: @@ -509,10 +510,10 @@ class SMTPAutoresponder(smtp.SMTPClient):
try: ourAddress = smtp.Address(self.incoming.context.fromAddr) - allRecipients = self.incoming.message.getaddrlist("To") + allRecipients = self.incoming.message.get_all("To")
- for _, addr in allRecipients: - recipient = smtp.Address(addr) + for address in allRecipients: + recipient = smtp.Address(address) if not ourAddress.domain in recipient.domain: logging.debug(("Not our domain (%s) or subdomain, skipping" " email address: %s") @@ -525,11 +526,11 @@ class SMTPAutoresponder(smtp.SMTPClient): " email address: %s") % str(recipient)) continue # Only check the username before the first '+': - beforePlus = recipient.local.split('+', 1)[0] + beforePlus = recipient.local.split(b'+', 1)[0] if beforePlus == ourAddress.local: ours = str(recipient) if not ours: - raise addr.BadEmail(allRecipients) + raise addr.BadEmail('No email address accepted, please see log', allRecipients)
except Exception as error: logging.error(("Couldn't find our email address in incoming email " diff --git a/bridgedb/distributors/email/server.py b/bridgedb/distributors/email/server.py index 0f96812..8a2fbea 100644 --- a/bridgedb/distributors/email/server.py +++ b/bridgedb/distributors/email/server.py @@ -49,10 +49,10 @@ Servers which interface with clients and distribute bridges over SMTP.
from __future__ import unicode_literals
+import email.message import logging import io import socket -import rfc822
from twisted.internet import defer from twisted.internet import reactor @@ -222,7 +222,7 @@ class SMTPMessage(object): if self.nBytes > self.context.maximumSize: self.ignoring = True else: - self.lines.append(line) + self.lines.append(line.decode('utf-8') if isinstance(line, bytes) else line) if not safelog.safe_logging: try: ln = line.rstrip("\r\n").encode('utf-8', 'replace') @@ -251,12 +251,8 @@ class SMTPMessage(object): :rtype: :api:`twisted.mail.smtp.rfc822.Message` :returns: A ``Message`` comprised of all lines received thus far. """ - rawMessage = io.StringIO() - for line in self.lines: - line = line.decode('utf-8') if isinstance(line, bytes) else line - rawMessage.writelines(line + '\n') - rawMessage.seek(0) - return rfc822.Message(rawMessage) + + return email.message_from_string('\n'.join(self.lines))
@implementer(smtp.IMessageDelivery) diff --git a/bridgedb/test/test_email_dkim.py b/bridgedb/test/test_email_dkim.py index e8fe3f3..2330a71 100644 --- a/bridgedb/test/test_email_dkim.py +++ b/bridgedb/test/test_email_dkim.py @@ -11,8 +11,8 @@
"""Unittests for the :mod:`bridgedb.distributors.email.dkim` module."""
+import email.message import io -import rfc822
from twisted.trial import unittest
@@ -47,7 +47,7 @@ get bridges
def _createMessage(self, messageString): """Create an ``email.message.Message`` from a string.""" - messageIO = io.StringIO(messageString if isinstance(messageString, str) else messageString.decode('utf-8')) + messageIO = io.StringIO(unicode(messageString)) return rfc822.Message(messageIO)
def test_checkDKIM_good(self): diff --git a/bridgedb/test/test_email_server.py b/bridgedb/test/test_email_server.py index bc331f4..081a0e4 100644 --- a/bridgedb/test/test_email_server.py +++ b/bridgedb/test/test_email_server.py @@ -13,10 +13,10 @@
from __future__ import print_function
+import email.message import socket import string import types -import rfc822
from twisted.python import log from twisted.internet import defer @@ -95,10 +95,10 @@ class SMTPMessageTests(unittest.TestCase): defer.Deferred)
def test_SMTPMessage_getIncomingMessage(self): - """``getIncomingMessage`` should return a ``rfc822.Message``.""" + """``getIncomingMessage`` should return a ``email.message.Message``.""" self.message.lineReceived(self.line) self.assertIsInstance(self.message.getIncomingMessage(), - rfc822.Message) + email.message.Message)
class SMTPIncomingDeliveryTests(unittest.TestCase):
tor-commits@lists.torproject.org