email.headerregistry:自定义标题对象

源代码: Lib/email/headerregistry.py


3.6 版的新Function:[1]

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

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

以下各节首先介绍 HeadersBase Class 及其属性,然后介绍用于修改HeaderRegistry行为的 API,最后介绍用于表示从结构化 Headers 解析的数据的支持类。

  • 类别 email.headerregistry. BaseHeader(名称)
    • 名称header_factory调用传递到BaseHeader。任何 Headers 对象的字符串值都是完全解码为 unicode 的* value *。

该 Base Class 定义以下只读属性:

  • name

    • Headers 名称(“:”之前的字段部分)。这正是在header_factory调用中为* name *传递的值;也就是说,保留大小写。
  • defects

    • HeaderDefect个实例的 Tuples 报告在解析过程中发现的所有 RFC 合规性问题。该电子邮件软件包试图完整地检测出合规性问题。有关可能报告的缺陷类型的讨论,请参见errors模块。
  • max_count

    • 可以具有相同name的此类型的头的最大数量。值None表示无限制。该属性的BaseHeader值为None;期望专门的 Headers 类将根据需要覆盖此值。

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

  • fold(** policy *)
    • 返回一个包含linesep个字符的字符串,以根据* policy *正确折叠标题。 8bitcte_type将被视为7bit,因为 Headers 可能不包含任意二进制数据。如果utf8False,则非 ASCII 数据将被 RFC 2047编码。

BaseHeader本身不能用于创建头对象。它定义了每个专用 Headers 与之配合以生成 Headers 对象的协议。具体来说,BaseHeader要求专门的类提供名为parseclassmethod()。此方法称为:

parse(string, kwds)

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

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方法。

  • 类别 email.headerregistry. UnstructuredHeader
    • “非结构化”Headers 是 RFC 5322中 Headers 的默认类型。没有指定语法的任何 Headers 都被视为非结构化。非结构化 Headers 的经典示例是* Subject *Headers。

RFC 5322中,非结构化标题是 ASCII 字符集中的任意文本。 RFC 2047但是具有 RFC 5322兼容机制,用于将非 ASCII 文本编码为 Headers 值内的 ASCII 字符。当将包含编码单词的“值”传递给构造函数时,UnstructuredHeader解析器将按照非结构化文本的 RFC 2047规则将此类编码单词转换为 unicode。解析器使用试探法try对某些不符合要求的编码字进行解码。在这种情况下,会记录缺陷以及诸如编码字或非编码文本中无效字符之类的问题的缺陷。

此 Headers 类型不提供其他属性。

  • 类别 email.headerregistry. DateHeader
    • RFC 5322为电子邮件标题中的日期指定了非常特定的格式。 DateHeader解析器识别该日期格式,并识别有时在“野外”发现的多种变体形式。

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

  • datetime
    • 如果 Headers 值可以识别为一种或另一种形式的有效日期,则此属性将包含一个表示该日期的datetime实例。如果将 Importing 日期的时区指定为-0000(表示采用 UTC 格式,但不包含有关源时区的信息),则datetime将是天真的datetime。如果找到了特定的时区偏移量(包括 0000),则datetime将包含一个感知的datetime,该datetime使用datetime.timezone记录时区偏移量。

Headers 的decoded值是pass根据 RFC 5322规则格式化datetime来确定的;也就是说,它设置为:

email.utils.format_datetime(self.datetime)

创建DateHeader时,* value *可能是datetime实例。例如,这意味着以下代码有效,并且可以完成预期的工作:

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

因为这是天真的datetime,它将被解释为 UTC 时间戳,并且所得值的时区为-0000。更有用的是使用utils模块中的localtime()Function:

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

本示例使用当前时区偏移量将日期 Headers 设置为当前时间和日期。

  • 类别 email.headerregistry. AddressHeader
    • 地址头是最复杂的结构化头类型之一。 AddressHeader类为任何地址 Headers 提供了通用接口。

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

  • groups

    • Group个对象的 Tuples,对在 Headers 值中找到的地址和组进行编码。不属于组的地址在此列表中表示为display_nameNone的单地址Groups
  • addresses

    • Address个对象的 Tuples 对 Headers 值中的所有单个地址进行编码。如果 Headers 值包含任何组,则该组中各个地址将在值中出现该组的点处包含在列表中(即,地址列表被“展平”为一维列表)。

Headers 的decoded值会将所有编码的字解码为 unicode。 idna编码的域名也被解码为 unicode。 decoded的值是pass__ groups属性的元素str值和', '来设置的。

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

  • 类别 email.headerregistry. SingleAddressHeader

  • address

    • Headers 值编码的单个地址。如果 Headers 值实际上包含多个地址(默认情况下policy违反了 RFC),则访问此属性将导致ValueError

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

  • 类别 email.headerregistry. MIMEVersionHeader

      • MIME-Version *Headers 实际上只有一个有效值,即1.0。为了将来验证,此 Headers 类支持其他有效的版本号。如果版本号的有效值是 RFC 2045,则 Headers 对象的以下属性将具有非None的值:
  • version

    • 版本号为字符串,其中删除了所有空格和/或 Comments。
  • major

    • 主版本号为整数
  • minor

    • 次要版本号作为整数
  • 类别 email.headerregistry. ParameterizedMIMEHeader

    • MIMEHeaders 均以前缀“ Content-”开头。每个特定的 Headers 都有一个特定的值,该值在该 Headers 的类下描述。有些还可以采用一系列补充参数,这些参数具有通用格式。此类用作所有带有参数的 MIMEHeaders 的基础。
  • params

    • 将参数名称 Map 到参数值的字典。
  • 类别 email.headerregistry. ContentTypeHeader

  • content_type

    • Content Type 字符串,格式为maintype/subtype
  • maintype

  • subtype

  • 类别 email.headerregistry. ContentDispositionHeader

  • content-disposition

    • inlineattachment是唯一常用的有效值。
  • 类别 email.headerregistry. ContentTransferEncoding

    • 处理* Content-Transfer-Encoding *Headers。
  • cte

    • 有效值为7bit8bitbase64quoted-printable。有关更多信息,请参见 RFC 2045
    • class * email.headerregistry. HeaderRegistry(* base_class = BaseHeader default_class = UnstructuredHeader use_default_map = True *)
    • 默认情况下,这是EmailPolicy使用的工厂。 HeaderRegistry使用* base_class 和从其持有的注册表中检索到的专用类,构建用于动态创建 Headers 实例的类。当给定的 Headers 名称未出现在注册表中时, default_class 指定的类将用作专用类。当 use_default_map *为True(默认值)时,Headers 名称到类的标准 Map 在初始化期间复制到注册表中。 * base_class *始终是生成的类的__bases__列表中的最后一个类。

默认 Map 为:

Note

  • 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 *是要 Map 的标题的名称。它将在注册表中转换为小写。 * cls 是专用类,与 base_class 一起使用,用于创建用于实例化与 name *匹配的 Headers 的类。
  • __getitem__(* name *)

    • 构造并返回一个类以处理创建* name *Headers 的过程。
  • __call__(* name value *)

    • 从注册表中检索与* name 关联的专用 Headers(如果 name 未出现在注册表中,则使用 default_class ),并与 base_class *组合以生成一个类,调用构造的类的构造函数,并将其传递给相同的对象参数列表,最后返回由此创建的类实例。

以下类是用于表示从结构化 Headers 解析的数据的类,通常,应用程序可以使用这些类来构造结构化值以分配给特定的 Headers。

    • class * email.headerregistry. Address(* display_name ='' username ='' domain ='' addr_spec = None *)
    • 用于表示电子邮件地址的类。地址的一般形式为:
[display_name] <username@domain>

or:

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部分,正确引用以用作裸地址(上面显示的第二种形式)。此属性是不可变的。
  • __str__ ( )

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

为了支持 SMTP( RFC 5321),Address处理一种特殊情况:如果usernamedomain都是空字符串(或None),则Address的字符串值为<>

    • class * email.headerregistry. Group(* display_name = None addresses = None *)
    • 用于表示地址组的类。地址组的一般形式为:
display_name: [address-list];

为了方便处理由组和单个地址组成的地址列表,Group也可以pass将* display_name 设置为None并提供单个列表来表示不属于组的单个地址。地址为 addresses *。

  • display_name

    • 群组的display_name。如果它是None并且在addresses中正好有一个Address,则Group表示不在组中的单个地址。
  • addresses

    • Address个对象的可能为空的 Tuples,它们代表组中的地址。
  • __str__ ( )

    • Groupstr值是根据 RFC 5322格式化的,但没有任何非 ASCII 字符的内容传输编码。如果display_name不存在,并且addresses列表中只有一个Address,则str的值将与该Addressstr相同。

Footnotes