email.generator:生成 MIME 文档

源代码: Lib/email/generator.py


最常见的任务之一是生成由消息对象结构所表示的电子邮件消息的扁平化(序列化)版本。如果你想要通过 smtplib.SMTP.sendmail() 发送消息,或者在控制台上打印消息,就需要这样做。将一个消息对象结构并生成其序列化表示形式正是生成器类的工作。

email.parser 模块一样,你不仅限于使用捆绑的生成器;你也可以自己从头编写一个。但是,捆绑的生成器知道如何以符合标准的方式生成大多数电子邮件,应能很好地处理 MIME 和非 MIME 电子邮件消息,并且其设计使得面向字节的解析和生成操作是互逆的,前提是两者使用相同的非转换 policy。也就是说,通过 BytesParser 类解析序列化的字节流,然后使用 BytesGenerator 重新生成序列化的字节流,应能产生与输入完全相同的输出 [1]。(另一方面,在通过程序构建的 EmailMessage 上使用生成器,可能会因为填充默认值而导致 EmailMessage 对象发生改变。)

可使用 Generator 类将消息扁平化为文本(而非二进制)的序列化表示,但由于 Unicode 无法直接表示二进制数据,消息必须转换为只包含 ASCII 字符的内容,这通过使用标准的电子邮件 RFC 内容传输编码技术,来为那些“非 8 位纯净”的信道传输电子邮件进行编码。

为了支持对 SMIME 签名的消息进行可重现的处理,Generator 对于类型为 multipart/signed 的消息部分及其所有子部分,会禁用标头折叠。

class email.generator.BytesGenerator(outfp, mangle_from_=None, maxheaderlen=None, *, policy=None)

返回一个 BytesGenerator 对象,该对象会将提供给 flatten() 方法的任何消息,或提供给 write() 方法的任何经过 surrogateescape 编码的文本,写入到 文件类对象 *outfp* 中。 *outfp* 必须支持一个接受二进制数据的 write 方法。

如果可选参数 *mangle_from_* 为 True,则在正文中任何以确切字符串 "From "(即 From 后跟一个空格)开头的行前面加上一个 > 字符。*mangle_from_* 默认为 *policy* 的 mangle_from_ 设置值(对于 compat32 策略,该值为 True,对于所有其他策略则为 False)。 *mangle_from_* 旨在用于消息以 Unix mbox 格式存储的情况(参见 mailboxWHY THE CONTENT-LENGTH FORMAT IS BAD)。

如果 *maxheaderlen* 不为 None,则重新折叠任何长度超过 *maxheaderlen* 的标头行;如果为 0,则不重新换行任何标头。如果 *maxheaderlen* 为 None(默认值),则根据 *policy* 设置来换行标头和其他消息行。

如果指定了 *policy*,则使用该策略来控制消息生成。如果 *policy* 为 None(默认值),则使用传递给 flattenMessageEmailMessage 对象关联的策略来控制消息生成。有关 *policy* 控制内容的详细信息,请参阅 email.policy

在 3.2 版本加入。

在 3.3 版本发生变更: 添加了 *policy* 关键字。

在 3.6 版本发生变更: *mangle_from_* 和 *maxheaderlen* 参数的默认行为将遵循策略。

flatten(msg, unixfrom=False, linesep=None)

将以 *msg* 为根的消息对象结构的文本表示打印到创建 BytesGenerator 实例时指定的输出文件。

如果 policy 选项 cte_type8bit (默认值),则将原始已解析消息中未被修改的任何标头复制到输出中,并保留高位设置的字节与原始消息一致,同时保留任何正文部分的非 ASCII Content-Transfer-Encoding。如果 cte_type7bit,则根据需要使用与 ASCII 兼容的 Content-Transfer-Encoding 转换高位设置的字节。也就是说,将具有非 ASCII Content-Transfer-EncodingContent-Transfer-Encoding: 8bit)的部分转换为与 ASCII 兼容的 Content-Transfer-Encoding,并使用 MIME unknown-8bit 字符集对标头中不符合 RFC 的非 ASCII 字节进行编码,从而使其符合 RFC 标准。

如果 *unixfrom* 为 True,则在根消息对象的第一个 RFC 5322 标头之前打印 Unix 邮箱格式使用的信封头分隔符(见 mailbox)。如果根对象没有信封头,则创建一个标准的信封头。默认值为 False。请注意,对于子部分,从不打印信封头。

如果 *linesep* 不为 None,则将其用作扁平化消息所有行之间的分隔符。如果 *linesep* 为 None(默认值),则使用 *policy* 中指定的值。

clone(fp)

返回此 BytesGenerator 实例的一个独立克隆,其选项设置完全相同,并将 *fp* 作为新的 *outfp*。

write(s)

使用 ASCII 编解码器和 surrogateescape 错误处理程序对 *s* 进行编码,并将其传递给传入 BytesGenerator 构造函数的 *outfp* 的 *write* 方法。

为了方便起见,EmailMessage 提供了 as_bytes()bytes(aMessage) (也即 __bytes__()) 方法,这简化了消息对象的序列化二进制表示的生成。更多详情请参阅 email.message

由于字符串无法表示二进制数据,Generator 类必须将其扁平化的任何消息中的所有二进制数据转换为 ASCII 兼容格式,方法是将其转换为 ASCII 兼容的 Content-Transfer-Encoding。用电子邮件 RFC 的术语来说,可以认为 Generator 是序列化到一个“非 8 位纯净”的 I/O 流。换句话说,大多数应用程序会希望使用 BytesGenerator,而不是 Generator

class email.generator.Generator(outfp, mangle_from_=None, maxheaderlen=None, *, policy=None)

返回一个 Generator 对象,该对象会将提供给 flatten() 方法的任何消息,或提供给 write() 方法的任何文本,写入到 文件类对象 *outfp* 中。 *outfp* 必须支持一个接受字符串数据的 write 方法。

如果可选参数 *mangle_from_* 为 True,则在正文中任何以确切字符串 "From "(即 From 后跟一个空格)开头的行前面加上一个 > 字符。*mangle_from_* 默认为 *policy* 的 mangle_from_ 设置值(对于 compat32 策略,该值为 True,对于所有其他策略则为 False)。 *mangle_from_* 旨在用于消息以 Unix mbox 格式存储的情况(参见 mailboxWHY THE CONTENT-LENGTH FORMAT IS BAD)。

如果 *maxheaderlen* 不为 None,则重新折叠任何长度超过 *maxheaderlen* 的标头行;如果为 0,则不重新换行任何标头。如果 *maxheaderlen* 为 None(默认值),则根据 *policy* 设置来换行标头和其他消息行。

如果指定了 *policy*,则使用该策略来控制消息生成。如果 *policy* 为 None(默认值),则使用传递给 flattenMessageEmailMessage 对象关联的策略来控制消息生成。有关 *policy* 控制内容的详细信息,请参阅 email.policy

在 3.3 版本发生变更: 添加了 *policy* 关键字。

在 3.6 版本发生变更: *mangle_from_* 和 *maxheaderlen* 参数的默认行为将遵循策略。

flatten(msg, unixfrom=False, linesep=None)

将以 *msg* 为根的消息对象结构的文本表示打印到创建 Generator 实例时指定的输出文件。

如果 policy 选项 cte_type8bit,则生成消息时会如同该选项被设置为 7bit 一样处理。(这是必需的,因为字符串无法表示非 ASCII 字节。)根据需要使用与 ASCII 兼容的 Content-Transfer-Encoding 转换高位设置的字节。也就是说,将具有非 ASCII Content-Transfer-EncodingContent-Transfer-Encoding: 8bit)的部分转换为与 ASCII 兼容的 Content-Transfer-Encoding,并使用 MIME unknown-8bit 字符集对标头中不符合 RFC 的非 ASCII 字节进行编码,从而使其符合 RFC 标准。

如果 *unixfrom* 为 True,则在根消息对象的第一个 RFC 5322 标头之前打印 Unix 邮箱格式使用的信封头分隔符(见 mailbox)。如果根对象没有信封头,则创建一个标准的信封头。默认值为 False。请注意,对于子部分,从不打印信封头。

如果 *linesep* 不为 None,则将其用作扁平化消息所有行之间的分隔符。如果 *linesep* 为 None(默认值),则使用 *policy* 中指定的值。

在 3.2 版本发生变更: 增加了对重新编码 8bit 消息正文的支持,以及 *linesep* 参数。

clone(fp)

返回此 Generator 实例的一个独立克隆,其选项完全相同,并将 *fp* 作为新的 *outfp*。

write(s)

将 *s* 写入到传递给 Generator 构造函数的 *outfp* 的 *write* 方法。这为 Generator 实例提供了足够的文件类 API,使其可以在 print() 函数中使用。

为了方便起见,EmailMessage 提供了 as_string()str(aMessage) (也即 __str__()) 方法,这简化了消息对象的格式化字符串表示的生成。更多详情请参阅 email.message

email.generator 模块还提供了一个派生类 DecodedGenerator,它类似于 Generator 基类,不同之处在于非 text 部分不会被序列化,而是在输出流中用一个根据部分信息填充的模板派生出的字符串来表示。

class email.generator.DecodedGenerator(outfp, mangle_from_=None, maxheaderlen=None, fmt=None, *, policy=None)

行为与 Generator 类似,不同之处在于,对于传递给 Generator.flatten() 的消息的任何子部分,如果子部分的主类型是 text,则打印该子部分的解码后的有效负载;如果主类型不是 text,则不打印它,而是使用该部分的信息填充字符串 *fmt*,并打印填充后的结果字符串。

要填充 *fmt*,执行 fmt % part_info,其中 part_info 是一个由以下键和值组成的字典:

  • type – 非 text 部分的完整 MIME 类型

  • maintype – 非 text 部分的主 MIME 类型

  • subtype – 非 text 部分的子 MIME 类型

  • filename – 非 text 部分的文件名

  • description – 与非 text 部分关联的描述

  • encoding – 非 text 部分的内容传输编码

如果 *fmt* 为 None,则使用以下默认的 *fmt*

“[Non-text (%(type)s) part of message omitted, filename %(filename)s]”

可选的 *_mangle_from_* 和 *maxheaderlen* 与 Generator 基类中的相同。

脚注