email.message:表示电子邮件消息

源代码: Lib/email/message.py


3.6 版新增: [1]

email 包中的核心类是 EmailMessage 类,从 email.message 模块导入。它是 email 对象模型的基本类。 EmailMessage 提供了设置和查询标头字段、访问消息正文以及创建或修改结构化消息的核心功能。

电子邮件消息由标头有效负载(也称为内容)组成。标头是 RFC 5322RFC 6532 样式的字段名和值,其中字段名和值用冒号分隔。冒号不属于字段名或字段值。有效负载可以是简单的文本消息、二进制对象或结构化的子消息序列,每个子消息序列都有自己的一组标头和自己的有效负载。后一种类型的有效负载通过消息具有 MIME 类型(如 multipart/*message/rfc822)来表示。

EmailMessage 对象提供的概念模型是标头有序字典,以及表示 RFC 5322 消息正文的有效负载,该正文可能是 EmailMessage 对象的列表。除了用于访问标头名称和值的普通字典方法外,还有用于从标头访问专门信息(例如 MIME 内容类型)、操作有效负载、生成消息的序列化版本以及递归遍历对象树的方法。

类似于字典的 EmailMessage 接口由标头名称索引,这些名称必须是 ASCII 值。字典的值是带有一些额外方法的字符串。标头以保留大小写形式存储和返回,但字段名称不区分大小写。键是有序的,但与真正的字典不同,可以有重复项。还提供了其他方法来处理具有重复键的标头。

对于简单消息对象,有效负载是字符串或字节对象,对于 MIME 容器文档(例如 multipart/*message/rfc822 消息对象),则为 EmailMessage 对象的列表。

class email.message.EmailMessage(policy=default)

如果指定了 policy,则使用它指定的规则来更新和序列化消息的表示形式。如果未设置 policy,则使用 default 策略,该策略遵循电子邮件 RFC 的规则,但行尾除外(它使用 Python 标准 \n 行尾,而不是 RFC 要求的 \r\n)。有关更多信息,请参阅 policy 文档。

as_string(unixfrom=False, maxheaderlen=None, policy=None)

将整个消息展平为字符串并返回。当可选的 unixfrom 为 true 时,信封头包含在返回的字符串中。unixfrom 默认为 False。为了向后兼容基本 Message 类,maxheaderlen 被接受,但默认为 None,这意味着默认情况下,行长由 max_line_length 策略控制。policy 参数可用于覆盖从消息实例获取的默认策略。这可用于控制方法生成的部分格式,因为指定的 policy 将传递给 Generator

展平消息可能会触发对 EmailMessage 的更改,如果需要填入默认值以完成转换为字符串(例如,MIME 边界可能会生成或修改)。

请注意,提供此方法是为了方便起见,可能不是在应用程序中序列化消息的最有用方法,尤其是在处理多条消息时。有关序列化消息的更灵活的 API,请参阅 email.generator.Generator。另请注意,当 utf8False(这是默认值)时,此方法仅限于生成序列化为“7 位干净”的消息。

在版本 3.6 中更改:当未指定 maxheaderlen 时,默认行为已从默认为 0 更改为默认为策略中的 max_line_length 值。

__str__()

等效于 as_string(policy=self.policy.clone(utf8=True))。允许 str(msg) 生成包含可读格式中序列化消息的字符串。

在版本 3.4 中更改:该方法已更改为使用 utf8=True,从而生成类似于 RFC 6531 的消息表示形式,而不是 as_string() 的直接别名。

as_bytes(unixfrom=False, policy=None)

将整个消息展平为字节对象并返回。当可选的 unixfrom 为 true 时,返回的字符串中将包含信封头。unixfrom 的默认值为 Falsepolicy 参数可用于覆盖从消息实例获取的默认策略。这可用于控制方法生成的部分格式,因为指定的 policy 将传递给 BytesGenerator

展平消息可能会触发对 EmailMessage 的更改,如果需要填入默认值以完成转换为字符串(例如,MIME 边界可能会生成或修改)。

请注意,提供此方法是为了方便起见,它可能不是在您的应用程序中序列化消息的最有用方法,尤其是在您处理多条消息时。有关用于序列化消息的更灵活的 API,请参阅 email.generator.BytesGenerator

__bytes__()

等同于 as_bytes()。允许 bytes(msg) 生成包含已序列化的消息的字节对象。

is_multipart()

如果消息的有效负载是子 EmailMessage 对象的列表,则返回 True,否则返回 False。当 is_multipart() 返回 False 时,有效负载应为字符串对象(可能是 CTE 编码的二进制有效负载)。请注意,is_multipart() 返回 True 并不一定意味着 “msg.get_content_maintype() == ‘multipart’” 将返回 True。例如,当 EmailMessage 的类型为 message/rfc822 时,is_multipart 将返回 True

set_unixfrom(unixfrom)

将消息的信封头设置为 unixfrom,它应为一个字符串。(有关此头的简要说明,请参阅 mboxMessage。)

get_unixfrom()

返回消息的信封头。如果从未设置过信封头,则默认为 None

以下方法实现了用于访问消息头的映射式接口。请注意,这些方法与普通映射(即字典)接口之间存在一些语义差异。例如,在字典中没有重复的键,但此处可能有重复的消息头。此外,在字典中,keys() 返回的键没有保证的顺序,但在 EmailMessage 对象中,头始终按其在原始消息中出现的顺序或稍后添加到消息中的顺序返回。任何被删除然后重新添加的头始终附加到头列表的末尾。

这些语义差异是有意的,并且偏向于在最常见的用例中使用方便。

请注意,在所有情况下,消息中存在的任何信封头都不会包含在映射接口中。

__len__()

返回头部的总数,包括重复项。

__contains__(name)

如果消息对象具有名为 name 的字段,则返回 True。匹配时不区分大小写,并且 name 不包括尾随冒号。用于 in 运算符。例如

if 'message-id' in myMessage:
   print('Message-ID:', myMessage['message-id'])
__getitem__(name)

返回命名头部字段的值。name 不包括冒号字段分隔符。如果头部不存在,则返回 None;绝不会引发 KeyError

请注意,如果命名字段在消息的头部中出现多次,则将返回这些字段值中的哪一个是不确定的。使用 get_all() 方法获取所有现有名为 name 的头部的值。

使用标准(非 compat32)策略,返回值是 email.headerregistry.BaseHeader 子类的实例。

__setitem__(name, val)

将一个头部添加到消息,其字段名为 name,值为 val。该字段追加到消息现有头部的末尾。

请注意,这不会覆盖或删除任何具有相同名称的现有头部。如果您想确保新头部是消息中唯一具有字段名 name 的头部,请首先删除该字段,例如

del msg['subject']
msg['subject'] = 'Python roolz!'

如果policy定义某些标题是唯一的(就像标准策略所做的那样),当尝试为一个已经存在的标题分配一个值时,此方法可能会引发ValueError。为了保持一致性,此行为是故意的,但不要依赖它,因为我们可能会选择让此类分配在将来自动删除现有标题。

__delitem__(name)

从消息的标题中删除所有名称为name的字段。如果标题中不存在指定字段,则不会引发异常。

keys()

返回所有消息标题字段名称的列表。

values()

返回所有消息字段值的列表。

items()

返回包含所有消息字段标题和值的 2 元组列表。

get(name, failobj=None)

返回指定标题字段的值。这与__getitem__()相同,但如果指定的标题不存在,则返回可选的failobjfailobj默认为None)。

以下是一些其他有用的标题相关方法

get_all(name, failobj=None)

返回名为name的所有字段的值的列表。如果消息中没有此类标题,则返回failobj(默认为None)。

add_header(_name, _value, **_params)

扩展头设置。此方法类似于 __setitem__(),但可以将其他头参数作为关键字参数提供。_name 是要添加的头字段,_value 是头的主要值。

对于关键字参数字典 _params 中的每个项目,密钥将作为参数名称,下划线转换为破折号(因为破折号在 Python 标识符中是非法的)。通常,参数将作为 key="value" 添加,除非该值为 None,在这种情况下,将仅添加密钥。

如果该值包含非 ASCII 字符,可以通过以 (CHARSET, LANGUAGE, VALUE) 格式指定一个三元组来明确控制字符集和语言,其中 CHARSET 是一个用于对该值进行编码的字符集的字符串名称,LANGUAGE 通常可以设置为 None 或空字符串(有关其他可能性,请参见 RFC 2231),VALUE 是包含非 ASCII 代码点的字符串值。如果没有传递三元组并且该值包含非 ASCII 字符,则会使用 CHARSETutf-8LANGUAGENoneRFC 2231 格式自动对其进行编码。

以下是一个示例

msg.add_header('Content-Disposition', 'attachment', filename='bud.gif')

这将添加一个类似于

Content-Disposition: attachment; filename="bud.gif"

带非 ASCII 字符的扩展接口示例

msg.add_header('Content-Disposition', 'attachment',
               filename=('iso-8859-1', '', 'Fußballer.ppt'))
replace_header(_name, _value)

替换头。替换消息中找到的第一个与 _name 匹配的头,保留原始头的头顺序和字段名称大小写。如果没有找到匹配的头,则引发 KeyError

get_content_type()

返回消息的内容类型,强制转换为 maintype/subtype 形式的小写。如果消息中没有 Content-Type 头,则返回 get_default_type() 返回的值。如果 Content-Type 头无效,则返回 text/plain

(根据RFC 2045,消息始终具有默认类型,get_content_type()始终会返回一个值。RFC 2045将消息的默认类型定义为text/plain,除非它出现在multipart/digest容器中,在这种情况下,它将为message/rfc822。如果Content-Type头具有无效的类型规范,RFC 2045要求默认类型为text/plain。)

get_content_maintype()

返回消息的主内容类型。这是get_content_type()返回的字符串的maintype部分。

get_content_subtype()

返回消息的子内容类型。这是get_content_type()返回的字符串的subtype部分。

get_default_type()

返回默认内容类型。大多数消息的默认内容类型为text/plain,但multipart/digest容器的子消息除外。此类子消息的默认内容类型为message/rfc822

set_default_type(ctype)

设置默认内容类型。ctype应为text/plainmessage/rfc822,尽管并未强制执行此操作。默认内容类型不会存储在Content-Type头中,因此它仅影响当消息中不存在Content-Type头时get_content_type方法的返回值。

set_param(param, value, header='Content-Type', requote=True, charset=None, language='', replace=False)

Content-Type 头中设置一个参数。如果该参数已在头中存在,则用value 替换其值。当headerContent-Type(默认值)并且头尚未在消息中存在时,添加该头,将其值设置为 text/plain,并附加新的参数值。可选的header 指定 Content-Type 的备用头。

如果该值包含非 ASCII 字符,则可以使用可选的charsetlanguage 参数明确指定字符集和语言。可选的language 指定 RFC 2231 语言,默认为空字符串。charsetlanguage 都应为字符串。默认情况下,使用 utf8 charsetNone 作为language

如果replaceFalse(默认值),则将头移动到头列表的末尾。如果replaceTrue,则将就地更新头。

EmailMessage 对象中使用requote 参数已弃用。

请注意,可以通过头值的 params 属性访问头中现有的参数值(例如,msg['Content-Type'].params['charset'])。

在 3.4 版本中更改: 添加了 replace 关键字。

del_param(param, header='content-type', requote=True)

Content-Type 头中完全删除给定的参数。头将重新写入,不带参数或其值。可选的header 指定 Content-Type 的备用头。

EmailMessage 对象中使用requote 参数已弃用。

get_filename(failobj=None)

返回消息的 Content-Disposition 头的 filename 参数的值。如果头没有 filename 参数,则此方法将回退到在 Content-Type 头上查找 name 参数。如果两者都找不到,或者头丢失,则返回failobj。返回的字符串将始终按照 email.utils.unquote() 进行取消引用。

get_boundary(failobj=None)

返回消息的 Content-Type 头的 boundary 参数的值,如果头不存在或没有 boundary 参数,则返回 failobj。返回的字符串将始终按照 email.utils.unquote() 进行取消引用。

set_boundary(boundary)

Content-Type 头的 boundary 参数设置为 boundary。如果需要,set_boundary() 始终会引用 boundary。如果消息对象没有 Content-Type 头,则会引发 HeaderParseError

请注意,使用此方法与删除旧的 Content-Type 头并通过 add_header() 添加一个带有新边界的头略有不同,因为 set_boundary() 保留了头列表中 Content-Type 头的顺序。

get_content_charset(failobj=None)

返回 Content-Type 头的 charset 参数,并强制转换为小写。如果没有 Content-Type 头,或者该头没有 charset 参数,则返回 failobj

get_charsets(failobj=None)

返回包含消息中字符集名称的列表。如果消息是 multipart,则列表将包含有效负载中每个子部分的一个元素,否则,它将是一个长度为 1 的列表。

列表中的每个项目都将是一个字符串,该字符串是表示的子部分的 Content-Type 标头中 charset 参数的值。如果子部分没有 Content-Type 标头、没有 charset 参数,或者不是 text 主 MIME 类型,那么返回列表中的该项目将为 failobj

is_attachment()

如果存在 Content-Disposition 标头,并且它的(不区分大小写)值为 attachment,则返回 True,否则返回 False

在 3.4.2 版本中更改:为了与 is_multipart() 保持一致,is_attachment 现在是一个方法,而不是一个属性。

get_content_disposition()

如果消息的 Content-Disposition 标头存在,则返回其小写值(不带参数),否则返回 None。如果消息遵循 RFC 2183,则此方法的可能值为 inlineattachmentNone

在 3.5 版本中添加。

以下方法与查询和操作消息的内容(有效载荷)有关。

walk()

walk() 方法是一个通用生成器,可用于深度优先遍历顺序迭代消息对象树的所有部分和子部分。您通常会将 walk() 用作 for 循环中的迭代器;每次迭代都会返回下一个子部分。

以下是一个示例,它打印多部分消息结构中每个部分的 MIME 类型

>>> for part in msg.walk():
...     print(part.get_content_type())
multipart/report
text/plain
message/delivery-status
text/plain
text/plain
message/rfc822
text/plain

walk 迭代任何部件的子部件,其中 is_multipart() 返回 True,即使 msg.get_content_maintype() == 'multipart' 可能返回 False。我们可以通过利用 _structure 调试帮助器函数在我们的示例中看到这一点

>>> from email.iterators import _structure
>>> for part in msg.walk():
...     print(part.get_content_maintype() == 'multipart',
...           part.is_multipart())
True True
False False
False True
False False
False False
False True
False False
>>> _structure(msg)
multipart/report
    text/plain
    message/delivery-status
        text/plain
        text/plain
    message/rfc822
        text/plain

这里 message 部件不是 multiparts,但它们确实包含子部件。 is_multipart() 返回 True,并且 walk 进入子部件。

get_body(preferencelist=('related', 'html', 'plain'))

返回最适合作为消息“正文”的 MIME 部件。

preferencelist 必须是来自集合 relatedhtmlplain 的字符串序列,并指示返回部件的内容类型的首选项顺序。

从调用 get_body 方法的对象开始寻找候选匹配项。

如果 preferencelist 中不包含 related,则将遇到的任何相关项的根部件(或根部件的子部件)视为候选项,如果(子)部件与首选项匹配。

在遇到 multipart/related 时,检查 start 参数,如果找到具有匹配 Content-ID 的部件,则在寻找候选匹配项时仅考虑它。否则,仅考虑 multipart/related 的第一个(默认根)部件。

如果部件具有 Content-Disposition 头部,则仅在头部的值是 inline 时才将部件视为候选匹配项。

如果没有任何候选项与 preferencelist 中的任何首选项匹配,则返回 None

注释:(1) 对于大多数应用程序,唯一真正有意义的 preferencelist 组合是 ('plain',)('html', 'plain') 和默认 ('related', 'html', 'plain')。(2) 由于匹配从调用 get_body 的对象开始,因此在 multipart/related 上调用 get_body 将返回对象本身,除非 preferencelist 具有非默认值。(3) 未指定 Content-Type 或其 Content-Type 头部无效的消息(或消息部件)将被视为类型为 text/plain,这偶尔会导致 get_body 返回意外结果。

iter_attachments()

返回一个迭代器,用于遍历邮件的所有直接子部分,这些子部分不是候选“正文”部分。也就是说,跳过以下每个部分的第一次出现:text/plaintext/htmlmultipart/relatedmultipart/alternative(除非它们通过 Content-Disposition: attachment 明确标记为附件),并返回所有剩余部分。当直接应用于 multipart/related 时,返回一个迭代器,用于遍历除根部分(即由 start 参数指向的部分,如果没有 start 参数,或者 start 参数与任何部分的 Content-ID 不匹配,则为第一部分)之外的所有相关部分。当直接应用于 multipart/alternative 或非 multipart 时,返回一个空迭代器。

iter_parts()

返回一个迭代器,用于遍历邮件的所有直接子部分,对于非 multipart,该迭代器将为空。(另请参见 walk()。)

get_content(*args, content_manager=None, **kw)

调用 content_managerget_content() 方法,将 self 作为邮件对象传递,并将任何其他参数或关键字作为附加参数传递。如果未指定 content_manager,请使用当前 policy 指定的 content_manager

set_content(*args, content_manager=None, **kw)

调用 set_content() 方法,将 self 作为邮件对象传递,并将任何其他参数或关键字作为附加参数传递。如果未指定 content_manager,请使用当前 policy 指定的 content_manager

将非 multipart 消息转换为 multipart/related 消息,将任何现有的 Content- 头和有效负载移动到 multipart 的(新)第一部分中。如果指定了 boundary,请将其用作 multipart 中的边界字符串,否则将边界保留为在需要时自动创建(例如,当消息被序列化时)。

make_alternative(boundary=None)

将非 multipartmultipart/related 转换为 multipart/alternative,将任何现有的 Content- 头和有效负载移动到 multipart 的(新)第一部分中。如果指定了 boundary,请将其用作 multipart 中的边界字符串,否则将边界保留为在需要时自动创建(例如,当消息被序列化时)。

make_mixed(boundary=None)

将非 multipartmultipart/relatedmultipart-alternative 转换为 multipart/mixed,将任何现有的 Content- 头和有效负载移动到 multipart 的(新)第一部分中。如果指定了 boundary,请将其用作 multipart 中的边界字符串,否则将边界保留为在需要时自动创建(例如,当消息被序列化时)。

如果邮件是 multipart/related,创建一个新的邮件对象,将所有参数传递给其 set_content() 方法,并将其 attach()multipart。如果邮件不是 multipart,则调用 make_related(),然后按上述方法进行。如果邮件是任何其他类型的 multipart,则引发 TypeError。如果未指定 content_manager,则使用当前 policy 指定的 content_manager。如果添加的部分没有 Content-Disposition 头部,则添加一个值为 inline 的头部。

add_alternative(*args, content_manager=None, **kw)

如果消息是 multipart/alternative,创建一个新消息对象,将所有参数传递给它的 set_content() 方法,并 attach() 它到 multipart。如果消息是非 multipartmultipart/related,调用 make_alternative(),然后按上述方式进行。如果消息是任何其他类型的 multipart,引发 TypeError。如果未指定 content_manager,请使用当前 policy 指定的 content_manager

add_attachment(*args, content_manager=None, **kw)

如果消息是 multipart/mixed,创建一个新消息对象,将所有参数传递给它的 set_content() 方法,并 attach() 它到 multipart。如果消息是非 multipartmultipart/relatedmultipart/alternative,调用 make_mixed(),然后按上述方法进行。如果未指定 content_manager,使用当前 policy 指定的 content_manager。如果添加的部件没有 Content-Disposition 头,添加一个值为 attachment 的头。此方法可用于显式附件(Content-Disposition: attachment)和 inline 附件(Content-Disposition: inline),方法是将适当的选项传递给 content_manager

clear()

移除有效负载和所有头。

clear_content()

移除有效负载和所有 !Content- 头,保留所有其他头并保持其原始顺序。

EmailMessage 对象具有以下实例属性

preamble

MIME 文档的格式允许在头后的空行和第一个多部分边界字符串之间存在一些文本。通常,此文本在 MIME 感知邮件阅读器中永远不可见,因为它超出了标准 MIME 装甲的范围。但是,在查看消息的原始文本或在非 MIME 感知阅读器中查看消息时,此文本可能会变得可见。

preamble 属性包含 MIME 文档的这个前置额外装甲文本。当 Parser 在标头之后但在第一个边界字符串之前发现一些文本时,它会将此文本分配给消息的 preamble 属性。当 Generator 正在写出 MIME 消息的纯文本表示形式,并且它发现消息有一个 preamble 属性时,它会将此文本写在标头和第一个边界之间的区域中。有关详细信息,请参阅 email.parseremail.generator

请注意,如果消息对象没有前置内容,则 preamble 属性将为 None

epilogue

epilogue 属性的作用与 preamble 属性相同,只是它包含出现在最后一个边界和消息末尾之间的文本。与 preamble 一样,如果没有 epilog 文本,此属性将为 None

defects

defects 属性包含解析此消息时发现的所有问题的列表。请参阅 email.errors 以详细了解可能的解析缺陷。

class email.message.MIMEPart(policy=default)

此类表示 MIME 消息的一个子部分。它与 EmailMessage 相同,只是在调用 set_content() 时不会添加任何 MIME-Version 标头,因为子部分不需要它们自己的 MIME-Version 标头。

脚注