launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #25950
[Merge] ~cjwatson/launchpad:py3-stubmailer-bytes into launchpad:master
Colin Watson has proposed merging ~cjwatson/launchpad:py3-stubmailer-bytes into launchpad:master.
Commit message:
Treat email bodies in StubMailer as bytes
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/395904
Other bits of email infrastructure, as well as very many tests, still need to be updated to use bytes here for Python 3 compatibility. This mainly just establishes the basic compatibility infrastructure.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:py3-stubmailer-bytes into launchpad:master.
diff --git a/lib/lp/bugs/scripts/debbugs.py b/lib/lp/bugs/scripts/debbugs.py
index f15de06..0d3c3c8 100644
--- a/lib/lp/bugs/scripts/debbugs.py
+++ b/lib/lp/bugs/scripts/debbugs.py
@@ -11,13 +11,10 @@ import re
import subprocess
import sys
-if sys.version_info[:2] >= (3, 5):
- from email import message_from_bytes
-else:
- from email import message_from_string as message_from_bytes
-
import six
+from lp.services.compat import message_from_bytes
+
class Bug:
def __init__(self, db, id, package=None, date=None, status=None,
diff --git a/lib/lp/services/compat.py b/lib/lp/services/compat.py
index 50935f9..b985631 100644
--- a/lib/lp/services/compat.py
+++ b/lib/lp/services/compat.py
@@ -11,6 +11,8 @@ from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
'lzma',
+ 'message_as_bytes',
+ 'message_from_bytes',
'mock',
'SafeConfigParser',
]
@@ -21,6 +23,13 @@ except ImportError:
from ConfigParser import SafeConfigParser
try:
+ from email import message_from_bytes
+except ImportError:
+ from email import message_from_string as message_from_bytes
+
+import io
+
+try:
import lzma
except ImportError:
from backports import lzma
@@ -29,3 +38,20 @@ try:
import mock
except ImportError:
from unittest import mock
+
+import six
+
+
+if six.PY3:
+ def message_as_bytes(message):
+ from email.generator import BytesGenerator
+ from email.policy import compat32
+
+ fp = io.BytesIO()
+ g = BytesGenerator(
+ fp, mangle_from_=False, maxheaderlen=0, policy=compat32)
+ g.flatten(message)
+ return fp.getvalue()
+else:
+ def message_as_bytes(message):
+ return message.as_string()
diff --git a/lib/lp/services/mail/stub.py b/lib/lp/services/mail/stub.py
index 1492057..b63265c 100644
--- a/lib/lp/services/mail/stub.py
+++ b/lib/lp/services/mail/stub.py
@@ -5,13 +5,17 @@
__metaclass__ = type
-import email
from logging import getLogger
from zope.component import getUtility
from zope.interface import implementer
from zope.sendmail.interfaces import IMailer
+from lp.services.compat import (
+ message_as_bytes,
+ message_from_bytes,
+ )
+
@implementer(IMailer)
class StubMailer:
@@ -37,7 +41,7 @@ class StubMailer:
# headers that determine the actual To: address. However, this might
# be required to bypass some spam filters.
if self.rewrite:
- message = email.message_from_string(message)
+ message = message_from_bytes(message)
message['X-Orig-To'] = message['To']
message['X-Orig-Cc'] = message['Cc']
message['X-Orig-From'] = message['From']
@@ -47,7 +51,7 @@ class StubMailer:
del message['Reply-To']
message['To'] = ', '.join(self.to_addrs)
message['From'] = self.from_addr
- message = message.as_string()
+ message = message_as_bytes(message)
sendmail = getUtility(IMailer, self.mailer)
sendmail.send(self.from_addr, self.to_addrs, message)
diff --git a/lib/lp/testing/mail_helpers.py b/lib/lp/testing/mail_helpers.py
index 3ac740a..1b405e3 100644
--- a/lib/lp/testing/mail_helpers.py
+++ b/lib/lp/testing/mail_helpers.py
@@ -7,7 +7,6 @@ from __future__ import absolute_import, print_function
__metaclass__ = type
-import email
import operator
import transaction
@@ -20,6 +19,7 @@ from lp.registry.interfaces.persontransferjob import (
ITeamInvitationNotificationJobSource,
ITeamJoinNotificationJobSource,
)
+from lp.services.compat import message_from_bytes
from lp.services.config import config
from lp.services.job.runner import JobRunner
from lp.services.log.logger import DevNullLogger
@@ -45,7 +45,7 @@ def pop_notifications(sort_key=None, commit=True):
notifications = []
for fromaddr, toaddrs, raw_message in stub.test_emails:
- notification = email.message_from_string(raw_message)
+ notification = message_from_bytes(raw_message)
notification['X-Envelope-To'] = ', '.join(toaddrs)
notification['X-Envelope-From'] = fromaddr
notifications.append(notification)