email.policy
:策略对象¶
在 3.3 版本加入。
源代码: Lib/email/policy.py
email
包的主要关注点是处理各种电子邮件和 MIME RFCs 所描述的电子邮件消息。然而,电子邮件消息的通用格式(一个由多个标头字段组成的块,每个字段包含一个名称后跟一个冒号,然后是一个值,整个块后跟一个空行和一个任意的“正文”)这种格式在电子邮件领域之外也得到了应用。其中一些用法与主要的电子邮件 RFCs 相当接近,而另一些则不然。即使在处理电子邮件时,有时也需要打破对 RFCs 的严格遵守,例如生成与那些本身不遵循标准或以违反标准的方式实现您想使用的扩展的电子邮件服务器互操作的电子邮件。
策略对象赋予 email 包处理所有这些不同用例的灵活性。
Policy
对象封装了一组属性和方法,用于在使用过程中控制 email 包中各种组件的行为。Policy
实例可以传递给 email 包中的各种类和方法,以改变默认行为。可设置的值及其默认值将在下面描述。
email 包中所有的类都使用一个默认策略。对于所有的 parser
类和相关的便利函数,以及 Message
类,默认策略是 Compat32
策略,通过其对应的预定义实例 compat32
来实现。这个策略提供了与 Python 3.3 之前的 email 包版本的完全向后兼容性(在某些情况下,包括与 bug 的兼容性)。
EmailMessage
的 policy 关键字的默认值是 EmailPolicy
策略,通过其预定义实例 default
实现。
当创建 Message
或 EmailMessage
对象时,它会获得一个策略。如果消息是由 parser
创建的,传递给解析器的策略将成为它创建的消息所使用的策略。如果消息是由程序创建的,那么可以在创建时指定策略。当消息被传递给 generator
时,生成器默认使用消息的策略,但你也可以传递一个特定的策略给生成器,它将覆盖存储在消息对象上的策略。
在 Python 的未来版本中,email.parser
类和解析器便利函数的 policy 关键字的默认值**将会改变**。因此,在调用 parser
模块中描述的任何类和函数时,你应该**总是显式指定你想要使用的策略**。
本文档的第一部分涵盖了 Policy
的特性,它是一个抽象基类,定义了所有策略对象(包括 compat32
)共有的特性。这包括一些由 email 包内部调用的钩子方法,自定义策略可以重写这些方法以获得不同的行为。第二部分描述了具体的类 EmailPolicy
和 Compat32
,它们分别实现了提供标准行为和向后兼容行为与特性的钩子。
Policy
实例是不可变的,但可以被克隆,接受与类构造函数相同的关键字参数,并返回一个新的 Policy
实例,该实例是原始实例的副本,但指定的属性值已被更改。
例如,以下代码可用于从磁盘文件中读取电子邮件消息,并将其传递给 Unix 系统上的系统 sendmail
程序。
>>> 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
在创建要输入到 sendmail
的 stdin
的二进制字符串时,使用符合 RFC 规范的行分隔符,而默认策略会使用 \n
行分隔符。
一些 email 包的方法接受一个 policy 关键字参数,允许为该方法覆盖策略。例如,以下代码使用前一个示例中 msg 对象的 as_bytes()
方法,并使用其运行平台的原生行分隔符将消息写入文件。
>>> 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)¶
这是所有策略类的抽象基类。它为一些简单的方法提供了默认实现,以及不可变性属性的实现、
clone()
方法和构造函数的语义。策略类的构造函数可以接受各种关键字参数。可以指定的参数是这个类上的任何非方法属性,以及具体类上的任何额外的非方法属性。在构造函数中指定的值将覆盖相应属性的默认值。
该类定义了以下属性,因此以下属性的值可以在任何策略类的构造函数中传递:
- linesep¶
用于在序列化输出中终止行的字符串。默认是
\n
,因为这是 Python 内部使用的行尾规则,尽管 RFCs 要求使用\r\n
。
- cte_type¶
控制可能或必须使用的内容传输编码(Content Transfer Encodings)的类型。可能的值是:
7bit
所有数据必须是“7 位安全的”(仅 ASCII)。这意味着在必要时,数据将使用 quoted-printable 或 base64 编码进行编码。
8bit
数据不限于 7 位安全。标头中的数据仍然需要是仅 ASCII 的,因此会被编码(有关例外情况,请参见下面的
fold_binary()
和utf8
),但正文部分可以使用8bit
CTE。cte_type
值为8bit
仅适用于BytesGenerator
,不适用于Generator
,因为字符串不能包含二进制数据。如果一个Generator
在指定cte_type=8bit
的策略下运行,它的行为将如同cte_type
是7bit
一样。
- raise_on_defect¶
如果为
True
,任何遇到的缺陷都会被作为错误引发。如果为False
(默认值),缺陷将被传递给register_defect()
方法。
- mangle_from_¶
如果为
True
,正文中以 *“From ”* 开头的行会通过在它们前面加上一个>
来进行转义。此参数在消息由生成器序列化时使用。默认值:False
。在 3.5 版本加入。
- verify_generated_headers¶
如果为
True
(默认值),生成器将引发HeaderWriteError
,而不是写入一个折叠或分隔不当的标头,这样的标头可能会被解析为多个标头或与相邻数据连接。这类标头可能由自定义标头类或email
模块中的错误生成。由于它是一项安全特性,即使在
Compat32
策略中,它也默认为True
。为了实现向后兼容但行为不安全的模式,必须将其显式设置为False
。在 3.13 版本加入。
以下
Policy
方法旨在由使用 email 库的代码调用,以创建具有自定义设置的策略实例:其余的
Policy
方法由 email 包的代码调用,不应由使用 email 包的应用程序调用。自定义策略必须实现所有这些方法。- handle_defect(obj, defect)¶
处理在 obj 上发现的 defect。当 email 包调用此方法时,defect 将始终是
MessageDefect
的子类。默认实现会检查
raise_on_defect
标志。如果为True
,defect 将作为异常被引发。如果为False
(默认值),obj 和 defect 将被传递给register_defect()
。
- register_defect(obj, defect)¶
在 obj 上注册一个 defect。在 email 包中,defect 将始终是
MessageDefect
的子类。默认实现会调用 obj 的
defects
属性的append
方法。当 email 包调用handle_defect
时,obj 通常会有一个具有append
方法的defects
属性。与 email 包一起使用的自定义对象类型(例如,自定义Message
对象)也应提供这样的属性,否则解析消息中的缺陷将引发意外错误。
- header_max_count(name)¶
返回名为 name 的标头所允许的最大数量。
在向
EmailMessage
或Message
对象添加标头时调用。如果返回的值不是0
或None
,并且已经存在名为 name 的标头数量大于或等于返回的值,则会引发ValueError
。由于
Message.__setitem__
的默认行为是将值附加到标头列表中,因此很容易在不知不觉中创建重复的标头。此方法允许限制某些标头可以以编程方式添加到Message
对象中的实例数量。(解析器不会遵守此限制,它将忠实地生成消息中存在的所有标头。)默认实现对所有标头名称返回
None
。
- header_source_parse(sourcelines)¶
email 包使用一个字符串列表调用此方法,每个字符串都以在被解析的源中找到的行分隔符结尾。第一行包括字段标头名称和分隔符。源中的所有空白都将被保留。该方法应返回
(name, value)
元组,该元组将存储在Message
中以表示解析后的标头。如果实现希望保持与现有 email 包策略的兼容性,name 应该是保留大小写的名称(直到“
:
”分隔符之前的所有字符),而 value 应该是展开后的值(所有行分隔符被移除,但空白保持不变),并去除前导空白。sourcelines 可能包含 surrogateescaped 编码的二进制数据。
没有默认实现。
- header_store_parse(name, value)¶
当应用程序以编程方式修改
Message
(而不是由解析器创建的Message
)时,email 包会使用应用程序提供的名称和值调用此方法。该方法应返回(name, value)
元组,该元组将存储在Message
中以表示该标头。如果实现希望保持与现有 email 包策略的兼容性,name 和 value 应该是不会改变传入参数内容的字符串或字符串子类。
没有默认实现。
- header_fetch_parse(name, value)¶
当应用程序请求某个标头时,email 包会使用当前存储在
Message
中的 name 和 value 调用此方法,而该方法返回的任何内容都将作为被检索标头的值返回给应用程序。请注意,Message
中可能存储了多个同名的标头;该方法被传递的是将要返回给应用程序的特定标头的名称和值。value 可能包含 surrogateescaped 编码的二进制数据。方法返回的值中不应包含 surrogateescaped 编码的二进制数据。
没有默认实现。
- class email.policy.EmailPolicy(**kw)¶
这个具体的
Policy
提供了旨在完全符合当前电子邮件 RFC 的行为。这些 RFC 包括(但不限于)RFC 5322、RFC 2047 以及当前的 MIME RFC。此策略添加了新的标头解析和折叠算法。标头不再是简单的字符串,而是
str
的子类,其属性取决于字段类型。解析和折叠算法完全实现了 RFC 2047 和 RFC 5322。message_factory
属性的默认值是EmailMessage
。除了上面列出的适用于所有策略的可设置属性外,此策略还添加了以下附加属性:
在 3.6 版本加入: [1]
- utf8¶
如果为
False
,则遵循 RFC 5322,通过将非 ASCII 字符编码为“编码词”来支持标头中的这些字符。如果为True
,则遵循 RFC 6532 并对标头使用utf-8
编码。以此方式格式化的消息可以传递给支持SMTPUTF8
扩展(RFC 6531)的 SMTP 服务器。
- refold_source¶
如果
Message
对象中标头的值源自parser
(而不是由程序设置),此属性指示生成器在将消息转换回序列化形式时是否应重新折叠该值。可能的值为:none
所有源值都使用原始的折叠方式
long
任何行长于
max_line_length
的源值都将被重新折叠all
所有值都会被重新折叠。
默认值为
long
。
- header_factory¶
一个可调用对象,接受两个参数
name
和value
,其中name
是标头字段名,value
是未折叠的标头字段值,并返回一个表示该标头的字符串子类。提供了一个默认的header_factory
(见headerregistry
),它支持对各种地址和日期 RFC 5322 标头字段类型以及主要的 MIME 标头字段类型进行自定义解析。将来会增加对其他自定义解析的支持。
- content_manager¶
一个至少有两个方法的对象:get_content 和 set_content。当调用
EmailMessage
对象的get_content()
或set_content()
方法时,它会调用此对象的相应方法,将消息对象作为其第一个参数,并将传递给它的任何参数或关键字作为附加参数传递。默认情况下,content_manager
被设置为raw_data_manager
。在 3.4 版本加入。
该类提供了
Policy
抽象方法的以下具体实现:- header_source_parse(sourcelines)¶
名称被解析为直到“
:
”之前的所有内容并原样返回。值是通过去除第一行剩余部分的前导空格,将所有后续行连接在一起,并去除任何尾随的回车或换行符来确定的。
- header_store_parse(name, value)¶
名称原样返回。如果输入值具有一个
name
属性且其与 name 忽略大小写匹配,则该值原样返回。否则,name 和 value 会被传递给header_factory
,返回的结果标头对象作为值。在这种情况下,如果输入值包含 CR 或 LF 字符,则会引发ValueError
。
- header_fetch_parse(name, value)¶
如果值有一个
name
属性,则它会被原样返回。否则,name 和移除了任何 CR 或 LF 字符的 value 将被传递给header_factory
,并返回生成的标头对象。任何代理转义的字节都会变成 unicode 的未知字符符号。
- fold(name, value)¶
标头折叠由
refold_source
策略设置控制。一个值当且仅当它没有name
属性时,才被认为是“源值”(拥有name
属性意味着它是某种标头对象)。如果根据策略需要重新折叠一个源值,它会被转换成一个标头对象,方法是将 name 和去除了任何 CR 和 LF 字符的 value 传递给header_factory
。标头对象的折叠是通过调用其fold
方法并传入当前策略来完成的。源值使用
splitlines()
分割成行。如果该值不需重新折叠,则这些行将使用策略中的linesep
重新连接并返回。例外情况是包含非 ASCII 二进制数据的行。在这种情况下,无论refold_source
设置如何,该值都会被重新折叠,这会导致二进制数据使用unknown-8bit
字符集进行 CTE 编码。
以下 EmailPolicy
实例为特定应用领域提供了合适的默认值。请注意,将来这些实例的行为(特别是 HTTP
实例)可能会被调整,以更紧密地符合其相关领域的 RFC。
- email.policy.default¶
一个
EmailPolicy
的实例,所有默认值均未改变。此策略使用标准的 Python\n
换行符,而不是 RFC 规范的\r\n
。
- email.policy.SMTP¶
适用于按照电子邮件 RFCs 规范序列化消息。与
default
类似,但linesep
设置为\r\n
,这符合 RFC 规范。
- email.policy.SMTPUTF8¶
与
SMTP
相同,但utf8
为True
。适用于将消息序列化到消息存储中,而不在标头中使用编码词。仅当发件人或收件人地址含有非 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
,email 包的有效 API 与 Python 3.2 API 相比有以下变化:
在
Message
上设置一个标头会导致该标头被解析并创建一个标头对象。从
Message
获取一个标头值会导致该标头被解析,并创建并返回一个标头对象。任何标头对象,或任何由于策略设置而被重新折叠的标头,都将使用一个完全实现了 RFC 折叠算法的算法进行折叠,包括知道在何处需要和允许使用编码词。
从应用程序的角度来看,这意味着通过 EmailMessage
获取的任何标头都是一个带有额外属性的标头对象,其字符串值是标头的完全解码的 unicode 值。同样,可以使用 unicode 字符串为标头赋新值或创建新标头,策略将负责将 unicode 字符串转换为正确的 RFC 编码形式。
标头对象及其属性在 headerregistry
中有描述。
- class email.policy.Compat32(**kw)¶
这个具体的
Policy
是向后兼容策略。它复制了 email 包在 Python 3.2 中的行为。policy
模块也定义了这个类的一个实例compat32
,它被用作默认策略。因此,email 包的默认行为是保持与 Python 3.2 的兼容性。以下属性的值与
Policy
的默认值不同:- mangle_from_¶
默认值为
True
。
该类提供了
Policy
抽象方法的以下具体实现:- header_source_parse(sourcelines)¶
名称被解析为直到“
:
”之前的所有内容并原样返回。值是通过去除第一行剩余部分的前导空格,将所有后续行连接在一起,并去除任何尾随的回车或换行符来确定的。
- header_store_parse(name, value)¶
名称和值将不加修改地返回。
脚注