email.policy :策略对象

3.3 新版功能.

源代码: Lib/email/policy.py


这个 email 包的主要重点是处理各种电子邮件和MIME RFC所描述的电子邮件消息。但是,电子邮件消息的一般格式(一个标题字段块,每个字段包含一个名称,后跟一个冒号和一个值,整个字段块后跟一个空行和一个任意的“body”)是一种在电子邮件领域之外找到实用程序的格式。其中一些用法与主电子邮件RFC非常接近,有些则不符合。即使在处理电子邮件时,有时也需要打破对RFC的严格遵从性,例如生成与自身不符合标准的电子邮件服务器交互操作的电子邮件,或者以违反标准的方式实现要使用的扩展。

策略对象使电子邮件包能够灵活地处理所有这些不同的用例。

A Policy 对象封装了一组属性和方法,这些属性和方法控制电子邮件包各个组件在使用过程中的行为。 Policy 实例可以传递到电子邮件包中的各种类和方法,以更改默认行为。可设置值及其默认值如下所述。

电子邮件包中的所有类都使用默认策略。对于所有的 parser 类和相关的方便函数,以及 Message 类,这是 Compat32 策略,通过其对应的预定义实例 compat32 . 此策略提供与电子邮件包的pre-python3.3版本的完全向后兼容性(在某些情况下,包括bug兼容性)。

此默认值用于 policy 关键字到 EmailMessageEmailPolicy 策略,通过其预定义的实例 default .

当A MessageEmailMessage 对象被创建,它获得一个策略。如果消息是由 parser ,传递给解析器的策略将是它创建的消息所使用的策略。如果消息是由程序创建的,则可以在创建时指定策略。当消息传递到 generator ,生成器默认使用来自消息的策略,但也可以将特定策略传递给生成器,该策略将覆盖存储在消息对象上的策略。

的默认值 policy 关键字为 email.parser 类和解析器方便函数 会改变的 在未来的Python版本中。所以你应该 始终明确指定要使用的策略 调用中描述的任何类和函数时, parser 模块。

本文的第一部分介绍了 Policy ,一个 abstract base class 定义所有策略对象通用的功能,包括 compat32 . 这包括电子邮件包内部调用的某些hook方法,自定义策略可以重写这些方法以获得不同的行为。第二部分介绍了具体的分类 EmailPolicyCompat32 实现分别提供标准行为和向后兼容行为和特性的挂钩。

Policy 实例是不可变的,但它们可以被复制,接受与类构造函数相同的关键字参数,并返回新的 Policy 实例,该实例是原始的副本,但指定的属性值已更改。

例如,可以使用以下代码从磁盘上的文件中读取电子邮件消息并将其传递给系统 sendmail UNIX系统上的程序:

>>> from email import message_from_binary_file
>>> from email.generator import BytesGenerator
>>> from email import policy
>>> from subprocess import Popen, PIPE
>>> with open('mymsg.txt', 'rb') as f:
...     msg = message_from_binary_file(f, policy=policy.default)
>>> p = Popen(['sendmail', msg['To'].addresses[0]], stdin=PIPE)
>>> g = BytesGenerator(p.stdin, policy=msg.policy.clone(linesep='\r\n'))
>>> g.flatten(msg)
>>> p.stdin.close()
>>> rc = p.wait()

我们来告诉你 BytesGenerator 在创建要馈入的二进制字符串时使用RFC更正行分隔符字符 sendmail's stdin ,其中默认策略将使用 \n 行分隔符。

一些电子邮件包方法接受 policy 关键字参数,允许为该方法重写策略。例如,以下代码使用 as_bytes() 方法 msg 对象,并使用运行消息的平台的本机行分隔符将消息写入文件:

>>> import os
>>> with open('converted.txt', 'wb') as f:
...     f.write(msg.as_bytes(policy=msg.policy.clone(linesep=os.linesep)))
17

还可以使用加法运算符组合策略对象,生成一个策略对象,其设置是求和对象的非默认值的组合:

>>> compat_SMTP = policy.compat32.clone(linesep='\r\n')
>>> compat_strict = policy.compat32.clone(raise_on_defect=True)
>>> compat_strict_SMTP = compat_SMTP + compat_strict

这个操作不是交换的;也就是说,对象的添加顺序很重要。举例说明:

>>> policy100 = policy.compat32.clone(max_line_length=100)
>>> policy80 = policy.compat32.clone(max_line_length=80)
>>> apolicy = policy100 + policy80
>>> apolicy.max_line_length
80
>>> apolicy = policy80 + policy100
>>> apolicy.max_line_length
100
class email.policy.Policy(**kw)

这就是 abstract base class 对于所有策略类。它提供了一些简单方法的默认实现,以及不可变属性的实现, clone() 方法和构造函数语义。

策略类的构造函数可以传递各种关键字参数。可以指定的参数是此类上的任何非方法属性,以及具体类上的任何其他非方法属性。构造函数中指定的值将重写相应属性的默认值。

此类定义了以下属性,因此可以在任何策略类的构造函数中传递以下属性的值:

max_line_length

序列化输出中任何行的最大长度,不计算行尾字符。默认值为78,每 RFC 5322 . 一个值 0None 指示根本不应进行换行。

linesep

用于终止序列化输出中的行的字符串。默认值为 \n 因为这是Python使用的内部行尾规则 \r\n 是RFC所必需的。

cte_type

控制可能使用或需要使用的内容传输编码的类型。可能的值为:

7bit

所有数据必须是“7位干净”(仅限ASCII)。这意味着必要时,将使用引用的可打印或base64编码对数据进行编码。

8bit

数据不限于7位干净。头中的数据仍然需要仅为ASCII,因此将进行编码(请参见 fold_binary()utf8 以下为例外情况),但车身部件可以使用 8bit CTE。

A cte_type 价值 8bit 只适用于 BytesGenerator 不是 Generator ,因为字符串不能包含二进制数据。如果A Generator 正在指定的策略下操作 cte_type=8bit 就好像 cte_type7bit .

raise_on_defect

如果 True ,遇到的任何缺陷都将作为错误提出。如果 False (默认),缺陷将传递给 register_defect() 方法。

mangle_from_

如果 True ,行从开始 “从” 在尸体里放了一个 > 在他们面前。此参数在生成器序列化消息时使用。违约: False .

3.5 新版功能: 这个 mangle_from_ 参数。

message_factory

用于构造新的空消息对象的factory函数。由分析器在生成消息时使用。默认为 None ,在这种情况下 Message 使用。

3.6 新版功能.

以下 Policy 方法由代码调用,代码使用电子邮件库创建具有自定义设置的策略实例:

clone(**kw)

返回一个新的 Policy 其属性与当前实例具有相同值的实例,但通过关键字参数为这些属性提供新值的实例除外。

剩余的 Policy 方法由电子邮件包代码调用,而不是由使用电子邮件包的应用程序调用。自定义策略必须实现所有这些方法。

handle_defect(obj, defect)

处理A 缺陷 发现于 obj . 当电子邮件包调用此方法时, 缺陷 将始终是 Defect .

默认实现检查 raise_on_defect flag。如果是 True缺陷 作为异常引发。如果是 False (违约), obj缺陷 被传递给 register_defect() .

register_defect(obj, defect)

注册A 缺陷obj . 在电子邮件包中, 缺陷 将始终是 Defect .

默认实现调用 append 方法 defects 属性 obj . 当电子邮件包调用时 handle_defectobj 通常会有一个 defects 具有 append 方法。与电子邮件包一起使用的自定义对象类型(例如,自定义 Message 对象)还应提供这样的属性,否则解析消息中的缺陷将导致意外错误。

header_max_count(name)

返回名为的头的最大允许数目 name .

在将头添加到 EmailMessageMessage 对象。如果返回值不是 0None ,并且已经有多个具有名称的头 name 大于或等于返回的值,a ValueError 提高了。

因为默认行为 Message.__setitem__ 将值附加到头列表中,很容易创建重复的头而不实现它。此方法允许将某些头限制在可以添加到 Message 以编程方式。(解析器不遵守该限制,它将忠实地生成所解析消息中存在的尽可能多的头。)

默认实现返回 None 所有标题名称。

header_source_parse(sourcelines)

电子邮件包使用字符串列表调用此方法,每个字符串以要分析的源中的行分隔字符结尾。第一行包括字段头名称和分隔符。保留源中的所有空白。该方法应返回 (name, value) 要存储在 Message 表示解析的头。

如果实现希望保持与现有电子邮件包策略的兼容性, name 应为保留大小写的名称(所有字符到 ':' 分隔符),而 value 应该是展开的值(删除所有行分隔符字符,但空格保持不变),去掉前导空格。

源细胞 可能包含代理转义的二进制数据。

没有默认实现

header_store_parse(name, value)

当应用程序修改 Message 以编程方式(而不是 Message 由分析器创建)。该方法应返回 (name, value) 要存储在 Message 以表示标题。

如果实现希望保持与现有电子邮件包策略的兼容性,则 namevalue 应该是不更改传入参数内容的字符串或字符串子类。

没有默认实现

header_fetch_parse(name, value)

电子邮件包使用 namevalue 当前存储在 Message 当应用程序请求该头时,无论方法返回什么,都是作为要检索的头的值传递给应用程序的。请注意,在 Message ;该方法将传递要返回到应用程序的头的特定名称和值。

value 可能包含代理转义的二进制数据。方法返回的值中不应存在代理转义的二进制数据。

没有默认实现

fold(name, value)

电子邮件包使用 namevalue 当前存储在 Message 对于给定的标题。方法应返回一个字符串,该字符串通过组合 namevalue 插入 linesep 适当位置的字符。见 RFC 5322 关于邮件头折叠规则的讨论。

value 可能包含代理转义的二进制数据。方法返回的字符串中不应存在代理转义的二进制数据。

fold_binary(name, value)

一样 fold() ,但返回的值应该是字节对象而不是字符串。

value 可能包含代理转义的二进制数据。这些可以在返回的bytes对象中转换回二进制数据。

class email.policy.EmailPolicy(**kw)

这种混凝土 Policy 提供旨在完全符合当前电子邮件RFC的行为。这些包括(但不限于) RFC 5322RFC 2047 以及当前的mime rfc。

此策略添加了新的头解析和折叠算法。头不是简单的字符串,而是 str 具有依赖于字段类型的属性的子类。解析与折叠算法全面实现 RFC 2047RFC 5322 .

的默认值 message_factory 属性是 EmailMessage .

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

3.6 新版功能: 1

utf8

如果 False ,跟随 RFC 5322 ,通过将头中的非ASCII字符编码为“编码字”,来支持这些字符。如果 True ,跟随 RFC 6532 使用 utf-8 头的编码。以这种方式格式化的邮件可以传递到支持 SMTPUTF8 延伸 (RFC 6531

refold_source

如果标题的值位于 Message 对象源于 parser (与由程序设置不同),此属性指示生成器在将消息转换回序列化形式时是否应重新保存该值。可能的值为:

none

所有源值都使用原始折叠

long

具有任何长于 max_line_length 将重新折叠

all

所有值都被重新折叠。

默认值为 long .

header_factory

接受两个参数的可调用文件, namevalue 在哪里 name 是标题字段名,并且 value 是展开的头字段值,并返回表示该头的字符串子类。默认值 header_factory (见 headerregistry )提供支持对各种地址和日期进行自定义分析的 RFC 5322 头字段类型和主要的mime头字段样式。以后将添加对其他自定义分析的支持。

content_manager

至少有两种方法的对象:获取内容和设置内容。当 get_content()set_content() AN方法 EmailMessage 对象,它调用此对象的相应方法,将消息对象作为第一个参数传递给它,并将传递给它的任何参数或关键字作为附加参数传递给它。默认情况下 content_manager 设置为 raw_data_manager .

3.4 新版功能.

类提供了以下抽象方法的具体实现 Policy

header_max_count(name)

返回的值 max_count 用于用给定名称表示标题的专用类的属性。

header_source_parse(sourcelines)

名称被解析为 ':' 并且原封不动地返回。该值是通过从第一行的其余部分剥离前导空格、将所有后续行连接在一起以及剥离任何尾随的回车符或换行符来确定的。

header_store_parse(name, value)

返回的名称不变。如果输入值具有 name 属性和它匹配 name 忽略大小写,返回的值不变。否则 namevalue 被传递给 header_factory ,并返回结果头对象作为值。在这种情况下 ValueError 如果输入值包含CR或LF字符,则引发。

header_fetch_parse(name, value)

如果该值具有 name 属性,它将返回到未修改的。否则 namevalue 删除任何CR或LF字符后,将传递给 header_factory ,并返回结果头对象。所有代理转义的字节都将转换为Unicode未知字符glyph。

fold(name, value)

收割台折叠由 refold_source 策略设置。当且仅当一个值没有 name 属性(具有 name 属性表示它是某种类型的头对象)。如果源值需要根据策略重新折叠,则通过传递 name 以及 value 将任何CR和LF字符删除到 header_factory . 通过调用头对象的 fold 方法。

源值拆分为行,使用 splitlines() . 如果不重新折叠该值,则使用 linesep 并返回。例外情况是包含非ASCII二进制数据的行。在这种情况下,无论 refold_source 设置,使二进制数据使用 unknown-8bit 字符集

fold_binary(name, value)

一样 fold() 如果 cte_type7bit ,但返回的值为字节。

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

以下实例 EmailPolicy 提供适用于特定应用程序域的默认值。请注意,将来这些实例的行为(尤其是 HTTP 实例)可以调整为更接近与其域相关的RFC。

email.policy.default

的实例 EmailPolicy 所有默认值不变。此策略使用标准python \n 行结束而不是RFC正确 \r\n .

email.policy.SMTP

适用于根据电子邮件RFC对消息进行序列化。类似于 default 但是 linesep 设置为 \r\n ,符合RFC。

email.policy.SMTPUTF8

一样 SMTP 除了那个 utf8True . 用于将消息序列化到消息存储区,而不使用头中的编码字。仅当发件人或收件人地址具有非ASCII字符时才应用于SMTP传输 smtplib.SMTP.send_message() 方法自动处理此问题)。

email.policy.HTTP

适用于在HTTP通信中使用的对头进行序列化。类似于 SMTP 除了那个 max_line_length 设置为 None (无限)。

email.policy.strict

便利实例。一样 default 除了那个 raise_on_defect 设置为 True . 这允许通过以下方式严格制定任何策略:

somepolicy + policy.strict

所有这些 EmailPolicies ,电子邮件包的有效API从python 3.2 API更改为以下方式:

  • 在上设置标题 Message 结果将解析该头并创建一个头对象。

  • 从中获取头值 Message 结果将分析该头,并创建并返回头对象。

  • 任何头对象或由于策略设置而重新折叠的任何头使用完全实现RFC折叠算法的算法进行折叠,包括知道在哪里需要和允许编码字。

从应用程序视图中,这意味着通过 EmailMessage 是具有额外属性的头对象,其字符串值是头的完全解码的Unicode值。同样,可以使用Unicode字符串为头分配新值或创建新头,并且策略将负责将Unicode字符串转换为正确的RFC编码形式。

标题对象及其属性在 headerregistry .

class email.policy.Compat32(**kw)

这种混凝土 Policy 是向后兼容策略。它复制了python 3.2中电子邮件包的行为。这个 policy 模块还定义了这个类的一个实例, compat32 ,用作默认策略。因此,电子邮件包的默认行为是保持与Python3.2的兼容性。

以下属性的值与 Policy 违约:

mangle_from_

默认值为 True .

类提供了以下抽象方法的具体实现 Policy

header_source_parse(sourcelines)

名称被解析为 ':' 并且原封不动地返回。该值是通过从第一行的其余部分剥离前导空格、将所有后续行连接在一起以及剥离任何尾随的回车符或换行符来确定的。

header_store_parse(name, value)

返回的名称和值未经修改。

header_fetch_parse(name, value)

如果该值包含二进制数据,则将其转换为 Header 对象使用 unknown-8bit 字符集否则将原封不动地返回。

fold(name, value)

使用折叠收割台 Header 折叠算法,保留值中现有的换行符,并将每个结果行封装到 max_line_length .非ASCII二进制数据使用 unknown-8bit 字符集

fold_binary(name, value)

使用折叠收割台 Header 折叠算法,保留值中现有的换行符,并将每个结果行封装到 max_line_length . 如果 cte_type7bit ,非ASCII二进制数据使用 unknown-8bit 字符集否则,将使用原始源报头,其中包含现有的换行符和可能包含的任何(RFC无效)二进制数据。

email.policy.compat32

的实例 Compat32 提供与Python3.2中电子邮件包行为的向后兼容性。

脚注

1

最初在3.3中作为 provisional feature .