email.headerregistry
: 自定义标头对象¶
源代码: Lib/email/headerregistry.py
3.6 版本新增: [1]
标头由 str
的自定义子类表示。用于表示给定标头的特定类由创建标头时生效的 header_factory
的 policy
确定。本节记录了 email 包为处理符合 RFC 5322 的电子邮件消息而实现的特定 header_factory
,它不仅为各种标头类型提供了自定义标头对象,还为应用程序提供了扩展机制来添加其自己的自定义标头类型。
当使用任何从 EmailPolicy
派生的 policy 对象时,所有标头都由 HeaderRegistry
生成,并且以 BaseHeader
作为它们的最后一个基类。每个标头类都有一个附加的基类,该基类由标头的类型确定。例如,许多标头都有 UnstructuredHeader
类作为它们的另一个基类。标头的专门化第二个类由标头的名称确定,使用存储在 HeaderRegistry
中的查找表。所有这些都为典型的应用程序程序透明地管理,但提供了接口来修改默认行为,供更复杂的应用程序使用。
以下各节首先记录标头基类及其属性,然后是修改 HeaderRegistry
行为的 API,最后是用于表示从结构化标头解析的数据的支持类。
- class email.headerregistry.BaseHeader(name, value)¶
name 和 value 从
header_factory
调用传递给BaseHeader
。任何标头对象的字符串值都是完全解码为 unicode 的 value。此基类定义以下只读属性
- name¶
标头的名称(字段中 ‘:’ 之前的部分)。这正是为 name 在
header_factory
调用中传递的值;也就是说,保留了大小写。
- defects¶
HeaderDefect
实例的元组,报告在解析期间发现的任何 RFC 合规性问题。email 包尝试完全检测合规性问题。有关可能报告的缺陷类型,请参阅errors
模块。
- max_count¶
此类型标头可以具有相同
name
的最大数量。None
值表示无限制。此属性的BaseHeader
值为None
;预期专门化的标头类将根据需要覆盖此值。
BaseHeader
还提供了以下方法,该方法由 email 库代码调用,通常不应由应用程序程序调用- fold(*, policy)¶
返回一个字符串,其中包含
linesep
字符,以便根据 policy 正确折叠标头。cte_type
为8bit
将被视为7bit
,因为标头可能不包含任意二进制数据。如果utf8
为False
,则非 ASCII 数据将进行 RFC 2047 编码。
BaseHeader
本身不能用于创建标头对象。它定义了每个专门的标头为生成标头对象而与之协作的协议。具体来说,BaseHeader
要求专门化的类提供一个名为parse
的classmethod()
。此方法按如下方式调用parse(string, kwds)
kwds
是一个字典,其中包含一个预初始化的键defects
。defects
是一个空列表。parse 方法应将检测到的任何缺陷附加到此列表。返回时,kwds
字典必须包含至少键decoded
和defects
的值。decoded
应为标头的字符串值(即,完全解码为 unicode 的标头值)。parse 方法应假定 string 可能包含内容传输编码的部分,但应正确处理所有有效的 unicode 字符,以便它可以解析未编码的标头值。BaseHeader
的__new__
然后创建标头实例,并调用其init
方法。如果专门的类希望设置BaseHeader
本身提供的属性之外的其他属性,则只需提供init
方法。这样的init
方法应如下所示def init(self, /, *args, **kw): self._myattr = kw.pop('myattr') super().init(*args, **kw)
也就是说,专门的类放入
kwds
字典中的任何额外内容都应删除并处理,并且将kw
(和args
)的剩余内容传递给BaseHeader
init
方法。
- class email.headerregistry.UnstructuredHeader¶
“非结构化”标头是 RFC 5322 中的默认标头类型。任何没有指定语法的标头都视为非结构化标头。非结构化标头的经典示例是 Subject 标头。
在 RFC 5322 中,非结构化头部是在 ASCII 字符集中运行的任意文本。RFC 2047 提供了一种 RFC 5322 兼容的机制,用于在头部值中将非 ASCII 文本编码为 ASCII 字符。当包含编码词的值传递给构造函数时,
UnstructuredHeader
解析器会根据 RFC 2047 中非结构化文本的规则,将这些编码词转换为 Unicode。解析器使用启发式方法尝试解码某些不符合规范的编码词。在这种情况下会注册缺陷,以及在编码词或非编码文本中存在无效字符等问题的缺陷。此头部类型不提供其他属性。
- class email.headerregistry.DateHeader¶
RFC 5322 为电子邮件头部中的日期指定了非常具体的格式。
DateHeader
解析器可以识别该日期格式,并识别有时在“实际应用中”发现的许多变体形式。此头部类型提供以下附加属性
- datetime¶
如果头部值可以被识别为某种形式的有效日期,则此属性将包含一个
datetime
实例,表示该日期。如果输入日期的时区指定为-0000
(表示它在 UTC 中,但不包含有关源时区的任何信息),则datetime
将是一个朴素的datetime
。如果找到特定的时区偏移量(包括+0000
),则datetime
将包含一个感知时区的datetime
,它使用datetime.timezone
来记录时区偏移量。
头部的
decoded
值由根据 RFC 5322 规则格式化datetime
来确定;也就是说,它被设置为email.utils.format_datetime(self.datetime)
创建
DateHeader
时,value 可以是datetime
实例。这意味着,例如,以下代码是有效的并且可以按预期工作msg['Date'] = datetime(2011, 7, 15, 21)
因为这是一个朴素的
datetime
,它将被解释为 UTC 时间戳,并且结果值将具有-0000
的时区。更有用的是使用来自utils
模块的localtime()
函数msg['Date'] = utils.localtime()
此示例使用当前时区偏移量将日期头部设置为当前时间和日期。
- class email.headerregistry.AddressHeader¶
地址头部是最复杂的结构化头部类型之一。
AddressHeader
类为任何地址头部提供通用接口。此头部类型提供以下附加属性
- groups¶
一个
Group
对象的元组,用于编码头部值中找到的地址和组。不属于组的地址在此列表中表示为单地址Groups
,其display_name
为None
。
- addresses¶
一个
Address
对象的元组,用于编码头部值中的所有单独地址。如果头部值包含任何组,则组中的各个地址将包含在列表中,该列表位于该组在值中出现的位置(也就是说,地址列表被“扁平化”为一维列表)。
头部的
decoded
值将所有编码词解码为 Unicode。idna
编码的域名也被解码为 Unicode。decoded
值由 拼接groups
属性的元素的str
值和', '
来设置。任何组合中的
Address
和Group
对象的列表可用于设置地址头部的值。display_name
为None
的Group
对象将被解释为单个地址,这允许通过使用从源头部的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¶
MIME 标头都以 ‘Content-’ 前缀开头。每个特定的标头都有一个特定的值,该值在相应标头的类下描述。有些标头还可以接受一系列补充参数,这些参数具有通用格式。此类别作为所有接受参数的 MIME 标头的基类。
- params¶
一个字典,将参数名称映射到参数值。
- class email.headerregistry.ContentTypeHeader¶
一个
ParameterizedMIMEHeader
类,用于处理 Content-Type 标头。- content_type¶
内容类型字符串,格式为
maintype/subtype
。
- maintype¶
- subtype¶
- class email.headerregistry.ContentDispositionHeader¶
一个
ParameterizedMIMEHeader
类,用于处理 Content-Disposition 标头。- content_disposition¶
inline
和attachment
是常用的唯二有效值。
- class email.headerregistry.ContentTransferEncoding¶
处理 Content-Transfer-Encoding 标头。
- class email.headerregistry.HeaderRegistry(base_class=BaseHeader, default_class=UnstructuredHeader, use_default_map=True)¶
这是
EmailPolicy
默认使用的工厂。HeaderRegistry
使用 base_class 和从其保存的注册表中检索的专用类动态构建用于创建标头实例的类。当给定的标头名称未出现在注册表中时,由 default_class 指定的类将用作专用类。当 use_default_map 为True
(默认值)时,标头名称到类的标准映射将在初始化期间复制到注册表中。 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
- bcc:
UniqueAddressHeader
- resent-bcc:
AddressHeader
- from:
UniqueAddressHeader
- resent-from:
AddressHeader
- reply-to:
UniqueAddressHeader
- mime-version:
MIMEVersionHeader
- content-type:
ContentTypeHeader
- content-disposition:
ContentDispositionHeader
- content-transfer-encoding:
ContentTransferEncodingHeader
- message-id:
MessageIDHeader
HeaderRegistry
具有以下方法- map_to_type(self, name, cls)¶
name 是要映射的标头的名称。它将在注册表中转换为小写。 cls 是要使用的专用类,与 base_class 一起使用,以创建用于实例化与 name 匹配的标头的类。
- __getitem__(name)¶
构造并返回一个用于处理创建 name 标头的类。
- __call__(name, value)¶
从注册表中检索与 name 关联的专用标头(如果 name 未出现在注册表中,则使用 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 而不是 username 和 domain,在这种情况下,将从 addr_spec 解析 username 和 domain。 addr_spec 必须是正确 RFC 引用的字符串;如果不是,
Address
将引发错误。允许使用 Unicode 字符,并且在序列化时将正确编码。但是,根据 RFC,Unicode 不允许在地址的用户名部分中使用。- display_name¶
地址的显示名称部分(如果有),删除所有引号。如果地址没有显示名称,则此属性将为空字符串。
- username¶
地址的
username
部分,删除所有引号。
- domain¶
地址的
domain
部分。
- addr_spec¶
地址的
username@domain
部分,正确引用以用作裸地址(如上所示的第二种形式)。此属性是不可变的。
为了支持 SMTP (RFC 5321),
Address
处理一种特殊情况:如果username
和domain
都是空字符串(或None
),则Address
的字符串值为<>
。
- class email.headerregistry.Group(display_name=None, addresses=None)¶
用于表示地址组的类。地址组的一般形式为
display_name: [address-list];
为了方便处理由组和单个地址混合组成的地址列表,
Group
也可以通过将 display_name 设置为None
并提供单个地址列表作为 addresses 来表示不属于组的单个地址。- display_name¶
组的
display_name
。如果为None
且addresses
中恰好有一个Address
,则Group
表示不属于组的单个地址。
脚注