Chapter 12 ■ Building and parsing e-Mail
233
• method(..., cte='quoted-printable')
All of these methods seem to default to one of only two content transfer encodings. Safe 7-bit
information is included verbatim in the e-mail using bare and readable ASCII encoding,
while anything more dangerous gets encoded using Base64. If you are ever in a situation
where you are frequently inspecting incoming or outgoing e-mails manually, you might
find the latter option unfortunate—it means, for example, that a text part with one single
Unicode character inside it will get turned into completely unreadable Base64 rubbish. You
can override the choice of encoding with the cte keyword. In particular, you might find
the quoted-printable encoding attractive: ASCII characters are preserved verbatim in the
encoded e-mail, and escape sequences are used for any bytes that have their eighth bit set.
• add_related(..., cid='<Content ID>')
Usually, you will want each related part to be identified by a custom content ID so that
your HTML can link to it. The content ID should always be surrounded by angle brackets
in your call, but have them removed when you actually form the cid: link in your HTML. It
is notable that content IDs are supposed to be globally unique—every content ID you ever
include in a document is supposed to be unique among all content IDs ever included in an
e-mail in the entire history of the world! Listing 12-3 uses make_msgid() because the email
module provides no specific facility for building unique content IDs.
• add_attachment(..., filename='data.csv')
When adding attachments, most e-mail clients (as well as their users) will expect at least a
suggested file name, though of course the e-mail recipient can override this default when
they select “Save” if they choose to.
There are, again, other more complicated versions of these calls for special cases that you can learn about in the official
Python documentation, but these should carry you through the most common situations in building MIME e-mails.
Parsing E-Mail Messages
There are two basic approaches to reading an e-mail message once you have parsed it using one of the functions
in the email module. The simple approach is to assume that the message offers a body and attachments through
standard and customary use of MIME and lets the convenience methods built into EmailMessage help you find them.
The more complex approach is to visit all of the parts and subparts of the message manually and then decide on your
own what they mean and how they might be saved or displayed.
Listing 12-4 illustrates the simple approach. As with saving e-mail messages, it is important to be careful to read
input as bytes and then to hand those bytes to the email module without attempting any decoding step of your own.
Listing 12-4. Asking EmailMessage for the Body and Attachments
#!/usr/bin/env python3
Foundations of Python Network Programming, Third Edition
https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter12/display_email.py
import argparse, email.policy, sys
def main(binary_file):
policy = email.policy.SMTP
message = email.message_from_binary_file(binary_file, policy=policy)
for header in ['From', 'To', 'Date', 'Subject']:
print(header + ':', message.get(header, '(none)'))
print()