On this page
email.policy:策略对象
版本 3.3 中的新Function。
源代码: Lib/email/policy.py
email软件包的主要重点是处理各种电子邮件和 MIME RFC 所描述的电子邮件。但是,电子邮件的一般格式(一个标题字段块,每个标题字段由一个名称,一个冒号,一个值,整个块,一个空行和一个任意的“ body”组成)是一种已经发现的格式电子邮件领域之外的 Util。其中一些用法与主要电子邮件 RFC 相当接近,有些则与之不符。即使使用电子邮件,有时也需要 break 对 RFC 的严格合规,例如生成与本身不遵循标准的电子邮件服务器进行互操作的电子邮件,或者以违反方式使用您想要使用的扩展标准。
策略对象使电子邮件包可以灵活地处理所有这些不同的用例。
Policy对象封装了一组属性和方法,这些属性和方法控制电子邮件包在使用过程中各个组件的行为。 Policy实例可以传递到电子邮件包中的各种类和方法,以更改默认行为。可设置值及其默认值如下所述。
电子邮件包中的所有类都使用默认策略。对于所有parser类和相关的便利Function,对于Message类,这是Compat32策略(pass其对应的 sched 义实例compat32)。此策略提供与电子邮件包的 Python3.3 之前版本的完全向后兼容性(在某些情况下,包括错误兼容性)。
EmailMessage的* policy *关键字的默认值是EmailPolicy策略(pass其 sched 义实例default)。
创建Message或EmailMessage对象时,它会获取一个策略。如果消息是由parser创建的,则传递给解析器的策略将是它创建的消息所使用的策略。如果消息是由程序创建的,则可以在创建策略时指定该策略。当消息传递给generator时,生成器默认使用消息中的策略,但是您也可以将特定策略传递给生成器,该策略将覆盖存储在消息对象上的策略。
email.parser类的* policy *关键字和解析器便捷Function的默认值 将在 Python 的 Future 版本中更改 。因此,在调用parser模块中描述的任何类和函数时,您应该 始终明确指定要使用的策略 。
本文档的第一部分介绍Policy的Function,抽象 Base Class定义了所有策略对象(包括compat32)所共有的Function。这包括电子邮件程序包内部调用的某些钩子方法,自定义策略可以覆盖某些钩子方法以获得不同的行为。第二部分描述了具体的类EmailPolicy和Compat32,它们实现了分别提供标准行为和向后兼容行为和Function的钩子。
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
行分隔符。
一些电子邮件软件包方法接受* 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
此操作不是可交换的;也就是说,对象的添加 Sequences 很重要。为了显示:
>>> 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
- 类别
email.policy.
Policy
(*** kw *)- 这是所有策略类别的抽象 Base Class。它提供了一些简单方法的默认实现,以及不变性属性,clone()方法和构造函数语义的实现。
策略类的构造函数可以传递各种关键字参数。可以指定的参数是此类上的任何非方法属性,以及具体类上的所有其他非方法属性。在构造函数中指定的值将覆盖相应属性的默认值。
此类定义以下属性,因此可以在任何策略类的构造函数中传递以下内容的值:
max_line_length
linesep
- 用于终止串行化输出中的行的字符串。默认值是
\n
,因为这是 Python 使用的内部行尾规则,尽管 RFC 要求\r\n
。
- 用于终止串行化输出中的行的字符串。默认值是
cte_type
- 控制可能使用或要求使用的内容传输编码的类型。可能的值为:
7bit |
所有数据都必须为“ 7 位干净”(仅 ASCII)。这意味着必要的数据将使用带引号的可打印格式或 base64 编码进行编码。 |
8bit |
数据不限于 7 位整洁。Headers 中的数据仍然必须为纯 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_
3.5 版中的新Function:* mangle_from_ *参数。
message_factory
- 工厂函数,用于构造新的空消息对象。构建消息时由解析器使用。默认为
None
,在这种情况下使用Message。
- 工厂函数,用于构造新的空消息对象。构建消息时由解析器使用。默认为
3.6 版的新Function。
以下Policy方法旨在pass代码使用电子邮件库来调用,以创建具有自定义设置的策略实例:
clone
(*** kw *)- 返回一个新的Policy实例,该实例的属性与当前实例具有相同的值,除非这些属性由关键字参数赋予新的值。
其余的Policy方法由电子邮件程序包代码调用,而不是由使用电子邮件程序包的应用程序调用的。定制策略必须实现所有这些方法。
handle_defect
(* obj , defect *)- 处理在* obj 上发现的缺陷*。当电子邮件包调用此方法时,* defect *将始终是
Defect
的子类。
- 处理在* obj 上发现的缺陷*。当电子邮件包调用此方法时,* defect *将始终是
默认实现检查raise_on_defect标志。如果为True
,则引发* defect (异常)。如果它是False
(默认值),则将 obj 和 defect *传递给register_defect()。
register_defect
(* obj , defect *)- 在* obj 上注册一个 defect 。在电子邮件包中, defect *始终是
Defect
的子类。
- 在* obj 上注册一个 defect 。在电子邮件包中, defect *始终是
默认实现调用* obj 的defects
属性的append
方法。当电子邮件包调用handle_defect时, obj *通常将具有defects
属性,该属性具有append
方法。与电子邮件包一起使用的自定义对象类型(例如,自定义Message
对象)也应提供此类属性,否则,解析消息中的缺陷将引发意外错误。
header_max_count
(* name *)- 返回名为* name *的 Headers 的最大允许数量。
将 Headers 添加到EmailMessage或Message对象时调用。如果返回的值不是0
或None
,并且已经有多个 Headers* name *大于或等于返回的值,则引发ValueError。
因为Message.__setitem__
的默认行为是将值附加到 Headers 列表中,所以很容易创建重复的 Headers 而没有意识到。此方法允许将某些 Headers 限制为可以pass编程方式添加到Message
的该 Headers 的实例数。 (解析器未遵守该限制,解析器将忠实地生成与要解析的消息中存在的 Headers 一样多的 Headers.)
默认实现为所有 Headers 名称返回None
。
header_source_parse
(* sourcelines *)- 电子邮件包使用字符串列表来调用此方法,每个字符串都以要在源中找到的行分隔字符结尾。第一行包括字段标题名称和分隔符。源中的所有空格都将保留。该方法应返回
(name, value)
Tuples,该 Tuples 将存储在Message
中以表示已解析的 Headers。
- 电子邮件包使用字符串列表来调用此方法,每个字符串都以要在源中找到的行分隔字符结尾。第一行包括字段标题名称和分隔符。源中的所有空格都将保留。该方法应返回
如果实现希望保持与现有电子邮件软件包策略的兼容性,那么* name 应该是大小写保留的名称(所有字符,直到':
'分隔符),而 value *应该是展开的值(所有行分隔符都被删除) ,但空白保持不变),去除了前导空白。
源代码可能包含替代转义的二进制数据。
没有默认实现
header_store_parse
(* name , value *)- 当应用程序以编程方式修改
Message
时(与解析器创建的Message
相反),电子邮件软件包将使用应用程序提供的名称和值来调用此方法。该方法应返回(name, value)
Tuples,该 Tuples 将存储在Message
中以表示 Headers。
- 当应用程序以编程方式修改
如果实现希望保持与现有电子邮件软件包策略的兼容性,则* name 和 value *应该是不改变传入参数内容的字符串或字符串子类。
没有默认实现
header_fetch_parse
(* name , value *)- 当应用程序请求该 Headers 时,电子邮件软件包将使用当前存储在
Message
中的* name 和 value *来调用此方法,该方法返回的任何内容将作为 Headers 的值传递回应用程序检索。请注意,Message
中可能存储了多个同名标题;该方法将传递给 Headers 的特定名称和值,该 Headers 将被返回给应用程序。
- 当应用程序请求该 Headers 时,电子邮件软件包将使用当前存储在
- value *可能包含替代转义的二进制数据。该方法返回的值中不应包含替代转义的二进制数据。
没有默认实现
fold
(* name , value *)
- value *可能包含替代转义的二进制数据。该方法返回的字符串中不应包含替代转义的二进制数据。
fold_binary
(* name , value *)- 与fold()相同,除了返回的值应该是字节对象而不是字符串。
- value *可能包含替代转义的二进制数据。这些可以在返回的字节对象中转换回二进制数据。
- 类别
email.policy.
EmailPolicy
(*** kw *)
此策略添加了新的 Headers 解析和折叠算法。头不是简单的字符串,而是str
子类,其子属性取决于字段的类型。解析和折叠算法完全实现 RFC 2047和 RFC 5322。
message_factory属性的默认值为EmailMessage。
除了上面列出的适用于所有策略的可设置属性外,此策略还添加了以下其他属性:
3.6 版的新Function:[1]
utf8
refold_source
- 如果
Message
对象中 Headers 的值源自parser(而不是由程序设置),则此属性指示在将消息转换回序列化形式时,生成器是否应重新折叠该值。可能的值为:
- 如果
none |
所有源值均使用原始折叠 |
long |
任意行长于max_line_length 的源值将被重新折叠 |
all |
所有值都被重新折叠。 |
默认值为long
。
header_factory
- 具有两个参数
name
和value
的可调用对象,其中name
是 Headers 字段名称,value
是展开的 Headers 字段值,并返回表示该 Headers 的字符串子类。提供了默认的header_factory
(请参阅headerregistry),它支持针对各种地址和日期 RFC 5322Headers 字段类型以及主要的 MIMEHeaders 字段类型的自定义解析。将来将添加对其他自定义解析的支持。
- 具有两个参数
content_manager
- 具有至少两个方法的对象:get_content 和 set_content。调用EmailMessage对象的get_content()或set_content()方法时,它将调用此对象的相应方法,将消息对象作为其第一个参数传递给它,并将传递给它的所有参数或关键字作为附加参数传递给该对象。默认情况下,
content_manager
设置为raw_data_manager。
- 具有至少两个方法的对象:get_content 和 set_content。调用EmailMessage对象的get_content()或set_content()方法时,它将调用此对象的相应方法,将消息对象作为其第一个参数传递给它,并将传递给它的所有参数或关键字作为附加参数传递给该对象。默认情况下,
3.4 版的新Function。
该类提供了Policy的抽象方法的以下具体实现:
header_max_count
(* name *)- 返回专用类的max_count属性的值,该属性用于表示具有给定名称的 Headers。
header_source_parse
(* sourcelines *)- 该名称将被解析为直到“
:
”的所有内容,并且将返回未修改的名称。该值是pass以下方式确定的:从第一行的其余部分中去除前导空格,将所有后续行连接在一起,并去除所有尾随的回车符或换行符。
- 该名称将被解析为直到“
header_store_parse
(* name , value *)- 名称不变。如果 Importing 值具有
name
属性,并且匹配* name (忽略大小写),则该值将保持不变。否则,将 name 和 value *传递给header_factory
,并将返回的 Headers 对象作为值返回。在这种情况下,如果 Importing 值包含 CR 或 LF 字符,则会引发ValueError
。
- 名称不变。如果 Importing 值具有
header_fetch_parse
(* name , value *)- 如果该值具有
name
属性,则将其返回未修改状态。否则,将* name 和 value *除去所有 CR 或 LF 字符后,传递给header_factory
,并返回结果 Headers 对象。任何替代的转义字节都会变成 Unicode 未知字符字形。
- 如果该值具有
fold
(* name , value *)- 标题折叠由refold_source策略设置控制。当且仅当一个值没有
name
属性(具有name
属性表示它是某种标题对象)时,该值才被视为“源值”。如果需要根据策略重新折叠源值,则pass将* name 和 value *传递给header_factory
,并将任何 CR 和 LF 字符删除,将其转换为 Headers 对象。头对象的折叠是pass使用当前策略调用其fold
方法来完成的。
- 标题折叠由refold_source策略设置控制。当且仅当一个值没有
源值使用splitlines()分成几行。如果该值不被重新折叠,则使用策略中的linesep
重新合并这些行并返回。exception 是包含非 ASCII 二进制数据的行。在那种情况下,无论refold_source
设置如何,该值都会重新折叠,这会使二进制数据使用unknown-8bit
字符集进行 CTE 编码。
如果cte_type为8bit
,则将非 ASCII 二进制数据转换回字节。不管refold_header
设置如何,都不会重折叠带有二进制数据的 Headers,因为无法知道二进制数据是由单字节字符还是多字节字符组成。
以下EmailPolicy实例提供适用于特定应用程序域的默认值。请注意,将来可能会调整这些实例(尤其是HTTP
实例)的行为,以使其更接近与它们的域相关的 RFC。
email.policy.
default
EmailPolicy
的实例,所有默认设置不变。此策略使用标准的 Python\n
行结尾而不是 RFC 正确的\r\n
。
email.policy.
SMTP
- 适用于序列化符合电子邮件 RFC 的消息。类似于
default
,但将linesep
设置为\r\n
,这符合 RFC。
- 适用于序列化符合电子邮件 RFC 的消息。类似于
email.policy.
SMTPUTF8
- 与
SMTP
相同,除了utf8是True
。在不使用 Headers 中的编码字的情况下,将消息序列化到消息存储很有用。如果发件人或收件人地址包含非 ASCII 字符(smtplib.SMTP.send_message()方法会自动处理),则仅应用于 SMTP 传输。
- 与
email.policy.
HTTP
- 适用于序列化 Headers,以用于 HTTP 通信。类似于
SMTP
,但max_line_length
设置为None
(无限制)。
- 适用于序列化 Headers,以用于 HTTP 通信。类似于
email.policy.
strict
- 便利实例。与
default
相同,除了raise_on_defect
设置为True
。这样可以pass以下方式严格执行任何策略:
- 便利实例。与
somepolicy + policy.strict
使用所有这些EmailPolicies,电子邮件包的有效 API pass以下方式从 Python 3.2 API 进行了更改:
Note
从应用程序的角度来看,这意味着passEmailMessage获得的任何 Headers 都是具有附加属性的 Headers 对象,其字符串值是 Headers 的完全解码的 unicode 值。同样,可以使用 unicode 字符串为 Headers 分配一个新值或创建一个新的 Headers,并且该策略将负责将 unicode 字符串转换为正确的 RFC 编码形式。
Headers 对象及其属性在headerregistry中描述。
- 类别
email.policy.
Compat32
(*** kw *)
以下属性的值与Policy默认值不同:
mangle_from_
- 默认值为
True
。
- 默认值为
该类提供了Policy的抽象方法的以下具体实现:
header_source_parse
(* sourcelines *)- 该名称将被解析为直到“
:
”的所有内容,并且将返回未修改的名称。该值是pass以下方式确定的:从第一行的其余部分中去除前导空格,将所有后续行连接在一起,并去除所有尾随的回车符或换行符。
- 该名称将被解析为直到“
header_store_parse
(* name , value *)- 名称和值未经修改就返回。
header_fetch_parse
(* name , value *)- 如果该值包含二进制数据,则使用
unknown-8bit
字符集将其转换为Header对象。否则,将返回原样。
- 如果该值包含二进制数据,则使用
fold
(* name , value *)- 使用Header折叠算法可折叠标题,该算法保留值中现有的换行符,并将每个结果行包装到
max_line_length
。非 ASCII 二进制数据使用unknown-8bit
字符集进行 CTE 编码。
- 使用Header折叠算法可折叠标题,该算法保留值中现有的换行符,并将每个结果行包装到
fold_binary
(* name , value *)- 使用Header折叠算法可折叠标题,该算法保留值中现有的换行符,并将每个结果行包装到
max_line_length
。如果cte_type
是7bit
,则使用unknown-8bit
字符集对非 ASCII 二进制数据进行 CTE 编码。否则,将使用原始源 Headers 及其现有的换行符及其可能包含的任何(RFC 无效)二进制数据。
- 使用Header折叠算法可折叠标题,该算法保留值中现有的换行符,并将每个结果行包装到
email.policy.
compat32
- Compat32的实例,向后兼容 Python 3.2 中电子邮件包的行为。
Footnotes
- [1]
- 最初在 3.3 中添加为provisional feature。