← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~cjwatson/launchpad:py3only-message-from-bytes into launchpad:master

 

Colin Watson has proposed merging ~cjwatson/launchpad:py3only-message-from-bytes into launchpad:master.

Commit message:
Use email.message_from_bytes directly

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/408168
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad:py3only-message-from-bytes into launchpad:master.
diff --git a/lib/lp/blueprints/doc/specification-notifications.txt b/lib/lp/blueprints/doc/specification-notifications.txt
index 7eb04ab..63130a4 100644
--- a/lib/lp/blueprints/doc/specification-notifications.txt
+++ b/lib/lp/blueprints/doc/specification-notifications.txt
@@ -116,9 +116,9 @@ are now subscribed.
 
 Now let's take a look at what the notification looks like:
 
-    >>> from lp.services.compat import message_from_bytes
+    >>> import email
     >>> notifications = [
-    ...     message_from_bytes(raw_message)
+    ...     email.message_from_bytes(raw_message)
     ...     for from_addr, to_addrs, raw_message in sorted(stub.test_emails)]
     >>> status_notification = notifications[0]
     >>> status_notification['To']
@@ -158,7 +158,7 @@ Whiteboard change:
     >>> transaction.commit()
 
     >>> notifications = [
-    ...     message_from_bytes(raw_message)
+    ...     email.message_from_bytes(raw_message)
     ...     for from_addr, to_addrs, raw_message in sorted(stub.test_emails)]
     >>> status_notification = notifications[0]
     >>> status_notification['To']
@@ -198,7 +198,7 @@ Definition status and whiteboard change:
     >>> transaction.commit()
 
     >>> notifications = [
-    ...     message_from_bytes(raw_message)
+    ...     email.message_from_bytes(raw_message)
     ...     for from_addr, to_addrs, raw_message in sorted(stub.test_emails)]
     >>> status_notification = notifications[0]
     >>> status_notification['To']
@@ -238,7 +238,7 @@ Change priority:
     >>> transaction.commit()
 
     >>> notifications = [
-    ...     message_from_bytes(raw_message)
+    ...     email.message_from_bytes(raw_message)
     ...     for from_addr, to_addrs, raw_message in sorted(stub.test_emails)]
     >>> status_notification = notifications[0]
     >>> status_notification['To']
@@ -272,7 +272,7 @@ Change approver, assignee and drafter:
     >>> transaction.commit()
 
     >>> notifications = [
-    ...     message_from_bytes(raw_message)
+    ...     email.message_from_bytes(raw_message)
     ...     for from_addr, to_addrs, raw_message in sorted(stub.test_emails)]
     >>> status_notification = notifications[0]
     >>> status_notification['To']
diff --git a/lib/lp/bugs/doc/externalbugtracker-debbugs.txt b/lib/lp/bugs/doc/externalbugtracker-debbugs.txt
index 9dce3b5..aec439d 100644
--- a/lib/lp/bugs/doc/externalbugtracker-debbugs.txt
+++ b/lib/lp/bugs/doc/externalbugtracker-debbugs.txt
@@ -416,10 +416,9 @@ same comment.
 If we query the DebBugs database directly we'll see that there are two
 copies of the same comment.
 
-    >>> from lp.services.compat import message_from_bytes
     >>> debian_bug = external_debbugs._findBug(bug_watch.remotebug)
     >>> for comment in debian_bug.comments:
-    ...     comment_email = message_from_bytes(comment)
+    ...     comment_email = email.message_from_bytes(comment)
     ...     print(comment_email['message-id'])
     <20040309081430.98BF411EE67@tux>
     <20040309081430.98BF411EE67@tux>
@@ -493,7 +492,7 @@ datecreated comes not from the Date header but from the Received header.
 
     >>> from lp.bugs.tests.externalbugtracker import (
     ...     read_test_file)
-    >>> parsed_message = message_from_bytes(
+    >>> parsed_message = email.message_from_bytes(
     ...     read_test_file('debbugs-comment-with-received-date.txt').encode(
     ...         'UTF-8'))
 
@@ -519,7 +518,7 @@ default to using the Date header again.
     >>> print(message.datecreated)
     2007-12-14 18:54:30+00:00
 
-    >>> parsed_message = message_from_bytes(
+    >>> parsed_message = email.message_from_bytes(
     ...     read_test_file('debbugs-comment-with-received-date.txt').encode(
     ...         'UTF-8'))
 
diff --git a/lib/lp/bugs/doc/initial-bug-contacts.txt b/lib/lp/bugs/doc/initial-bug-contacts.txt
index 46e8ed2..7161f17 100644
--- a/lib/lp/bugs/doc/initial-bug-contacts.txt
+++ b/lib/lp/bugs/doc/initial-bug-contacts.txt
@@ -167,8 +167,8 @@ notification). The email has the X-Launchpad-Message-Rationale header to
 track why daf received the email. The rational is repeated in the footer
 of the email with the bug title and URL.
 
+    >>> import email
     >>> from operator import itemgetter
-    >>> from lp.services.compat import message_from_bytes
 
     >>> test_emails = list(stub.test_emails)
     >>> test_emails.sort(key=itemgetter(1))
@@ -183,7 +183,7 @@ of the email with the bug title and URL.
     >>> print(to_addr)
     ['daf@xxxxxxxxxxxxx']
 
-    >>> msg = message_from_bytes(raw_message)
+    >>> msg = email.message_from_bytes(raw_message)
     >>> msg['References'] == (
     ...        bug_one_in_ubuntu_firefox.bug.initial_message.rfc822msgid)
     True
diff --git a/lib/lp/bugs/externalbugtracker/debbugs.py b/lib/lp/bugs/externalbugtracker/debbugs.py
index 360c2b5..1bca0c7 100644
--- a/lib/lp/bugs/externalbugtracker/debbugs.py
+++ b/lib/lp/bugs/externalbugtracker/debbugs.py
@@ -10,6 +10,7 @@ __all__ = [
     ]
 
 from datetime import datetime
+import email
 from email.utils import (
     mktime_tz,
     parseaddr,
@@ -41,7 +42,6 @@ from lp.bugs.interfaces.externalbugtracker import (
     UNKNOWN_REMOTE_IMPORTANCE,
     )
 from lp.bugs.scripts import debbugs
-from lp.services.compat import message_from_bytes
 from lp.services.config import config
 from lp.services.database.isolation import ensure_no_transaction
 from lp.services.mail.sendmail import simple_sendmail
@@ -242,7 +242,7 @@ class DebBugs(ExternalBugTracker):
 
         comment_ids = []
         for comment in debian_bug.comments:
-            parsed_comment = message_from_bytes(comment)
+            parsed_comment = email.message_from_bytes(comment)
 
             # It's possible for the same message to appear several times
             # in a DebBugs comment log, since each control command in a
@@ -271,7 +271,7 @@ class DebBugs(ExternalBugTracker):
         self._loadLog(debian_bug)
 
         for comment in debian_bug.comments:
-            parsed_comment = message_from_bytes(comment)
+            parsed_comment = email.message_from_bytes(comment)
             if parsed_comment['message-id'] == comment_id:
                 return parseaddr(parsed_comment['from'])
 
@@ -324,7 +324,7 @@ class DebBugs(ExternalBugTracker):
         self._loadLog(debian_bug)
 
         for comment in debian_bug.comments:
-            parsed_comment = message_from_bytes(comment)
+            parsed_comment = email.message_from_bytes(comment)
             if parsed_comment['message-id'] == comment_id:
                 msg_date = self._getDateForComment(parsed_comment)
                 message = getUtility(IMessageSet).fromEmail(comment, poster,
diff --git a/lib/lp/bugs/scripts/debbugs.py b/lib/lp/bugs/scripts/debbugs.py
index 81055c1..d693df1 100644
--- a/lib/lp/bugs/scripts/debbugs.py
+++ b/lib/lp/bugs/scripts/debbugs.py
@@ -11,8 +11,6 @@ import sys
 
 import six
 
-from lp.services.compat import message_from_bytes
-
 
 class Bug:
     def __init__(self, db, id, package=None, date=None, status=None,
@@ -59,7 +57,7 @@ class Bug:
         if self._emails:
             return self._emails
         for comment in self.comments:
-            message = message_from_bytes(comment)
+            message = email.message_from_bytes(comment)
             self._emails.append(message)
         return self._emails
 
@@ -207,7 +205,7 @@ class Database:
         bug.report = fd.read()
         fd.close()
 
-        report_msg = message_from_bytes(bug.report)
+        report_msg = email.message_from_bytes(bug.report)
         charset = report_msg.get_content_charset('ascii')
         description = report_msg.get_payload(decode=True)
         bug.description = description.decode(charset)
diff --git a/lib/lp/bugs/tests/bugs-emailinterface.txt b/lib/lp/bugs/tests/bugs-emailinterface.txt
index 452b6bf..94d9412 100644
--- a/lib/lp/bugs/tests/bugs-emailinterface.txt
+++ b/lib/lp/bugs/tests/bugs-emailinterface.txt
@@ -70,11 +70,11 @@ we'll have to authenticate the user manually:
 Now if we pass the message to the Malone handler, we can see that the
 bug got submitted correctly:
 
+    >>> import email
     >>> from lp.bugs.mail.handler import MaloneHandler
-    >>> from lp.services.compat import message_from_bytes
     >>> handler = MaloneHandler()
     >>> def construct_email(raw_mail):
-    ...     msg = message_from_bytes(raw_mail, _class=MockSignedMessage)
+    ...     msg = email.message_from_bytes(raw_mail, _class=MockSignedMessage)
     ...     if 'Message-Id' not in msg:
     ...         msg['Message-Id'] = factory.makeUniqueRFC822MsgId()
     ...     return msg
@@ -356,7 +356,7 @@ And the person sending the email has received an error message.
     ...     if not stub.test_emails:
     ...         raise AssertionError("No emails queued!")
     ...     from_addr, to_addrs, raw_message = stub.test_emails[-1]
-    ...     sent_msg = message_from_bytes(raw_message)
+    ...     sent_msg = email.message_from_bytes(raw_message)
     ...     error_mail, original_mail = sent_msg.get_payload()
     ...     print("Subject: %s" % sent_msg['Subject'])
     ...     print("To: %s" % ', '.join(to_addrs))
@@ -456,7 +456,8 @@ The same will happen if we send the same email without signing it:
     >>> class MockUnsignedMessage(email.message.Message):
     ...     signedMessage = None
     ...     signature = None
-    >>> msg = message_from_bytes(comment_mail, _class=MockUnsignedMessage)
+    >>> msg = email.message_from_bytes(
+    ...     comment_mail, _class=MockUnsignedMessage)
     >>> handler.process(
     ...     msg, msg['To'],
     ...     )
@@ -2040,7 +2041,7 @@ Let's take a closer look at send_process_error_notification(), which is
 used to send the error messages. It needs the message that caused the
 error, so let's create one.
 
-    >>> test_msg = message_from_bytes(b"""From: foo.bar@xxxxxxxxxxxxx
+    >>> test_msg = email.message_from_bytes(b"""From: foo.bar@xxxxxxxxxxxxx
     ... To: bugs@xxxxxxxxxxxxx
     ... Message-Id: <original@msg>
     ... Subject: Original Message Subject
@@ -2063,7 +2064,7 @@ The To and Subject headers got set to the values we provided:
 
     >>> transaction.commit()
     >>> from_addr, to_addrs, raw_message = stub.test_emails[-1]
-    >>> sent_msg = message_from_bytes(raw_message)
+    >>> sent_msg = email.message_from_bytes(raw_message)
     >>> sent_msg['To']
     'test@xxxxxxxxxxxxx'
     >>> sent_msg['Subject']
@@ -2123,7 +2124,7 @@ the original message.
     ...     max_return_size=max_return_size)
     >>> transaction.commit()
     >>> from_addr, to_addrs, raw_message = stub.test_emails[-1]
-    >>> sent_msg = message_from_bytes(raw_message)
+    >>> sent_msg = email.message_from_bytes(raw_message)
     >>> failure_msg, original_msg = sent_msg.get_payload()
     >>> msg = original_msg.get_payload()[0]
 
@@ -2220,7 +2221,7 @@ The 'subscribe' command failed, and the user is being notified of the
 failure in an email.
 
     >>> from_addr, to_addrs, raw_message = stub.test_emails[-1]
-    >>> sent_msg = message_from_bytes(raw_message)
+    >>> sent_msg = email.message_from_bytes(raw_message)
     >>> failure_msg, original_msg = sent_msg.get_payload()
     >>> print(failure_msg.get_payload(decode=True).decode('UTF-8'))
     An error occurred while processing a mail you sent to Launchpad's email
@@ -2268,7 +2269,7 @@ And the sender receives an email to let them know about the failing
 'security' command.
 
     >>> from_addr, to_addrs, raw_message = stub.test_emails[-1]
-    >>> sent_msg = message_from_bytes(raw_message)
+    >>> sent_msg = email.message_from_bytes(raw_message)
     >>> failure_msg, original_msg = sent_msg.get_payload()
     >>> print(failure_msg.get_payload(decode=True).decode('UTF-8'))
     An error occurred while processing a mail you sent to Launchpad's email
diff --git a/lib/lp/bugs/utilities/filebugdataparser.py b/lib/lp/bugs/utilities/filebugdataparser.py
index 3b320be..4ffc0a1 100644
--- a/lib/lp/bugs/utilities/filebugdataparser.py
+++ b/lib/lp/bugs/utilities/filebugdataparser.py
@@ -9,12 +9,12 @@ __all__ = [
     ]
 
 import base64
+import email
 import tempfile
 
 import six
 
 from lp.bugs.model.bug import FileBugData
-from lp.services.compat import message_from_bytes
 
 
 class FileBugDataParser:
@@ -62,7 +62,7 @@ class FileBugDataParser:
         header_text = self._consumeBytes(b'\n\n')
         # Use the email package to return a dict-like object of the
         # headers, so we don't have to parse the text ourselves.
-        return message_from_bytes(header_text)
+        return email.message_from_bytes(header_text)
 
     def readLine(self):
         """Read a line of the message."""
diff --git a/lib/lp/code/doc/codeimport.txt b/lib/lp/code/doc/codeimport.txt
index 3856ed3..d5da426 100644
--- a/lib/lp/code/doc/codeimport.txt
+++ b/lib/lp/code/doc/codeimport.txt
@@ -103,8 +103,8 @@ three members of the vcs-imports team.
     >>> vcs_imports = getUtility(ILaunchpadCelebrities).vcs_imports
     >>> len(get_contact_email_addresses(vcs_imports))
     3
-    >>> from lp.services.compat import message_from_bytes
-    >>> message = message_from_bytes(stub.test_emails[0][2])
+    >>> import email
+    >>> message = email.message_from_bytes(stub.test_emails[0][2])
     >>> print(message['subject'])
     New code import: ~import-person/widget/trunk-cvs
     >>> print(message['X-Launchpad-Message-Rationale'])
diff --git a/lib/lp/code/mail/tests/test_codeimport.py b/lib/lp/code/mail/tests/test_codeimport.py
index 18ecb59..ee62761 100644
--- a/lib/lp/code/mail/tests/test_codeimport.py
+++ b/lib/lp/code/mail/tests/test_codeimport.py
@@ -3,6 +3,7 @@
 
 """Tests for code import related mailings"""
 
+import email
 import textwrap
 
 import six
@@ -14,7 +15,6 @@ from lp.code.enums import (
     TargetRevisionControlSystems,
     )
 from lp.code.tests.helpers import GitHostingFixture
-from lp.services.compat import message_from_bytes
 from lp.services.mail import stub
 from lp.testing import (
     login_celebrity,
@@ -40,7 +40,7 @@ class TestNewCodeImports(TestCaseWithFactory):
             cvs_module='a_module', branch_name='import',
             product=fooix, registrant=eric)
         transaction.commit()
-        msg = message_from_bytes(stub.test_emails[0][2])
+        msg = email.message_from_bytes(stub.test_emails[0][2])
         self.assertEqual('code-import', msg['X-Launchpad-Notification-Type'])
         self.assertEqual('~eric/fooix/import', msg['X-Launchpad-Branch'])
         self.assertEqual(
@@ -64,7 +64,7 @@ class TestNewCodeImports(TestCaseWithFactory):
             branch_name='trunk', product=fooix, registrant=eric,
             rcs_type=RevisionControlSystems.BZR_SVN)
         transaction.commit()
-        msg = message_from_bytes(stub.test_emails[0][2])
+        msg = email.message_from_bytes(stub.test_emails[0][2])
         self.assertEqual('code-import', msg['X-Launchpad-Notification-Type'])
         self.assertEqual('~eric/fooix/trunk', msg['X-Launchpad-Branch'])
         self.assertEqual(
@@ -87,7 +87,7 @@ class TestNewCodeImports(TestCaseWithFactory):
             git_repo_url='git://git.example.com/fooix.git',
             branch_name='master', product=fooix, registrant=eric)
         transaction.commit()
-        msg = message_from_bytes(stub.test_emails[0][2])
+        msg = email.message_from_bytes(stub.test_emails[0][2])
         self.assertEqual('code-import', msg['X-Launchpad-Notification-Type'])
         self.assertEqual('~eric/fooix/master', msg['X-Launchpad-Branch'])
         self.assertEqual(
@@ -113,7 +113,7 @@ class TestNewCodeImports(TestCaseWithFactory):
             branch_name=u'master', product=fooix, registrant=eric,
             target_rcs_type=TargetRevisionControlSystems.GIT)
         transaction.commit()
-        msg = message_from_bytes(stub.test_emails[0][2])
+        msg = email.message_from_bytes(stub.test_emails[0][2])
         self.assertEqual('code-import', msg['X-Launchpad-Notification-Type'])
         self.assertEqual('~eric/fooix/+git/master', msg['X-Launchpad-Branch'])
         self.assertEqual(
@@ -141,7 +141,7 @@ class TestNewCodeImports(TestCaseWithFactory):
             git_repo_url='git://git.example.com/fooix.git',
             branch_name='master', sourcepackage=fooix, registrant=eric)
         transaction.commit()
-        msg = message_from_bytes(stub.test_emails[0][2])
+        msg = email.message_from_bytes(stub.test_emails[0][2])
         self.assertEqual('code-import', msg['X-Launchpad-Notification-Type'])
         self.assertEqual(
             '~eric/foobuntu/manic/fooix/master', msg['X-Launchpad-Branch'])
@@ -164,7 +164,7 @@ class TestUpdatedCodeImports(TestCaseWithFactory):
     layer = DatabaseFunctionalLayer
 
     def assertSameDetailsEmail(self, details, unique_name):
-        msg = message_from_bytes(stub.test_emails[0][2])
+        msg = email.message_from_bytes(stub.test_emails[0][2])
         self.assertEqual(
             'code-import-updated', msg['X-Launchpad-Notification-Type'])
         self.assertEqual(unique_name, msg['X-Launchpad-Branch'])
@@ -183,7 +183,7 @@ class TestUpdatedCodeImports(TestCaseWithFactory):
 
     def assertDifferentDetailsEmail(self, old_details, new_details,
                                     unique_name):
-        msg = message_from_bytes(stub.test_emails[0][2])
+        msg = email.message_from_bytes(stub.test_emails[0][2])
         self.assertEqual(
             'code-import-updated', msg['X-Launchpad-Notification-Type'])
         self.assertEqual(unique_name, msg['X-Launchpad-Branch'])
diff --git a/lib/lp/code/model/tests/test_gitrepository.py b/lib/lp/code/model/tests/test_gitrepository.py
index de296a7..6edeb1e 100644
--- a/lib/lp/code/model/tests/test_gitrepository.py
+++ b/lib/lp/code/model/tests/test_gitrepository.py
@@ -13,6 +13,7 @@ from datetime import (
     datetime,
     timedelta,
     )
+import email
 from functools import partial
 import hashlib
 import json
@@ -145,7 +146,6 @@ from lp.registry.interfaces.personociproject import IPersonOCIProjectFactory
 from lp.registry.interfaces.personproduct import IPersonProductFactory
 from lp.registry.tests.test_accesspolicy import get_policies_for_artifact
 from lp.services.authserver.xmlrpc import AuthServerAPIView
-from lp.services.compat import message_from_bytes
 from lp.services.config import config
 from lp.services.database.constants import UTC_NOW
 from lp.services.database.interfaces import IStore
@@ -1326,7 +1326,7 @@ class TestGitRepositoryModificationNotifications(TestCaseWithFactory):
                 getUtility(IGitRepositoryModifiedMailJobSource)).runAll()
         bodies_by_recipient = {}
         for from_addr, to_addrs, message in stub.test_emails:
-            body = message_from_bytes(message).get_payload(decode=True)
+            body = email.message_from_bytes(message).get_payload(decode=True)
             for to_addr in to_addrs:
                 bodies_by_recipient[to_addr] = six.ensure_text(body)
         # Both the owner and the unprivileged subscriber receive email.
diff --git a/lib/lp/codehosting/scanner/tests/test_email.py b/lib/lp/codehosting/scanner/tests/test_email.py
index 3072ec2..34af406 100644
--- a/lib/lp/codehosting/scanner/tests/test_email.py
+++ b/lib/lp/codehosting/scanner/tests/test_email.py
@@ -5,6 +5,7 @@
 
 __metaclass__ = type
 
+import email
 import os
 
 from breezy.uncommit import uncommit
@@ -25,7 +26,6 @@ from lp.codehosting.scanner import events
 from lp.codehosting.scanner.bzrsync import BzrSync
 from lp.codehosting.scanner.tests.test_bzrsync import BzrSyncTestCase
 from lp.registry.interfaces.person import IPersonSet
-from lp.services.compat import message_from_bytes
 from lp.services.config import config
 from lp.services.features.testing import FeatureFixture
 from lp.services.job.runner import JobRunner
@@ -72,7 +72,7 @@ class TestBzrSyncEmail(BzrSyncTestCase):
         self.assertEqual(len(stub.test_emails), 1)
         [initial_email] = stub.test_emails
         expected = 'First scan of the branch detected 0 revisions'
-        message = message_from_bytes(initial_email[2])
+        message = email.message_from_bytes(initial_email[2])
         email_body = message.get_payload()
         self.assertIn(expected, email_body)
         self.assertEmailHeadersEqual(
@@ -87,7 +87,7 @@ class TestBzrSyncEmail(BzrSyncTestCase):
         [initial_email] = stub.test_emails
         expected = ('First scan of the branch detected 1 revision'
                     ' in the revision history of the=\n branch.')
-        message = message_from_bytes(initial_email[2])
+        message = email.message_from_bytes(initial_email[2])
         email_body = message.get_payload()
         self.assertIn(expected, email_body)
         self.assertEmailHeadersEqual(
@@ -105,7 +105,7 @@ class TestBzrSyncEmail(BzrSyncTestCase):
         self.assertEqual(len(stub.test_emails), 1)
         [uncommit_email] = stub.test_emails
         expected = '1 revision was removed from the branch.'
-        message = message_from_bytes(uncommit_email[2])
+        message = email.message_from_bytes(uncommit_email[2])
         email_body = message.get_payload()
         self.assertIn(expected, email_body)
         self.assertEmailHeadersEqual(
@@ -137,7 +137,7 @@ class TestBzrSyncEmail(BzrSyncTestCase):
             'Subject: [Branch %s] Test branch' % self.db_branch.unique_name)
         self.assertIn(expected, uncommit_email_body)
 
-        recommit_email_msg = message_from_bytes(recommit_email[2])
+        recommit_email_msg = email.message_from_bytes(recommit_email[2])
         recommit_email_body = recommit_email_msg.get_payload()[0].get_payload(
             decode=True)
         subject = '[Branch %s] Rev 1: second' % self.db_branch.unique_name
diff --git a/lib/lp/registry/browser/tests/test_person.py b/lib/lp/registry/browser/tests/test_person.py
index 2b015ce..b21e38e 100644
--- a/lib/lp/registry/browser/tests/test_person.py
+++ b/lib/lp/registry/browser/tests/test_person.py
@@ -5,6 +5,7 @@
 __metaclass__ = type
 
 import doctest
+import email
 from operator import attrgetter
 import re
 from textwrap import dedent
@@ -67,7 +68,6 @@ from lp.registry.interfaces.teammembership import (
 from lp.registry.model.karma import KarmaCategory
 from lp.registry.model.milestone import milestone_sort_key
 from lp.scripts.garbo import PopulateLatestPersonSourcePackageReleaseCache
-from lp.services.compat import message_from_bytes
 from lp.services.config import config
 from lp.services.database.interfaces import IStore
 from lp.services.features.testing import FeatureFixture
@@ -938,7 +938,7 @@ class TestPersonEditView(TestPersonRenameFormMixin, TestCaseWithFactory):
         messages = [msg for from_addr, to_addr, msg in stub.test_emails]
         raw_msg = None
         for orig_msg in messages:
-            msg = message_from_bytes(orig_msg)
+            msg = email.message_from_bytes(orig_msg)
             if msg.get('to') == added_email:
                 raw_msg = orig_msg
         token_url = get_token_url_from_email(raw_msg)
diff --git a/lib/lp/registry/doc/distribution-mirror.txt b/lib/lp/registry/doc/distribution-mirror.txt
index 29c35dc..8939a83 100644
--- a/lib/lp/registry/doc/distribution-mirror.txt
+++ b/lib/lp/registry/doc/distribution-mirror.txt
@@ -364,7 +364,7 @@ up on the public mirror listings.
     >>> import transaction
     >>> transaction.commit()
 
-    >>> from lp.services.compat import message_from_bytes
+    >>> import email
     >>> from lp.services.mail import stub
     >>> len(stub.test_emails)
     2
@@ -377,7 +377,7 @@ up on the public mirror listings.
     ['mark@xxxxxxxxxxx']
     >>> valid_mirror.enabled
     False
-    >>> msg = message_from_bytes(raw_message)
+    >>> msg = email.message_from_bytes(raw_message)
     >>> print(msg.get_payload())
     Dear mirror administrator,
     <BLANKLINE>
diff --git a/lib/lp/registry/stories/gpg-coc/xx-gpg-coc.txt b/lib/lp/registry/stories/gpg-coc/xx-gpg-coc.txt
index 09342e8..1b81c27 100644
--- a/lib/lp/registry/stories/gpg-coc/xx-gpg-coc.txt
+++ b/lib/lp/registry/stories/gpg-coc/xx-gpg-coc.txt
@@ -5,9 +5,9 @@ Claiming GPG Keys
 Setup
 -----
 
+    >>> import email
     >>> from zope.component import getUtility
     >>> from lp.registry.interfaces.person import IPersonSet
-    >>> from lp.services.compat import message_from_bytes
     >>> from lp.services.mail import stub
     >>> from lp.testing.keyserver import KeyServerTac
     >>> from lp.testing.pages import setupBrowserFreshLogin
@@ -56,7 +56,7 @@ text part that provides useful information to users who -- for whatever reason
 -- cannot decrypt the token url.  Start by grabbing the confirmation message.
 
     >>> from_addr, to_addrs, raw_msg = stub.test_emails.pop()
-    >>> msg = message_from_bytes(raw_msg)
+    >>> msg = email.message_from_bytes(raw_msg)
     >>> msg.get_content_type()
     'text/plain'
 
@@ -178,7 +178,7 @@ their Launchpad account.
 Sample Person checks their email.
 
     >>> from_addr, to_addrs, raw_msg = stub.test_emails.pop()
-    >>> msg = message_from_bytes(raw_msg)
+    >>> msg = email.message_from_bytes(raw_msg)
     >>> msg.get_content_type()
     'text/plain'
     >>> body = msg.get_payload(decode=True)
@@ -512,7 +512,7 @@ Get the token from the body of the email sent.
     >>> import re
     >>> from lp.services.mail import stub
     >>> from_addr, to_addrs, raw_msg = stub.test_emails.pop()
-    >>> msg = message_from_bytes(raw_msg)
+    >>> msg = email.message_from_bytes(raw_msg)
     >>> cipher_body = msg.get_payload(decode=1)
     >>> body = decrypt_content(cipher_body, six.ensure_str('test'))
     >>> link = get_token_url_from_bytes(body)
@@ -628,7 +628,7 @@ Test if the advertisement email was sent:
 
     >>> from lp.services.mail import stub
     >>> from_addr, to_addrs, raw_msg = stub.test_emails.pop()
-    >>> msg = message_from_bytes(raw_msg)
+    >>> msg = email.message_from_bytes(raw_msg)
     >>> print(six.ensure_text(msg.get_payload(decode=True)))
     <BLANKLINE>
     ...
diff --git a/lib/lp/registry/stories/mailinglists/hosted-email-address.txt b/lib/lp/registry/stories/mailinglists/hosted-email-address.txt
index 9952c67..3853b24 100644
--- a/lib/lp/registry/stories/mailinglists/hosted-email-address.txt
+++ b/lib/lp/registry/stories/mailinglists/hosted-email-address.txt
@@ -46,8 +46,8 @@ Launchpad sends that address a confirmation message.
     >>> from_addr, to_addrs, raw_msg = stub.test_emails.pop()
     >>> stub.test_emails
     []
-    >>> from lp.services.compat import message_from_bytes
-    >>> msg = message_from_bytes(raw_msg)
+    >>> import email
+    >>> msg = email.message_from_bytes(raw_msg)
     >>> print(msg['From'])
     Launchpad Email Validator <noreply@xxxxxxxxxxxxx>
     >>> print(msg['Subject'])
diff --git a/lib/lp/registry/stories/person/xx-add-sshkey.txt b/lib/lp/registry/stories/person/xx-add-sshkey.txt
index c58405f..8c1095d 100644
--- a/lib/lp/registry/stories/person/xx-add-sshkey.txt
+++ b/lib/lp/registry/stories/person/xx-add-sshkey.txt
@@ -225,7 +225,7 @@ this case we'll raise an UnexpectedFormData.
 If he removes a key then he will get a security warning email notification
 that the key has been removed.
 
-    >>> from lp.services.compat import message_from_bytes
+    >>> import email
     >>> from lp.services.mail import stub
     >>> stub.test_emails = []
     >>> browser.open('http://launchpad.test/~salgado/+editsshkeys')
@@ -233,7 +233,7 @@ that the key has been removed.
     >>> from_addr, to_addr, msg = stub.test_emails.pop()
     >>> to_addr
     ['guilherme.salgado@xxxxxxxxxxxxx']
-    >>> payload = message_from_bytes(msg).get_payload()
+    >>> payload = email.message_from_bytes(msg).get_payload()
     >>> assert payload.startswith('The SSH Key')
 
 
diff --git a/lib/lp/registry/tests/test_mailinglistapi.py b/lib/lp/registry/tests/test_mailinglistapi.py
index 256bbfa..ec689eb 100644
--- a/lib/lp/registry/tests/test_mailinglistapi.py
+++ b/lib/lp/registry/tests/test_mailinglistapi.py
@@ -6,7 +6,7 @@
 __metaclass__ = type
 __all__ = []
 
-from email import message_from_string
+import email
 from textwrap import dedent
 
 from six.moves import xmlrpc_client
@@ -36,10 +36,7 @@ from lp.registry.xmlrpc.mailinglist import (
     ENABLED,
     MailingListAPIView,
     )
-from lp.services.compat import (
-    message_as_bytes,
-    message_from_bytes,
-    )
+from lp.services.compat import message_as_bytes
 from lp.services.config import config
 from lp.services.identity.interfaces.account import AccountStatus
 from lp.services.identity.interfaces.emailaddress import (
@@ -449,7 +446,7 @@ class MailingListAPIMessageTestCase(TestCaseWithFactory):
             self.factory.makeMailingList(team, owner)
         sender = self.factory.makePerson(email='me@xxxxxx')
         with person_logged_in(sender):
-            message = message_from_string(dedent("""\
+            message = email.message_from_string(dedent("""\
                 From: me@xxxxxx
                 To: team@xxxxxxxxxxxxxxxxxxxx
                 Subject: A question
@@ -493,7 +490,7 @@ class MailingListAPIMessageTestCase(TestCaseWithFactory):
         # Non-ascii messages headers are re-encoded for moderators.
         team, sender, message = self.makeMailingListAndHeldMessage()
         with person_logged_in(sender):
-            message = message_from_bytes(dedent("""\
+            message = email.message_from_bytes(dedent("""\
                 From: \xa9 me <me@xxxxxx>
                 To: team@xxxxxxxxxxxxxxxxxxxx
                 Subject: \xa9 gremlins
diff --git a/lib/lp/services/compat.py b/lib/lp/services/compat.py
index 88df437..835b123 100644
--- a/lib/lp/services/compat.py
+++ b/lib/lp/services/compat.py
@@ -10,15 +10,9 @@ __metaclass__ = type
 __all__ = [
     'escape',
     'message_as_bytes',
-    'message_from_bytes',
     ]
 
 try:
-    from email import message_from_bytes
-except ImportError:
-    from email import message_from_string as message_from_bytes
-
-try:
     from html import escape
 except ImportError:
     from cgi import escape
diff --git a/lib/lp/services/mail/doc/emailauthentication.txt b/lib/lp/services/mail/doc/emailauthentication.txt
index efcdce9..8cd8a8b 100644
--- a/lib/lp/services/mail/doc/emailauthentication.txt
+++ b/lib/lp/services/mail/doc/emailauthentication.txt
@@ -108,14 +108,11 @@ be canonicalised to \r\n. In order to ensure that the line endings in
 signed_canonicalised.txt are not already '\r\n', we recreate the test
 message.
 
-    >>> from lp.services.compat import (
-    ...     message_as_bytes,
-    ...     message_from_bytes,
-    ...     )
+    >>> from lp.services.compat import message_as_bytes
     >>> from lp.services.mail.signedmessage import SignedMessage
     >>> msg = read_test_message('signed_canonicalised.txt')
     >>> msg_lines = message_as_bytes(msg).splitlines()
-    >>> msg = message_from_bytes(
+    >>> msg = email.message_from_bytes(
     ...     b'\n'.join(msg_lines), _class=SignedMessage)
     >>> msg.parsed_bytes = message_as_bytes(msg)
 
@@ -135,7 +132,7 @@ authenticateEmail() doesn't have any problems verifying the signature:
 
     >>> from lp.registry.interfaces.person import IPerson
     >>> for line_ending in b'\n', b'\r\n':
-    ...     msg = message_from_bytes(
+    ...     msg = email.message_from_bytes(
     ...         line_ending.join(msg_lines), _class=SignedMessage)
     ...     msg.parsed_bytes = message_as_bytes(msg)
     ...     principal = authenticateEmail(msg, accept_any_timestamp)
diff --git a/lib/lp/services/mail/doc/mailbox.txt b/lib/lp/services/mail/doc/mailbox.txt
index aa9ac88..6424f2d 100644
--- a/lib/lp/services/mail/doc/mailbox.txt
+++ b/lib/lp/services/mail/doc/mailbox.txt
@@ -74,8 +74,8 @@ before:
     >>> len(mails)
     2
     >>> id, raw_mail = mails[0]
-    >>> from lp.services.compat import message_from_bytes
-    >>> mail = message_from_bytes(raw_mail)
+    >>> import email
+    >>> mail = email.message_from_bytes(raw_mail)
     >>> print(mail['Message-ID'])
     <test1>
 
@@ -90,7 +90,7 @@ Since we didn't delete the mail, it's still in there:
     >>> len(mails)
     2
     >>> id, raw_mail = mails[0]
-    >>> mail = message_from_bytes(raw_mail)
+    >>> mail = email.message_from_bytes(raw_mail)
     >>> print(mail['Message-ID'])
     <test1>
 
diff --git a/lib/lp/services/mail/doc/sending-mail.txt b/lib/lp/services/mail/doc/sending-mail.txt
index de0483f..b520983 100644
--- a/lib/lp/services/mail/doc/sending-mail.txt
+++ b/lib/lp/services/mail/doc/sending-mail.txt
@@ -17,10 +17,10 @@ The mail get sent when the transaction gets commited:
 
 Now let's look at the sent email:
 
-    >>> from lp.services.compat import message_from_bytes
+    >>> import email
     >>> from lp.services.mail import stub
     >>> from_addr, to_addr, raw_message = stub.test_emails.pop()
-    >>> msg = message_from_bytes(raw_message)
+    >>> msg = email.message_from_bytes(raw_message)
     >>> msg['To']
     'test@xxxxxxxxxxxxx'
     >>> msg['From']
@@ -52,7 +52,7 @@ the person's name is encoded properly.
 
     >>> transaction.commit()
     >>> from_addr, to_addr, raw_message = stub.test_emails.pop()
-    >>> msg = message_from_bytes(raw_message)
+    >>> msg = email.message_from_bytes(raw_message)
     >>> msg['To']
     'test@xxxxxxxxxxxxx'
     >>> msg['From']
@@ -86,7 +86,7 @@ simple_sendmail_from_person uses the Person's preferred email address:
     >>> transaction.commit()
     >>> found = False
     >>> for from_addr, to_addr, raw_message in stub.test_emails:
-    ...     msg = message_from_bytes(raw_message)
+    ...     msg = email.message_from_bytes(raw_message)
     ...     if msg['From'] == 'Sample Person <testing@xxxxxxxxxxxxx>':
     ...         found = True
     >>> assert found
@@ -109,7 +109,7 @@ the header will appear more than once in the output message.
     >>> transaction.commit()
 
     >>> from_addr, to_addr, raw_message = stub.test_emails.pop()
-    >>> msg = message_from_bytes(raw_message)
+    >>> msg = email.message_from_bytes(raw_message)
     >>> msg["X-Foo"]
     'test'
     >>> msg.get_all("X-Bar")
@@ -129,7 +129,7 @@ only.
 Now let's look at the sent email again.
 
     >>> from_addr, to_addr, raw_message = stub.test_emails.pop()
-    >>> msg = message_from_bytes(raw_message)
+    >>> msg = email.message_from_bytes(raw_message)
 
     >>> from email.header import decode_header
     >>> subject_str, charset = decode_header(msg['Subject'])[0]
@@ -154,7 +154,7 @@ contain non-ASCII characters:
     >>> transaction.commit()
 
     >>> from_addr, to_addr, raw_message = stub.test_emails.pop()
-    >>> msg = message_from_bytes(raw_message)
+    >>> msg = email.message_from_bytes(raw_message)
 
     >>> from email.utils import parseaddr
     >>> from_name_encoded, from_addr = parseaddr(msg['From'])
@@ -185,7 +185,7 @@ surrounded by quotes and quoted if necessary:
     >>> transaction.commit()
 
     >>> from_addr, to_addr, raw_message = stub.test_emails.pop()
-    >>> msg = message_from_bytes(raw_message)
+    >>> msg = email.message_from_bytes(raw_message)
     >>> parseaddr(msg['From'])
     ('Foo [Baz] " Bar', 'foo.bar@xxxxxxxxxxxxx')
 
@@ -244,7 +244,7 @@ The message is the same as the one from the simple_sendmail test except
 that the precedence header was not added.
 
     >>> from_addr, to_addr, raw_message = stub.test_emails.pop()
-    >>> msg = message_from_bytes(raw_message)
+    >>> msg = email.message_from_bytes(raw_message)
     >>> msg['To']
     'test@xxxxxxxxxxxxx'
     >>> msg['From']
@@ -282,7 +282,7 @@ provide better bounce handling.
 
     >>> from lp.services.config import config
     >>> from_addr, to_add, raw_message = stub.test_emails.pop()
-    >>> sent_msg = message_from_bytes(raw_message)
+    >>> sent_msg = email.message_from_bytes(raw_message)
     >>> sent_msg['Return-Path'] == config.canonical.bounce_address
     True
     >>> sent_msg['Errors-To'] == config.canonical.bounce_address
@@ -301,7 +301,7 @@ It's possible to set Return-Path manually if needed.
     >>> transaction.commit()
 
     >>> from_addr, to_add, raw_message = stub.test_emails.pop()
-    >>> sent_msg = message_from_bytes(raw_message)
+    >>> sent_msg = email.message_from_bytes(raw_message)
     >>> sent_msg['Return-Path']
     '<>'
 
@@ -322,7 +322,7 @@ are ignored.
     ...     print(to_addr)
     no-priv@xxxxxxxxxxxxx
 
-    >>> sent_msg = message_from_bytes(raw_message)
+    >>> sent_msg = email.message_from_bytes(raw_message)
     >>> sent_msg['To']
     'test@xxxxxxxxxxxxx'
     >>> sent_msg['CC']
@@ -332,7 +332,7 @@ Since sendmail() gets the addresses to send to from the email header,
 it needs to take care of unfolding the headers, so that they don't
 contain any line breaks.
 
-    >>> folded_message = message_from_bytes(b"""Subject: required
+    >>> folded_message = email.message_from_bytes(b"""Subject: required
     ... From: Not used
     ...  <from.address@xxxxxxxxxxx>
     ... To: To Address
diff --git a/lib/lp/services/mail/notification.py b/lib/lp/services/mail/notification.py
index 1d55202..9704416 100644
--- a/lib/lp/services/mail/notification.py
+++ b/lib/lp/services/mail/notification.py
@@ -10,13 +10,13 @@ __all__ = [
 
 
 from difflib import unified_diff
+import email
 from email.mime.message import MIMEMessage
 from email.mime.multipart import MIMEMultipart
 from email.mime.text import MIMEText
 import re
 
 from lp.bugs.mail.bugnotificationbuilder import get_bugmail_error_address
-from lp.services.compat import message_from_bytes
 from lp.services.config import config
 from lp.services.mail.helpers import get_email_template
 from lp.services.mail.mailwrapper import MailWrapper
@@ -72,7 +72,7 @@ def send_process_error_notification(to_address, subject, error_msg,
     original_msg_str = bytes(original_msg)
     if len(original_msg_str) > max_return_size:
         truncated_msg_str = original_msg_str[:max_return_size]
-        original_msg = message_from_bytes(truncated_msg_str)
+        original_msg = email.message_from_bytes(truncated_msg_str)
     msg.attach(MIMEMessage(original_msg))
     sendmail(msg)
 
diff --git a/lib/lp/services/mail/signedmessage.py b/lib/lp/services/mail/signedmessage.py
index 02eeb90..732a397 100644
--- a/lib/lp/services/mail/signedmessage.py
+++ b/lib/lp/services/mail/signedmessage.py
@@ -11,12 +11,12 @@ __all__ = [
     'strip_pgp_signature',
     ]
 
+import email
 from email.message import Message
 import re
 
 from zope.interface import implementer
 
-from lp.services.compat import message_from_bytes
 from lp.services.mail.interfaces import ISignedMessage
 
 
@@ -42,7 +42,7 @@ def signed_message_from_bytes(buf):
     It makes sure that the SignedMessage instance has access to the
     parsed bytes.
     """
-    msg = message_from_bytes(buf, _class=SignedMessage)
+    msg = email.message_from_bytes(buf, _class=SignedMessage)
     msg.parsed_bytes = buf
     return msg
 
diff --git a/lib/lp/services/mail/stub.py b/lib/lp/services/mail/stub.py
index b63265c..c63d2fd 100644
--- a/lib/lp/services/mail/stub.py
+++ b/lib/lp/services/mail/stub.py
@@ -5,16 +5,14 @@
 
 __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,
-    )
+from lp.services.compat import message_as_bytes
 
 
 @implementer(IMailer)
@@ -41,7 +39,7 @@ class StubMailer:
         # headers that determine the actual To: address. However, this might
         # be required to bypass some spam filters.
         if self.rewrite:
-            message = message_from_bytes(message)
+            message = email.message_from_bytes(message)
             message['X-Orig-To'] = message['To']
             message['X-Orig-Cc'] = message['Cc']
             message['X-Orig-From'] = message['From']
diff --git a/lib/lp/services/mail/tests/incomingmail.txt b/lib/lp/services/mail/tests/incomingmail.txt
index 6fa33ca..bd77caa 100644
--- a/lib/lp/services/mail/tests/incomingmail.txt
+++ b/lib/lp/services/mail/tests/incomingmail.txt
@@ -301,8 +301,7 @@ to the user, citing the OOPS ID, with the original message attached.
 
 OOPS notifications work even if the From: address isn't properly MIME-encoded.
 
-    >>> from lp.services.compat import message_from_bytes
-    >>> msg = message_from_bytes(
+    >>> msg = email.message_from_bytes(
     ... u"""From: \u05D1 <bet@xxxxxxxxxxxxx>
     ... To: launchpad@xxxxxxxx
     ... X-Launchpad-Original-To: launchpad@xxxxxxxx
diff --git a/lib/lp/services/mail/tests/test_stub.py b/lib/lp/services/mail/tests/test_stub.py
index 85a549f..e1af47a 100644
--- a/lib/lp/services/mail/tests/test_stub.py
+++ b/lib/lp/services/mail/tests/test_stub.py
@@ -15,9 +15,9 @@ def test_simple_sendmail():
     r"""
     Send an email (faked by TestMailer - no actual email is sent)
 
+    >>> from email import message_from_bytes
     >>> from email.mime.text import MIMEText
     >>> import transaction
-    >>> from lp.services.compat import message_from_bytes
     >>> from lp.services.mail import stub
     >>> from lp.services.mail.sendmail import simple_sendmail
 
diff --git a/lib/lp/services/messages/model/message.py b/lib/lp/services/messages/model/message.py
index f6638b2..a2943ea 100644
--- a/lib/lp/services/messages/model/message.py
+++ b/lib/lp/services/messages/model/message.py
@@ -11,6 +11,7 @@ __all__ = [
     ]
 
 from datetime import datetime
+import email
 from email.header import (
     decode_header,
     make_header,
@@ -57,7 +58,6 @@ from lp.registry.interfaces.person import (
     PersonCreationRationale,
     validate_public_person,
     )
-from lp.services.compat import message_from_bytes
 from lp.services.config import config
 from lp.services.database.constants import UTC_NOW
 from lp.services.database.datetimecol import UtcDateTimeCol
@@ -376,7 +376,7 @@ class MessageSet:
         # Parse the raw message into an email.message.Message instance,
         # if we haven't been given one already.
         if parsed_message is None:
-            parsed_message = message_from_bytes(email_message)
+            parsed_message = email.message_from_bytes(email_message)
 
         # We could easily generate a default, but a missing message-id
         # almost certainly means a developer is using this method when
diff --git a/lib/lp/services/verification/doc/logintoken.txt b/lib/lp/services/verification/doc/logintoken.txt
index 9a8587c..201c15a 100644
--- a/lib/lp/services/verification/doc/logintoken.txt
+++ b/lib/lp/services/verification/doc/logintoken.txt
@@ -49,7 +49,7 @@ Let's create a new LoginToken to confirm an email address for foobar.
 The email does not have a precedence header because the user implicitly
 requested it to complete their task.
 
-    >>> from lp.services.compat import message_from_bytes
+    >>> from email import message_from_bytes
 
     >>> msg = message_from_bytes(found_msg)
     >>> print(msg['Precedence'])
diff --git a/lib/lp/services/verification/tests/logintoken.py b/lib/lp/services/verification/tests/logintoken.py
index 4f7d3ee..fda3d6a 100644
--- a/lib/lp/services/verification/tests/logintoken.py
+++ b/lib/lp/services/verification/tests/logintoken.py
@@ -3,16 +3,15 @@
 
 """Helper functions for logintoken-related tests."""
 
+import email
 import re
 
 import six
 
-from lp.services.compat import message_from_bytes
-
 
 def get_token_url_from_email(email_msg):
     """Return the logintoken URL contained in the given email message."""
-    msg = message_from_bytes(email_msg)
+    msg = email.message_from_bytes(email_msg)
     return get_token_url_from_bytes(msg.get_payload(decode=True))
 
 
diff --git a/lib/lp/testing/mail_helpers.py b/lib/lp/testing/mail_helpers.py
index 16bdcc2..23112fe 100644
--- a/lib/lp/testing/mail_helpers.py
+++ b/lib/lp/testing/mail_helpers.py
@@ -5,6 +5,7 @@
 
 __metaclass__ = type
 
+import email
 import operator
 
 import six
@@ -18,7 +19,6 @@ 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
@@ -44,7 +44,7 @@ def pop_notifications(sort_key=None, commit=True):
 
     notifications = []
     for fromaddr, toaddrs, raw_message in stub.test_emails:
-        notification = message_from_bytes(raw_message)
+        notification = email.message_from_bytes(raw_message)
         notification['X-Envelope-To'] = ', '.join(toaddrs)
         notification['X-Envelope-From'] = fromaddr
         notifications.append(notification)
diff --git a/lib/lp/translations/doc/translations-export-to-branch.txt b/lib/lp/translations/doc/translations-export-to-branch.txt
index c8b74b0..76b63db 100644
--- a/lib/lp/translations/doc/translations-export-to-branch.txt
+++ b/lib/lp/translations/doc/translations-export-to-branch.txt
@@ -223,8 +223,8 @@ The Launchpad UI allows users to register branches in the Launchpad
 database without populating them in bzr.  Exporting to such a branch
 won't work, so we email a notification to the branch owner.
 
+    >>> import email
     >>> from lp.codehosting.vfs import get_rw_server
-    >>> from lp.services.compat import message_from_bytes
     >>> from lp.services.mail import stub
     >>> from lp.testing.factory import (
     ...     remove_security_proxy_and_shout_at_engineer)
@@ -255,7 +255,7 @@ won't work, so we email a notification to the branch owner.
     >>> transaction.commit()
 
     >>> sender, recipients, body = stub.test_emails.pop()
-    >>> message = message_from_bytes(body)
+    >>> message = email.message_from_bytes(body)
     >>> print(message['Subject'])
     Launchpad: translations branch has not been set up.