How can I get an email message's text content using Python? How can I get an email message's text content using Python? python python

How can I get an email message's text content using Python?


In a multipart e-mail, email.message.Message.get_payload() returns a list with one item for each part. The easiest way is to walk the message and get the payload on each part:

import emailmsg = email.message_from_string(raw_message)for part in msg.walk():    # each part is a either non-multipart, or another multipart message    # that contains further parts... Message is organized like a tree    if part.get_content_type() == 'text/plain':        print part.get_payload() # prints the raw text

For a non-multipart message, no need to do all the walking. You can go straight to get_payload(), regardless of content_type.

msg = email.message_from_string(raw_message)msg.get_payload()

If the content is encoded, you need to pass None as the first parameter to get_payload(), followed by True (the decode flag is the second parameter). For example, suppose that my e-mail contains an MS Word document attachment:

msg = email.message_from_string(raw_message)for part in msg.walk():    if part.get_content_type() == 'application/msword':        name = part.get_param('name') or 'MyDoc.doc'        f = open(name, 'wb')        f.write(part.get_payload(None, True)) # You need None as the first param                                              # because part.is_multipart()                                               # is False        f.close()

As for getting a reasonable plain-text approximation of an HTML part, I've found that html2text works pretty darn well.


Flat is better than nested ;)

from email.mime.multipart import MIMEMultipartassert isinstance(msg, MIMEMultipart)for _ in [k.get_payload() for k in msg.walk() if k.get_content_type() == 'text/plain']:    print _


To add on @Jarret Hardie's excellent answer:

I personally like to transform that kind of data structures to a dictionary that I can reuse later, so something like this where the content_type is the key and the payload is the value:

import email[...]email_message = {    part.get_content_type(): part.get_payload()    for part in email.message_from_bytes(raw_email).walk()}print(email_message["text/plain"])