Chapter 12 ■ Building and parsing e-Mail
228
• add_alternative() can then be called zero or more times to provide other renderings of your
e-mail message. If the body is HTML, for example, you might provide a plain-text alternative
rendering for less-capable e-mail clients.
• add_attachment() can be called zero or more times to supply any attachments like PDF
documents, images, or spreadsheets that should accompany the message. Each attachment
traditionally specifies a default file name for use if the recipient asks their e-mail client to save
the attachment.
Looking back, you can see that Listing 12-2 followed the above procedure exactly—it called set_content() as its
first step, then simply elected to call each of the other three methods zero times. The result was the simplest possible
e-mail structure, presenting a unified body with no subparts.
But how does e-mail look when things get more complicated? Listing 12-3 has been designed to give the answer.
Listing 12-3. Building a MIME-Powered E-Mail with HTML, an Inline Image, and Attachments
#!/usr/bin/env python3
Foundations of Python Network Programming, Third Edition
https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter12/build_mime_email.py
import argparse, email.message, email.policy, email.utils, mimetypes, sys
plain = """Hello,
This is a MIME message from Chapter 12.
- Anonymous"""
html = """
Hello,
This is a test message from Chapter 12.
- Anonymous
"""img = """
This is the smallest possible blue GIF:
"""
Tiny example GIF from http://www.perlmonks.org/?node_id=7974
blue_dot = (b'GIF89a1010\x900000\xff000,000010100\x02\x02\x0410;'
.replace(b'0', b'\x00').replace(b'1', b'\x01'))
def main(args):
message = email.message.EmailMessage(email.policy.SMTP)
message['To'] = 'Test Recipient [email protected]'
message['From'] = 'Test Sender [email protected]'
message['Subject'] = 'Foundations of Python Network Programming'
message['Date'] = email.utils.formatdate(localtime=True)
message['Message-ID'] = email.utils.make_msgid()
if not args.i:
message.set_content(html, subtype='html')
message.add_alternative(plain)
else:
cid = email.utils.make_msgid() # RFC 2392: must be globally unique!
message.set_content(html + img.format(cid.strip('<>')), subtype='html')