"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()" 方法的任何经过代理转义编码的文本写入到
   *file-like object* *outfp*。 *outfp* 必须支持接受二进制数据的
   "write" 方法。

   如果可选的 *mangle_from_* 为 "True"，则会将一个 ">" 字符放到消息体
   中恰好以字符串 ""From "" 打头，即开头文本为 "From" 加一个空格的任何
   行的前面。 *mangle_from_* 默认为 *policy* 的 "mangle_from_" 设置值
   (对于 "compat32" 策略为 "True" 而对于所有其他策略则为 "False")。
   *mangle_from_* 被设计为在当消息以 Unix mbox 格式存储时使用 (参见
   "mailbox" 和 WHY THE CONTENT-LENGTH FORMAT IS BAD).

   If *maxheaderlen* is not "None", refold any header lines that are
   longer than *maxheaderlen*, or if "0", do not rewrap any headers.
   If *maxheaderlen* is "None" (the default), wrap headers and other
   message lines according to the *policy* settings.

   如果指定了 *policy*，则使用该策略来控制消息的生成。如果 *policy* 为
   "None" (默认值)，则使用与传递给 "flatten" 的 "Message" 或
   "EmailMessage" 对象相关联的策略来控制消息的生成。 请参阅
   "email.policy" 了解有关 *policy* 所控制内容的详情。

   Added in version 3.2.

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

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

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

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

      如果 "policy" 选项 "cte_type" 为 "8bit" （默认值），则会将未被修
      改的原始已解析消息中的任何标头拷贝到输出，其中会重新生成与原始数
      据相同的高比特位组字节数据，并保留具有它们的任何消息体部分的非
      ASCII *Content-Transfer-Encoding*。如果 "cte_type" 为 "7bit"，则
      会根据需要使用兼容 ASCII 的 *Content-Transfer-Encoding* 来转换高
      比特位组字节数据。也就是说，将具有非 ASCII *Content-Transfer-
      Encoding* (*Content-Transfer-Encoding: 8bit*) 的部分转换为兼容
      ASCII 的 *Content-Transfer-Encoding*，并使用 MIME "unknown-8bit"
      字符集来编码标头中不符合 RFC 的非 ASCII 字节数据，以使其符合 RFC
      。

      如果 *unixfrom* 为 "True"，则会在根消息对象的第一个 **RFC 5322**
      标头之前打印 Unix mailbox 格式 (参见 "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"。

Because strings cannot represent binary data, the "Generator" class
must convert any binary data in any message it flattens to an ASCII
compatible format, by converting them to an ASCII compatible *Content-
Transfer-Encoding*.  Using the terminology of the email RFCs, you can
think of this as "Generator" serializing to an I/O stream that is not
"8 bit clean".  In other words, most applications will want to be
using "BytesGenerator", and not "Generator".

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

   返回一个 "Generator"，它将把提供给 "flatten()" 方法的任何消息，或者
   提供给 "write()" 方法的任何文本写入到 *file-like object* *outfp*。
   *outfp* 必须支持接受字符串数据的 "write" 方法。

   如果可选的 *mangle_from_* 为 "True"，则会将一个 ">" 字符放到消息体
   中恰好以字符串 ""From "" 打头，即开头文本为 "From" 加一个空格的任何
   行的前面。 *mangle_from_* 默认为 *policy* 的 "mangle_from_" 设置值
   (对于 "compat32" 策略为 "True" 而对于所有其他策略则为 "False")。
   *mangle_from_* 被设计为在当消息以 Unix mbox 格式存储时使用 (参见
   "mailbox" 和 WHY THE CONTENT-LENGTH FORMAT IS BAD).

   If *maxheaderlen* is not "None", refold any header lines that are
   longer than *maxheaderlen*, or if "0", do not rewrap any headers.
   If *maxheaderlen* is "None" (the default), wrap headers and other
   message lines according to the *policy* settings.

   如果指定了 *policy*，则使用该策略来控制消息的生成。如果 *policy* 为
   "None" (默认值)，则使用与传递给 "flatten" 的 "Message" 或
   "EmailMessage" 对象相关联的策略来控制消息的生成。 请参阅
   "email.policy" 了解有关 *policy* 所控制内容的详情。

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

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

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

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

      如果 "policy" 选项 "cte_type" 为 "8bit"，则视同选项被设为 "7bit"
      来生成消息。 （这是必需的，因为字符串无法表示非 ASCII 字节数据。
      ）将使用兼容 ASCII 的 *Content-Transfer-Encoding* 按需转换任何具
      有高比特位组的字节数据。也就是说，将具有非 ASCII *Content-
      Transfer-Encoding* (*Content-Transfer-Encoding: 8bit*) 的部分转
      换为兼容 ASCII 的 *Content-Transfer-Encoding*，并使用 MIME
      "unknown-8bit" 字符集来编码标头中不符合 RFC 的非 ASCII 字节数据
      ，以使其符合 RFC.

      如果 *unixfrom* 为 "True"，则会在根消息对象的第一个 **RFC 5322**
      标头之前打印 Unix mailbox 格式 (参见 "mailbox") 所使用的封包标头
      分隔符。 如果根对象没有封包标头，则会创建一个标准标头。 默认值为
      "False"。 请注意对于子部分来说，不会打印任何封包标头。

      如果 *linesep* 不为 "None"，则会将其用作扁平化消息的所有行之间的
      分隔符。如果 *linesep* 为 "None" （默认值），则使用在 *policy*
      中指定的值。

      在 3.2 版本发生变更: 添加了对重编码 "8bit" 消息体的支持，以及
      *linesep* 参数。

   clone(fp)

      返回此 "Generator" 实例的独立克隆，具有完全相同的选项设置，而
      *fp* 为新的 *outfp*。

   write(s)

      将 *s* 写入到传给 "Generator" 的构造器的 *outfp* 的 *write* 方法
      。这为 "Generator" 实例提供了刚好足够可用于 "print()" 函数的文件
      类 API。

作为一个便捷工具，"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*:

      "[忽略消息的非文本 (%(type)s) 部分，文件名 %(filename)s]"

   Optional *mangle_from_* and *maxheaderlen* are as with the
   "Generator" base class.

-[ 备注 ]-

[1] 此语句假定你使用了正确的 "unixfrom" 设置，并且没有针对自动调整的
    "email.policy" 设置调用（例如，"refold_source" 必须为 "none"，这 *
    不是* 默认值）。这也不是 100% 为真的，因为如果消息不遵循 RFC 标准
    则有时实际原始文本的信息会在解析错误恢复时丢失。 目标是在可能的情
    况下修复这些后续的边缘情况。
