Skip to main content

Lib/email/message.py (part 2)

Source:

cpython 3.14 @ ab2d84fe1023/Lib/email/message.py

This annotation covers the 3.6+ EmailMessage API (policy-aware) and multipart construction. See lib_email_detail for Message, headers, payload, and MIME basics.

Map

LinesSymbolRole
1-80MIMEPartBase for policy-aware message parts
81-200get_body / get_contentRetrieve decoded body (text, html, attachments)
201-350make_alternativeConstruct multipart/alternative container
351-500make_mixedConstruct multipart/mixed container
501-650EmailMessageTop-level message with convenience methods
651-800as_string / as_bytesSerialize to text/bytes using a Generator
801-1000policyEmailPolicy, SMTP, SMTPUTF8, HTTP policy objects

Reading

get_body

# CPython: Lib/email/message.py:430 MIMEPart.get_body
def get_body(self, preferencelist=('related', 'html', 'plain')):
"""Find the best text body part according to preference."""
# Walks the MIME tree, preferring related > html > plain
for pref in preferencelist:
for part in self.walk():
if part.get_content_maintype() == 'multipart':
continue
if part.get_content_subtype() == pref:
return part
return None

get_content

# CPython: Lib/email/message.py:480 MIMEPart.get_content
def get_content(self, *args, content_manager=None, **kw):
"""Return decoded content of this part."""
if content_manager is None:
content_manager = self.policy.content_manager
return content_manager.get_content(self, *args, **kw)

The content manager handles charset decoding and base64/quoted-printable decoding transparently.

make_alternative

# CPython: Lib/email/message.py:530 MIMEPart.make_alternative
def make_alternative(self, _subtype='alternative', policy=None):
"""Convert this message into a multipart/alternative container."""
keep_headers, payload = self._make_multipart(
_subtype, [self], policy)
del self._payload
del self._headers[:]
self._headers[:] = keep_headers
self.attach(payload)

msg.make_alternative() is used when adding an HTML version to an existing plain-text message.

as_string

# CPython: Lib/email/message.py:680 Message.as_string
def as_string(self, unixfrom=False, maxheaderlen=None, policy=None):
"""Return the entire message as a string."""
from email.generator import Generator
policy = self.policy if policy is None else self.policy.clone(policy)
fp = StringIO()
g = Generator(fp, mangle_from_=False, maxheaderlen=maxheaderlen,
policy=policy)
g.flatten(self, unixfrom=unixfrom)
return fp.getvalue()

Policy

# CPython: Lib/email/_header_value_parser.py (policy anatomy)
# email.policy.default — modern API, utf-8 aware
# email.policy.SMTP — CRLF line endings, max 998 chars/line
# email.policy.compat32 — legacy compat32 (old Message API default)

EmailMessage uses policy=email.policy.default by default.

gopy notes

email is pure Python. get_content calls ContentManager.get_content which uses policy.content_manager. as_bytes uses BytesGenerator, which calls write() on a BytesIO. All these are pure Python and work with gopy's io.StringIO / io.BytesIO.