11

From my understanding the mbox class in Python 3.6's standard library generates old-style message objects of the type email.message.Message.

The newer class email.message.EmailMessage introduced in 3.4/3.6 offers easier access to the content of the message (via get_content() and get_body()). How can I convert the email.message.Message objects I get from the mbox iterator into email.message.EmailMessage objects?

halloleo
  • 9,216
  • 13
  • 64
  • 122
  • 3
    I was about to ask the same question, but found a solution in the meantime. :) It’s possible to convert the old-style message to a string or bytes and parse it again using the [`email.parser`](https://docs.python.org/3/library/email.parser.html) module (the policy must be set to `email.policy.default`). But a more direct way would be to pass a factory to the `mbox` class. Like this: `mailbox.mbox(path, factory=lambda f: email.message_from_binary_file(f, policy=email.policy.default))` – Manuel Jacob Aug 13 '19 at 05:43
  • @ManuelJacob That's so cool! Indeed using a factory is the best! Works perfectly. Worth while to be made into an answer, I reckon... – halloleo Aug 13 '19 at 07:33

2 Answers2

7

Taking @ManuelJaco's comment I was able to create an mbox instance which contains automatically message objects of the type email.message.EmailMessage:

def make_EmailMessage(f):
    """Factory to create EmailMessage objects instead of Message objects"""
    return email.message_from_binary_file(f, policy=email.policy.default)

mbox = mailbox.mbox(mboxfile, factory=make_EmailMessage)

Note: When iterating over mbox all messages (even messages contained in a message!) are of the email.message.EmailMessage type.

Fato39
  • 746
  • 1
  • 11
  • 26
halloleo
  • 9,216
  • 13
  • 64
  • 122
3

To create an email.message.EmailMessage object, change the policy in parser to email.policy.default.

msg = email.message_from_string(raw_email_string,
                            policy = email.policy.default)