19.1.4. email.policy: 策略对象

    源代码:


    email 的主要焦点是按照各种电子邮件和 MIME RFC 的描述来处理电子邮件消息。 但是电子邮件消息的基本格式(一个由名称加冒号加值的标头字段构成的区块,后面再加一个空白行和任意的‘消息体’)是在电子邮件领域以外也获得应用的格式。 这些应用的规则有些与主要电子邮件 RFC 十分接近,有些则很不相同。 即使是操作电子邮件,有时也可能需要打破严格的 RFC 规则,例如生成可与某些并不遵循标准的电子邮件服务器互联的电子邮件,或者是实现希望应用某些破坏标准的操作方式的扩展。

    策略对象给予 email 包处理这些不同用例的灵活性。

    对象封装了一组属性和方法用来在使用期间控制 email 包中各个组件的行为。 Policy 实例可以被传给 email 包中的多个类和方法以更改它们的默认行为。 可设置的值及其默认值如下所述。

    在 email 包中的所有类会使用一个默认的策略。 对于所有 类及相关的便捷函数,还有对于 Message 类来说,它是 策略,通过其对应的预定义实例 compat32 来使用。 这个策略提供了与 Python3.3 版之前的 email 包的完全向下兼容性(在某些情况下,也包括对缺陷的兼容性)。

    传给 的 policy 关键字的默认值是 EmailPolicy 策略,表示为其预定义的实例 。

    在创建 Message 或 对象时,它需要一个策略。 如果消息是由 parser 创建的,则传给该解析器的策略将是它所创建的消息所使用的策略。 如果消息是由程序创建的,则该策略可以在创建它的时候指定。 当消息被传递给 时,生成器默认会使用来自该消息的策略,但你也可以将指定的策略传递给生成器,这将覆盖存储在消息对象上的策略。

    email.parser 类和解析器便捷函数的 policy 关键字的默认值在未来的 Python 版本中 将会改变。 因此在调用任何 模块所描述的类和函数时你应当 总是显式地指定你想要使用的策略

    本文档的第一部分介绍了 Policy 的特性,它是一个 ,定义了所有策略对象包括 compat32 的共有特性。 这些特性包括一些由 email 包内部调用的特定钩子方法,自定义策略可以重载这些方法以获得不同行为。 第二部分描述了实体类 和 Compat32,它们分别实现了提供标准行为和向下兼容行为与特性的钩子。

    实例是不可变的,但它们可以被克隆,接受与类构造器一致的关键字参数并返回一个新的 Policy 实例,新实例是原实例的副本,但具有被改变的指定属性。

    例如,以下代码可以被用来从一个 Unix 系统的磁盘文件中读取电子邮件消息并将其传递给系统的 程序:

    这里我们让 在创建要送入 sendmail's stdin 的二进制字串时使用符合 RFC 的行分隔字符,默认的策略将会使用 \n 行分隔符。

    某些 email 包的方法接受一个 policy 关键字参数,允许为该方法重载策略。 例如,以下代码使用了来自之前示例的 msg 对象的 as_bytes() 方法并使用其运行所在平台的本机行分隔符将消息写入一个文件:

    Policy 对象也可使用附加运算符进行组合来产生一个新策略对象,其设置是被加总对象的非默认值的组合:

    此运算不满足交换律;也就是说对象的添加顺序很重要。 见以下演示:

    class email.policy.Policy(**kw)

    这是所有策略类的 。 它提供了一些简单方法的默认实现,以及不可变特征属性,clone() 方法以及构造器语义的实现。

    可以向策略类的构造器传入各种关键字参数。 可以指定的参数是该类的任何非方法特征属性,以及实体类的任何额外非方法特征属性。 在构造器中指定的值将覆盖相应属性的默认值。

    这个类定义了下列特征属性,因此下列值可以被传给任何策略类的构造器:

    • max_line_length

      序列化输出中任何行的最大长度,不计入行字符的末尾。 默认值为 78,基于 。 值为 0None 表示完全没有行包装。

    • linesep

      用来在序列化输出中确定行的字符串。 默认值为 \n 因为这是 Python 所使用的内部行结束符规范,但 RFC 的要求是 \r\n

    • cte_type

      控制可能要求使用的内容传输编码格式类型。 可能的值包括:

      cte_type 值为 8bit 仅适用于 BytesGenerator 而非 Generator,因为字符串不能包含二进制数据。 如果 Generator 运行于指定了 cte_type=8bit 的策略,它的行为将与 cte_type7bit 相同。

    • raise_on_defect

      如为 ,则遇到的任何缺陷都将引发错误。 如为 False (默认值),则缺陷将被传递给 方法。

    • mangle_from_

      如为 True,则消息体中以 “From “ 开头的行会通过在其前面放一个 > 来进行转义。 当消息被生成器执行序列化时会使用此形参。 默认值t: 。

      3.5 新版功能: mangle_from_ 形参。

    • message_factory

      用来构造新的空消息对象的工厂函数。 在构建消息时由解析器使用。 默认为 None,在此情况下会使用 Message

      3.6 新版功能.

    下列 方法是由使用 email 库的代码来调用以创建具有自室外设置的策略实例:

    • clone(**kw)

      返回一个新的 Policy 实例,其属性与当前实例具有相同的值,除非是那些由关键字参数给出了新值的属性。

    其余的 方法是由 email 包代码来调用的,而不应当被使用 email 包的应用程序所调用。 自定义的策略必须实现所有这些方法。

    • handle_defect(obj, defect)

      处理在 obj 上发现的 defect。 当 email 包调用此方法时,defect 将总是 Defect 的一个子类。

      默认实现会检查 raise_on_defect 旗标。 如果其为 True,则 defect 会被作为异常来引发。 如果其为 False (默认值),则 objdefect 会被传递给 。

    • register_defect(obj, defect)

      obj 上注册一个 defect。 在 email 包中,defect 将总是 Defect 的一个子类。

      默认实现会调用 objdefects 属性的 append 方法。 当 email 包调用 handle_defect 时,obj 通常将具有一个带 append 方法的 defects 属性。 配合 email 包使用的自定义对象类型(例如自定义的 Message 对象)也应当提供这样的属性,否则在被解析消息中的缺陷将引发非预期的错误。

    • 返回名为 name 的标头的最大允许数量。

      当添加一个标头到 或 Message 对象时被调用。 如果返回值不为 0None,并且已有的名称为 name 的标头数量大于等于所返回的值,则会引发 。

      由于 Message.__setitem__ 的默认行为是将值添加到标头列表,因此很容易不知情地创建重复的标头。 此方法允许在程序中限制可以被添加到 Message 中的特定标头的实例数量。 (解析器不会考虑此限制,它将忠实地产生被解析消息中存在的任意数量的标头。)

      默认实现对于所有标头名称都返回 None

    • header_store_parse(name, value)

      当一个应用通过程序代码修改 Message (而不是由解析器创建 Message) 时,email 包会调用此方法时并附带应用程序所提供的名称和值。 此方法应当返回 (name, value) 元组以保存至 Message 中用来表示标头。

      如果一个实现希望保持与现有 email 包策略的兼容性,则 namevalue 应当为字符串或字符串的子类,它们不会修改在参数中传入的内容。

      此方法没有默认实现

    • header_fetch_parse(name, value)

      当标头被应用程序所请求时,email 包会调用此方法并附带当前保存在 Message 中的 namevalue,并且无论此方法返回什么它都会被回传给应用程序作为被提取标头的值。 请注意可能会有多个相同名称的标头被保存在 Message 中;此方法会将指定标头的名称和值返回给应用程序。

      value 可能包含经替代转义的二进制数据。 此方法所返回的值应当没有经替代转义的二进制数据。

      此方法没有默认实现

    • fold(name, value)

      email 包调用此方法时会附带当前保存在 Message 中的给定标头的 namevalue。 此方法应当返回一个代表该标头的(根据策略设置)通过处理 namevalue 并在适当位置插入 linesep 字符来正确地“折叠”的字符串。 请参阅 了解有关折叠电子邮件标头的规则的讨论。

      value 可能包含经替代转义的二进制数据。 此方法所返回的字符串应当没有经替代转义的二进制数据。

    • fold_binary(name, value)

      fold() 类似,不同之处在于返回的值应当为字节串对象而非字符串。

      value 可能包含经替代转义的二进制数据。 这些数据可以在被返回的字节串对象中被转换回二进制数据。

    class email.policy.EmailPolicy(**kw)

    这个实体 提供了完全遵循当前电子邮件 RFC 的行为。 这包括 (但不限于) RFC 5322, 以及当前的各种 MIME RFC。

    此策略添加了新的标头解析和折叠算法。 标头不是简单的字符串,而是带有依赖于字段类型的属性的 str 的子类。 这个解析和折叠算法完整实现了 RFC 2047 和 。

    message_factory 属性的默认值为 。

    除了上面列出的适用于所有策略的可设置属性,此策略还添加了下列额外属性:

    3.6 新版功能: 1

    • utf8

      如为 False,则遵循 ,通过编码为“已编码字”来支持标头中的非 ASCII 字符。 如为 True,则遵循 RFC 6532 并对标头使用 utf-8 编码格式。 以此方式格式化的消息可被传递给支持 SMTPUTF8 扩展 () 的 SMTP 服务器。

    • refold_source

      如果 Message 对象中标头的值源自 parser (而非由程序设置),此属性会表明当将消息转换回序列化形式时是否应当由生成器来重新折叠该值。 可能的值如下:

      none

      所有源值使用原始折叠

      long

      具有任何长度超过 max_line_length 的行的源值将被折叠

      all

      所有值会被重新折叠。

      默认值为 long

    • header_factory

      该可调用对象接受两个参数,namevalue,其中 name 为标头字段名而 value 为展开后的标头字段值,并返回一个表示该标头的字符串子类。 已提供的默认 header_factory (参见 ) 支持对各种地址和日期 RFC 5322 标头字段类型及主要 MIME 标头字段类型的自定义解析。 未来还将添加对其他自定义解析的支持。

    • content_manager

      此对象至少有两个方法: get_content 和 set_content。 当一个 对象的 get_content() 或 方法被调用时,它会调用此对象的相应方法,将消息对象作为其第一个参数,并将传给它的任何参数或关键字作为附加参数传入。 默认情况下 content_manager 会被设为 raw_data_manager

      3.4 新版功能.

    这个类提供了下列对 的抽象方法的具体实现:

    • header_max_count(name)

      返回用来表示具有给定名称的标头的专用类的 max_count 属性的值。

    • 此名称会被作为到 ‘:’ 止的所有内容来解析。 该值是通过从第一行的剩余部分去除前导空格,再将所有后续行连接到一起,并去除所有末尾回车符或换行符来确定的。

    • header_fetch_parse(name, value)

      如果值具有 name 属性,它会被原样返回。 在其他情况下 name 和移除了所有 CR 和 LF 字符的 value 会被传递给 header_factory,并返回结果标头对象。 任何经替代转义的字节串会被转换为 unicode 未知字符字形。

    • fold(name, value)

      标头折叠是由 策略设置来控制的。 当且仅当一个值没有 name 属性(具有 属性就意味着它是某种标头对象)它才会被当作是“源值”。 如果一个原值需要按照策略来重新折叠,则会通过将 name 和去除了所有 CR 和 LF 字符的 value 传递给 header_factory 来将其转换为标头对象。 标头对象的折叠是通过调用其 fold 方法并附带当前策略来完成的。

      源值会使用 splitlines() 来拆分成多行。 如果该值不被重新折叠,则会使用策略中的 linesep 重新合并这些行并将其返回。 例外的是包含非 ascii 二进制数据的行。 在此情况下无论 refold_source 如何设置该值都会被重新折叠,这会导致二进制数据使用 unknown-8bit 字符集进行 CTE 编码。

    • fold_binary(name, value)

      如果 为 7bit 则与 fold() 类似,不同之处在于返回的值是字节串。

      如果 为 8bit,则将非 ASCII 二进制数据转换回字节串。 带有二进制数据的标头不会被重新折叠,无论 refold_header 设置如何,因为无法知晓该二进制数据是由单字节字符还是多字节字符组成的。

    以下 EmailPolicy 的实例提供了适用于特定应用领域的默认值。 请注意在未来这些实例(特别是 HTTP 实例)的行为可能会被调整以便更严格地遵循与其领域相关的 RFC。

    email.policy.default

    一个未改变任何默认值的 EmailPolicy 实例。 此策略使用标准的 Python \n 行结束符而非遵循 RFC 的 \r\n

    email.policy.SMTP

    适用于按照符合电子邮件 RFC 的方式来序列化消息。 与 default 类似,但 linesep 被设为遵循 RFC 的 \r\n

    email.policy.SMTPUTF8

    SMTP 类似但是 为 True。 适用于在不使用标头内已编码字的情况下对消息进行序列化。 如果发送方或接收方地址具有非 ASCII 字符则应当只被用于 SMTP 传输 (smtplib.SMTP.send_message() 方法会自动如此处理)。

    email.policy.HTTP

    适用于序列化标头以在 HTTP 通信中使用。 与 SMTP 类似但是 max_line_length 被设为 None (无限制)。

    email.policy.strict

    便捷实例。 与 default 类似但是 raise_on_defect 被设为 True。 这样可以允许通过以下写法来严格地设置任何策略:

    因为所有这些 ,email 包的高效 API 相比 Python 3.2 API 发生了以下几方面变化:

    从应用程序的视角来看,这意味着任何通过 EmailMessage 获得的标头都是具有附加属性的标头对象,其字符串值都是该标头的完全解码后的 unicode 值。 类似地,可以使用 unicode 对象为一个标头赋予新的值,或创建一个新的标头对象,并且该策略将负责把该 unicode 字符串转换为正确的 RFC 已编码形式。

    标头对象及其属性的描述见 。

    class email.policy.Compat32(**kw)

    这个实体 Policy 为向下兼容策略。 它复制了 Python 3.2 中 email 包的行为。 模块还定义了该类的一个实例 compat32,用来作为默认策略。 因此 email 包的默认行为会保持与 Python 3.2 的兼容性。

    下列属性具有与 默认值不同的值:

    • mangle_from_

      默认值为 True

    这个类提供了下列对 Policy 的抽象方法的具体实现:

    • header_source_parse(sourcelines)

      此名称会被作为到 ‘:’ 止的所有内容来解析。 该值是通过从第一行的剩余部分去除前导空格,再将所有后续行连接到一起,并去除所有末尾回车符或换行符来确定的。

    • header_store_parse(name, value)

      name 和 value 会被原样返回。

    • header_fetch_parse(name, value)

      如果 value 包含二进制数据,则会使用 unknown-8bit 字符集来将其转换为 对象。 在其他情况下它会被原样返回。

    • fold_binary(name, value)

      标头会使用 Header 折叠算法进行折叠,该算法保留 value 中现有的换行,并将每个结果行的长度折叠至 max_line_length。 如果 cte_type7bit,则非 ascii 二进制数据会使用 unknown-8bit 字符集进行 CTE 编码。 在其他情况下则会使用原始的源标头,这将保留其现有的换行和所包含的任何(不符合 RFC 的)二进制数据。

    email.policy.compat32

    的实例,提供与 Python 3.2 中的 email 包行为的向下兼容性。

    备注

    1