19.1.4. email.policy:Policy Objects

版本3.3中的新功能。

源代码: Lib / email / policy.py

email包的首要关注点是处理电子邮件,如各种电子邮件和MIME RFC所述。然而,电子邮件消息的一般格式(每个标题字段的块由名称后跟冒号后跟一个值,整个块后跟空白行和任意“主体”)的格式是已经找到的格式实用程序在电子邮件领域之外。这些用途中的一些与主要RFC相当相近,一些不使用。即使使用电子邮件,有时也需要严格遵守RFC。

策略对象为电子邮件包提供了处理所有这些不同用例的灵活性。

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

电子邮件包中的所有类都使用默认策略。此策略名为Compat32,具有对应的预定义实例名为compat32它提供与Python3.3版本的电子邮件包完全向后兼容(在某些情况下,包括错误兼容性)。

本文档的第一部分介绍了Policy的功能,abstract base class,定义了所有策略对象共有的功能,包括compat32这包括由电子邮件包内部调用的某些挂接方法,自定义策略可以覆盖以获取不同的行为。

当创建Message对象时,它会获取策略。默认情况下,这将是compat32,但可以指定不同的策略。如果Message是由parser创建的,则传递给解析器的策略将是它创建的Message使用的策略。如果程序创建了Message,则可以在创建策略时指定策略。Message传递到generator时,生成器默认使用Message中的策略,但您也可以传递特定策略生成器将覆盖存储在Message对象上的。

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在创建二进制字符串时使用RFC正确的行分隔字符,以便将sendmail's stdin使用\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)

这是所有策略类的abstract base class它提供了几个平凡方法的默认实现,以及immutability属性,clone()方法和构造函数语义的实现。

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

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

max_line_length

序列化输出中任何行的最大长度,不计算行结束字符。默认值为78,每个 RFC 53220None表示根本不应进行换行。

linesep

用于终止序列化输出中的行的字符串。默认值为\n,因为这是Python使用的内部结束规则,虽然RFC需要\r\n

cte_type

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

7bit所有数据必须是“7位清除”(仅限ASCII)。这意味着在必要的数据将使用quoted-printable或base64编码进行编码。
8bit数据不被约束为7位清洁。头部中的数据仍然需要是仅ASCII,因此将被编码(见下面的'binary_fold'异常),但身体部分可以使用8bit CTE。

8bitcte_type值仅适用于BytesGenerator,而不适用于Generator,因为字符串不能包含二进制数据。如果Generator在指定cte_type=8bit的策略下运行,则它将表现为cte_type7bit

raise_on_defect

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

mangle_from_

如果True,则通过在其前面放置>来转义主体中以“From”当消息被生成器序列化时,使用此参数。默认值:False

版本3.5中的新功能: mangle_from _参数。

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

clone(**kw)

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

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

handle_defect(obj, defect)

处理obj上发现的缺陷当电子邮件包调用此方法时,defect将始终是Defect的子类。

默认实现检查raise_on_defect标志。如果它True,则作为异常引发缺陷如果是False(默认值),则将obj缺陷传递给register_defect()

register_defect(obj, defect)

obj上注册缺陷在电子邮件包中,defect将始终是Defect的子类。

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

header_max_count(name)

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

当标头添加到Message对象时调用。如果返回值不是0None,并且已有一些名为name的头等于返回的值,则ValueError

因为Message.__setitem__的默认行为是将值附加到标题列表,所以很容易创建重复的标题而不意识到它。此方法允许某些头部在可以以编程方式添加到Message的头部实例数量上受到限制。(解析器不会观察到该限制,这将忠实地产生与解析的消息中存在的标头一样多的头)。

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

header_source_parse(sourcelines)

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

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

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

没有默认实现

header_store_parse(name, value)

当应用程序以编程方式修改Message(与解析器创建的Message相反)时,电子邮件包使用应用程序提供的名称和值调用此方法。 。该方法应该返回要存储在Message中的(名称, 值) 标题。

如果实现希望保留与现有电子邮件包策略的兼容性,则名称应为不更改传递的参数的内容的字符串或字符串子类。

没有默认实现

header_fetch_parse(name, value)

当应用程序请求该标题时,电子邮件包使用当前存储在Message中的名称调用此方法,方法返回是作为要检索的头的值传递回应用程序的内容。请注意,在Message中可能存在多个具有相同名称的标头;该方法将传递要返回给应用程序的头的特定名称和值。

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

没有默认实现

fold(name, value)

电子邮件包使用当前存储在给定标题的Message中的名称来调用此方法。该方法应通过使用组合名称并插入linesep有关折叠电子邮件标头的规则的讨论,请参见 RFC 5322

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

fold_binary(name, value)

fold()相同,但返回的值应为字节对象,而不是字符串。

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

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)

如果值包含二进制数据,则使用unknown-8bit字符集将其转换为Header对象。否则返回未修改。

fold(name, value)

使用Header折叠算法折叠标头,该算法会保留值中的现有换行符,并将每个生成的行换行到max_line_length非ASCII二进制数据使用unknown-8bit字符集进行CTE编码。

fold_binary(name, value)

使用Header折叠算法折叠标头,该算法会保留值中的现有换行符,并将每个生成的行换行到max_line_length如果cte_type7bit,则使用unknown-8bit字符集对非ASCII二进制数据进行CTE编码。否则,将使用原始源标头,其中包含现有的换行符和任何(RFC无效的)二进制数据。

提供Compat32的实例作为模块常数:

email.policy.compat32

Compat32的实例,提供与Python 3.2中的电子邮件包行为的向后兼容性。

注意

以下文档介绍了provisional basis中包含在标准库中的新策略。如果核心开发人员认为有必要,可能会发生向后不兼容的更改(直到并包括删除该功能部件)。

class email.policy.EmailPolicy(**kw)

此具体的Policy提供了旨在完全符合当前电子邮件RFC的行为。这些包括(但不限于) RFC 5322 RFC 2047和当前MIME RFC。

此策略添加新的标头解析和折叠算法。取代简单字符串,标头是str子类,其属性取决于字段的类型。解析和折叠算法完全实现 RFC 2047 RFC 5322

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

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

具有namevalue两个参数的可调用项,其中name是头字段名称,value是展开的头字段值,并返回表示该头的字符串子类。提供了理解一些 RFC 5322头字段类型的默认header_factory(请参阅headerregistry)。(目前地址字段和日期字段有特殊处理,而所有其他字段被视为非结构化。此列表将在扩展程序标记为稳定之前完成。)

content_manager

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

版本3.4中的新功能。

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

header_max_count(name)

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

header_source_parse(sourcelines)

此方法的实现与Compat32策略的实现相同。

header_store_parse(name, value)

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

header_fetch_parse(name, value)

如果值具有name属性,则返回未修改。否则,将除去了任何CR或LF字符的名称传递到header_factory,并返回生成的标题对象。任何代理转义的字节变成unicode未知字符字形。

fold(name, value)

标题折叠由refold_source策略设置控制。当且仅当它没有name属性(具有name属性意味着它是某种类型的头对象)时,该值被认为是“源值” )。如果源值需要根据策略重新折叠,则通过将除去了任何CR和LF字符的名称传递给header_factory通过使用当前策略调用其fold方法来折叠标题对象。

源值使用splitlines()分为几行。如果值不重新折叠,则使用策略中的linesep重新连接行并返回。异常是包含非ascii二进制数据的行。在这种情况下,无论refold_source设置如何,都会重新折叠值,这会导致二进制数据使用unknown-8bit字符集进行CTE编码。

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字符(smtplib.SMTP.send_message()方法自动处理此字符),则应仅用于SMTP传输。

email.policy.HTTP

适用于串行化标头以用于HTTP流量。SMTP除了max_line_length设置为None(无限制)。

email.policy.strict

方便实例。除了raise_on_defect设置为True,与default相同。这允许任何政策通过写作严格:

somepolicy + policy.strict

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

  • Setting a header on a Message results in that header being parsed and a header object created.
  • Fetching a header value from a Message results in that header being parsed and a header object created and returned.
  • Any header object, or any header that is refolded due to the policy settings, is folded using an algorithm that fully implements the RFC folding algorithms, including knowing where encoded words are required and allowed.

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

头对象及其属性在headerregistry中描述。