email.policy
:策略对象¶
在版本 3.3 中添加。
源代码: Lib/email/policy.py
email
包的主要重点是处理电子邮件和 MIME RFC 中描述的电子邮件消息。但是,电子邮件消息的一般格式(一个由头字段块组成,每个字段块由一个名称、一个冒号和一个值组成,整个块后跟一个空行和一个任意“正文”)是一种在电子邮件领域之外找到用途的格式。其中一些用途与主要的电子邮件 RFC 非常一致,而另一些则不一致。即使在使用电子邮件时,有时也希望打破对 RFC 的严格遵守,例如生成与不遵循标准的电子邮件服务器进行交互的电子邮件,或以违反标准的方式实现您想要使用的扩展。
策略对象使电子邮件包能够灵活地处理所有这些不同的用例。
Policy
对象封装了一组属性和方法,它们控制电子邮件包在使用期间的各个组件的行为。Policy
实例可以传递给电子邮件包中的各个类和方法,以更改默认行为。可设置的值及其默认值如下所述。
电子邮件包中所有类都使用默认策略。对于所有 parser
类和相关便捷函数,以及 Message
类,这是 Compat32
策略,通过其对应的预定义实例 compat32
。此策略提供与电子邮件包的 Python3.3 之前版本(在某些情况下包括错误兼容性)的完全向后兼容性。
policy 关键字的 EmailMessage
的默认值为 EmailPolicy
策略,通过其预定义实例 default
。
创建 Message
或 EmailMessage
对象时,它会获取策略。如果消息是由 parser
创建的,传递给解析器的策略将是其创建的消息使用的策略。如果消息是由程序创建的,则可以在创建时指定策略。将消息传递给 generator
时,生成器默认使用消息中的策略,但你也可以将特定策略传递给生成器,该策略将覆盖存储在消息对象上的策略。
policy 关键字的 email.parser
类和解析器便捷函数的默认值将在 Python 的未来版本中发生更改。因此,在调用 parser
模块中描述的任何类和函数时,你应始终明确指定要使用的策略。
本说明文档的第一部分涵盖了 Policy
的特性,抽象基类 定义了所有策略对象共有的特性,包括 compat32
。这包括电子邮件包在内部调用的某些钩子方法,自定义策略可以覆盖这些方法以获取不同的行为。第二部分描述了具体类 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's
stdin
的二进制字符串时使用 RFC 正确的行分隔符字符,其中默认策略将使用 \n
行分隔符。
一些电子邮件包方法接受一个 策略 关键字参数,允许为该方法覆盖策略。例如,以下代码使用上一个示例中的 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 使用的内部行尾规则,尽管 RFC 需要\r\n
。
- cte_type¶
控制可能或必须使用的内容传输编码的类型。可能的值是
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()
方法。
以下
Policy
方法旨在由使用电子邮件库的代码调用,以创建具有自定义设置的策略实例其余
Policy
方法由电子邮件包代码调用,并且不打算由使用电子邮件包的应用程序调用。自定义策略必须实现所有这些方法。- handle_defect(obj, defect)¶
处理在 obj 上发现的缺陷。当电子邮件包调用此方法时,缺陷将始终是
Defect
的子类。默认实现检查
raise_on_defect
标志。如果为True
,则将 defect 作为异常引发。如果为False
(默认值),则将 obj 和 defect 传递给register_defect()
。
- register_defect(obj, defect)¶
在 obj 上注册 defect。在电子邮件包中,defect 始终是
Defect
的子类。默认实现调用 obj 的
defects
属性的append
方法。当电子邮件包调用handle_defect
时,obj 通常具有一个具有append
方法的defects
属性。与电子邮件包一起使用的自定义对象类型(例如,自定义Message
对象)也应提供此类属性,否则已解析消息中的缺陷将引发意外错误。
- header_max_count(name)¶
返回允许的最大数量,名为 name 的头。
当头被添加到
EmailMessage
或Message
对象时调用。如果返回值不是0
或None
,并且已经存在数量大于或等于返回值的名称为 name 的头,则会引发ValueError
。由于
Message.__setitem__
的默认行为是将值附加到头列表中,因此很容易在没有意识到这一点的情况下创建重复头。此方法允许对Message
中可以添加的特定头实例的数量进行限制(通过编程方式)。(解析器不会遵守此限制,它将忠实地生成与正在解析的消息中存在的一样多的头。)默认实现为所有头名称返回
None
。
- header_source_parse(sourcelines)¶
电子邮件包使用一组字符串调用此方法,每个字符串以解析的源中找到的行分隔符结尾。第一行包括字段头名称和分隔符。保留源中的所有空格。该方法应返回要存储在
Message
中以表示已解析头的(name, value)
元组。如果某个实现希望与现有的电子邮件包策略保持兼容,则name 应为保留大小写的名称(直到“
:
”分隔符的所有字符),而value 应为展开的值(删除所有行分隔符,但保留空格),并删除前导空格。sourcelines 可能包含代理转义的二进制数据。
没有默认实现
- header_store_parse(name, value)¶
当应用程序通过编程方式修改
Message
(而不是由解析器创建的Message
)时,电子邮件包使用应用程序提供的名称和值调用此方法。该方法应返回要存储在Message
中以表示头的(name, value)
元组。如果某个实现希望与现有的电子邮件包策略保持兼容,则name 和value 应为字符串或字符串子类,它们不会更改传入参数的内容。
没有默认实现
- header_fetch_parse(name, value)¶
当应用程序程序请求该头时,电子邮件包会使用当前存储在
消息
中的名称和值调用此方法,并且该方法返回的任何内容都将作为要检索的头部的值传递回应用程序。请注意,消息
中可能存储了多个具有相同名称的头;该方法会传递要返回给应用程序的头部的特定名称和值。值可能包含代理转义的二进制数据。该方法返回的值中不应包含代理转义的二进制数据。
没有默认实现
- 类 电子邮件.电子邮件策略(**千瓦)¶
此具体
策略
提供的行为旨在完全符合当前的电子邮件 RFC。其中包括(但不限于) RFC 5322、RFC 2047 和当前的 MIME RFC。此策略添加了新的标头解析和折叠算法。标头不是简单的字符串,而是
str
子类,其属性取决于字段的类型。解析和折叠算法完全实现了 RFC 2047 和 RFC 5322。message_factory
属性的默认值为EmailMessage
。除了上述适用于所有策略的可设置属性外,此策略还添加了以下附加属性
3.6 版中添加: [1]
- utf8¶
如果
False
,则遵循 RFC 5322,通过将非 ASCII 字符编码为“编码字”来支持标头中的非 ASCII 字符。如果True
,则遵循 RFC 6532,并对标头使用utf-8
编码。以这种方式格式化的邮件可以传递给支持SMTPUTF8
扩展的 SMTP 服务器(RFC 6531)。
- 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。当调用
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¶
适用于序列化符合电子邮件 RFC 的邮件。与
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
,电子邮件包的有效 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
,用作默认策略。因此,电子邮件包的默认行为是保持与 Python 3.2 的兼容性。以下属性的值与
Policy
默认值不同- mangle_from_¶
默认值为
True
。
该类提供了
Policy
抽象方法的以下具体实现- header_source_parse(sourcelines)¶
名称被解析为直到 ‘
:
’ 之前的所有内容,并原样返回。值通过去除第一行开头的空白,将所有后续行连接在一起,并去除任何尾随的回车或换行符来确定。
- header_store_parse(name, value)¶
名称和值返回时未经修改。
- header_fetch_parse(name, value)¶
如果值包含二进制数据,它将使用
Header
对象和unknown-8bit
字符集转换为Header
对象。否则它将返回时未经修改。
脚注