19.1.5. email.headerregistry:自定义标题对象

版本3.3中的新功能:作为provisional module

源代码: Lib / email / headerregistry.py

注意

标头库模块已在provisional basis如果核心开发人员认为有必要,可能会发生向后不兼容的更改(直到并包括删除模块)。

标题由str的自定义子类表示。用于表示给定报头的特定类由创建报头时有效的policyheader_factory确定。本节记录电子邮件包实现的用于处理符合 RFC 5322的电子邮件的特定header_factory,它不仅为各种标题提供自定义标题对象类型,而且还为应用程序提供了一种扩展机制,以添加自己的自定义标题类型。

当使用从EmailPolicy派生的任何策略对象时,所有头都由HeaderRegistry生成,并且具有BaseHeader作为它们的最后一个基类。每个头类都有一个额外的基类,由头类型决定。例如,许多头都有UnstructuredHeader类作为它们的其他基类。头的专用第二类由头的名称确定,使用存储在HeaderRegistry中的查找表。所有这些对于典型的应用程序是透明地管理的,但是提供了用于修改默认行为的接口以供更复杂的应用使用。

下面的部分首先记录头部基类及其属性,然后是用于修改HeaderRegistry的行为的API,最后是用于表示从结构化头部解析的数据的支持类。

class email.headerregistry.BaseHeader(name, value)

名称header_factory调用传递到BaseHeader任何头对象的字符串值是完全解码为unicode。

此基类定义以下只读属性:

name

标题的名称(“:”前的字段部分)。这正是在header_factory调用名称中传递的值;也就是说,情况被保留。

defects

HeaderDefect实例的元组,报告在解析期间发现的任何RFC合规性问题。电子邮件包尝试完全关于检测合规性问题。有关可能报告的缺陷类型的讨论,请参见errors模块。

max_count

此类型的标头的最大数量,可以具有相同的nameNone表示无限制。此属性的BaseHeader值为None;预期专用头部类将根据需要覆盖此值。

BaseHeader还提供以下方法,该方法由电子邮件库代码调用,并且一般不应用程序调用:

fold(*, policy)

根据需要返回包含linesep字符的字符串,以根据策略正确折叠标题。8bitcte_type将被视为7bit,因为字符串可能不包含二进制数据。

BaseHeader本身不能用于创建标题对象。它定义了每个专用报头协作以便产生报头对象的协议。具体来说,BaseHeader要求专用类提供一个名为parseclassmethod()此方法的调用如下:

parse(string, kwds)

kwds是包含一个预初始化键,defects的字典。defects是一个空列表。解析方法应该将任何检测到的缺陷附加到此列表。返回时,kwds字典必须包含至少键decodeddefects的值。decoded应为标头的字符串值(即,标头值完全解码为unicode)。解析方法应假设string可能包含传输编码部分,但应正确处理所有有效的unicode字符,以便它可以解析未编码的标头值。

BaseHeader__new__然后创建头实例,并调用其init方法。如果希望设置超出由BaseHeader本身提供的属性的附加属性,专用类只需要提供init方法。这样的init方法应该是这样的:

def init(self, *args, **kw):
    self._myattr = kw.pop('myattr')
    super().init(*args, **kw)

That is, anything extra that the specialized class puts in to the kwds dictionary should be removed and handled, and the remaining contents of kw (and args) passed to the BaseHeader init method.

class email.headerregistry.UnstructuredHeader

“非结构化”报头是 RFC 5322中默认的报头类型。任何没有指定语法的头都被视为非结构化头。非结构化报头的典型示例是主题报头。

RFC 5322中,非结构化报头是ASCII字符集中任意文本的一串。然而, RFC 2047有一个 RFC 5322兼容机制,用于将非ASCII文本编码为ASCII字符头值。When a value containing encoded words is passed to the constructor, the UnstructuredHeader parser converts such encoded words back in to the original unicode, following the RFC 2047 rules for unstructured text. 解析器使用启发法来尝试解码某些不兼容的编码字。在这种情况下注册缺陷,以及诸如编码字或非编码文本中的无效字符的问题的缺陷。

此标题类型不提供其他属性。

class email.headerregistry.DateHeader

RFC 5322指定电子邮件标头中的日期的非常具体的格式。DateHeader解析器识别日期格式,以及识别有时在“野外”中找到的许多变体形式。

此标题类型提供以下附加属性:

datetime

如果标头值可以被识别为一种形式或另一种形式的有效日期,则此属性将包含表示该日期的datetime实例。如果输入日期的时区指定为-0000(表示它在UTC中,但不包含有关源时区的信息),则datetime将是一个初始datetimeIf a specific timezone offset is found (including +0000), then datetime will contain an aware datetime that uses datetime.timezone to record the timezone offset.

The decoded value of the header is determined by formatting the datetime according to the RFC 5322 rules; that is, it is set to:

email.utils.format_datetime(self.datetime)

当创建DateHeader时,可能是datetime实例。这意味着,例如,下面的代码是有效的,并做什么期望:

msg['Date'] = datetime(2011, 7, 15, 21)

因为这是一个天真的datetime,它将被解释为UTC时间戳,并且结果值将具有-0000的时区。更有用的是使用utils模块中的localtime()函数:

msg['Date'] = utils.localtime()

此示例使用当前时区偏移将日期标题设置为当前时间和日期。

class email.headerregistry.AddressHeader

地址头是最复杂的结构化头类型之一。AddressHeader类为任何地址头提供通用接口。

此标题类型提供以下附加属性:

groups

用于编码在标头值中找到的地址和组的Group对象的元组。不是组的一部分的地址在此列表中表示为display_nameNone的单地址Groups

addresses

Address的元组,用于对标头值中的所有单个地址进行编码。如果标题值包含任何组,则来自组的单个地址将包含在列表中该值出现的点(即,地址列表“展平”为一维列表)中。

头的decoded值将所有编码字解码为unicode。idna编码的域名也被解码为unicode。The decoded value is set by joining the str value of the elements of the groups attribute with ', '.

任何组合中的AddressGroup对象的列表可用于设置地址头的值。display_nameNoneGroup对象将被解释为单个地址,这允许使用获得的列表完整地复制地址列表groups属性。

class email.headerregistry.SingleAddressHeader

AddressHeader的子类添加了一个附加属性:

address

由标头值编码的单个地址。如果标头值实际上包含多个地址(这将违反默认的policy下的RFC),访问此属性将导致ValueError

上述许多类都有一个Unique变体(例如,UniqueUnstructuredHeader)。唯一的区别是在Unique变体中,max_count设置为1。

class email.headerregistry.MIMEVersionHeader

对于MIME-Version头只有一个有效值,即1.0为了将来校验,此标题类支持其他有效的版本号。如果版本号对于 RFC 2045具有有效值,则头对象将具有以下属性的非None值:

version

版本号作为字符串,删除任何空格和/或注释。

major

主版本号作为整数

minor

次版本号作为整数

class email.headerregistry.ParameterizedMIMEHeader

MOME标题都以前缀“Content-”开头。每个特定头具有某个值,在该头的类下描述。一些还可以采取补充参数的列表,其具有通用格式。此类充当所有接收参数的MIME头的基础。

params

将参数名称映射到参数值的字典。

class email.headerregistry.ContentTypeHeader

处理Content-Type头的ParameterizedMIMEHeader类。

content_type

内容类型字符串,形式为maintype/subtype

maintype
subtype
class email.headerregistry.ContentDispositionHeader

处理Content-Disposition头的ParameterizedMIMEHeader类。

content-disposition

inlineattachment是唯一有效的常用值。

class email.headerregistry.ContentTransferEncoding

处理Content-Transfer-Encoding头。

cte

有效值为7bit8bitbase64quoted-printable有关详细信息,请参阅 RFC 2045

class email.headerregistry.HeaderRegistry(base_class=BaseHeader, default_class=UnstructuredHeader, use_default_map=True)

这是EmailPolicy默认使用的工厂。HeaderRegistry使用base_class和从其保存的注册表检索的专门类来动态构建用于创建标题实例的类。当给定的头名称未出现在注册表中时,由default_class指定的类用作专用类。use_default_mapTrue(默认值)时,头域名到类的标准映射将在初始化期间复制到注册表中。base_class始终是生成类的__bases__列表中的最后一个类。

默认映射为:

subject:UniqueUnstructuredHeader
date:UniqueDateHeader
resent-date:DateHeader
orig-date:UniqueDateHeader
sender:UniqueSingleAddressHeader
resent-sender:SingleAddressHeader
to:UniqueAddressHeader
resent-to:AddressHeader
cc:UniqueAddressHeader
resent-cc:AddressHeader
from:UniqueAddressHeader
resent-from:AddressHeader
reply-to:UniqueAddressHeader

HeaderRegistry有以下方法:

map_to_type(self, name, cls)

name是要映射的头的名称。它将在注册表中转换为小写。cls是要使用的专用类,与base_class一起创建用于实例化与名称匹配的标题的类。

__getitem__(name)

构造并返回一个类来处理创建名称头。

__call__(name, value)

从注册表中检索与名称相关联的专用标头(如果名称未出现在注册表中,则使用default_class)并使用base_class生成一个类,调用构造的类的构造函数,传递它相同的参数列表,最后返回实例创建的类。

以下类是用于表示从结构化头部解析的数据的类,并且通常可以由应用程序用来构造结构化值以分配给特定头部。

class email.headerregistry.Address(display_name='', username='', domain='', addr_spec=None)

用于表示电子邮件地址的类。地址的一般形式是:

[display_name] <username@domain>

要么:

username@domain

其中每个部分必须符合在 RFC 5322中阐明的特定语法规则。

为方便起见,可以指定addr_spec而不是用户名,在这种情况下用户名将从addr_spec解析。addr_spec必须是RFC引用的字符串;如果不是Address将引发错误。允许使用Unicode字符,并且在序列化时将进行属性编码。但是,根据RFC,unicode在地址的用户名部分中不允许

display_name

地址的显示名称部分(如果有),删除所有引用。如果地址没有显示名称,则此属性将为空字符串。

username

地址的username部分,删除所有引用。

domain

地址的domain部分。

addr_spec

正确地引用地址的username@domain部分,用作裸地址(上面显示的第二个表单)。此属性不可变。

__str__()

对象的str值是根据 RFC 5322规则引用的地址,但没有任何非ASCII字符的内容传输编码。

To support SMTP (RFC 5321), Address handles one special case: if username and domain are both the empty string (or None), then the string value of the Address is <>.

class email.headerregistry.Group(display_name=None, addresses=None)

用于表示地址组的类。地址组的一般形式是:

display_name: [address-list];

为了方便处理由组和单个地址的混合组成的地址的列表,还可以使用Group来表示不是组的一部分的单个地址,通过将display_name 到None并提供单个地址的列表作为地址

display_name

组的display_name如果None且在addresses中只有一个Address,则Group不在一个组。

addresses

表示组中地址的Address对象的可能为空的元组。

__str__()

根据 RFC 5322格式化Groupstr值,但没有任何非-ASCII字符。如果display_name为none且在addresses列表中有单个Address,则str作为单个Addressstr