Skip to main content

19.1.1. email.message:表示电子邮件

源代码: Lib/email/message.py


3.6 新版功能: [1]

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

电子邮件消息由 headerspayload (其也被称为 content)组成。标题是 RFC 5322RFC 6532 样式的字段名称和值,其中字段名称和值用冒号分隔。冒号不是字段名称或字段值的一部分。有效载荷可以是简单文本消息,或二进制对象或子消息的结构化序列,每个子消息具有它们自己的一组头部和它们自己的有效载荷。后一类型的有效载荷由具有诸如 multipart/*message/rfc822 的MIME类型的消息指示。

EmailMessage 对象提供的概念模型是与表示消息的 RFC 5322 主体的 payload 耦合的标题的有序字典,其可以是子 EmailMessage 对象的列表。除了用于访问头部名称和值的常规字典方法之外,还存在用于从头部(例如MIME内容类型)访问专用信息,用于在有效载荷上操作,用于生成消息的序列化版本的方法,以及用于递归地遍历对象树。

EmailMessage 类字典接口由标题名称索引,标题名称必须是ASCII值。字典的值是带有一些额外方法的字符串。头以字节保存的形式存储和返回,但字段名匹配大小写不敏感。不像真正的dict,有一个排序的键,并可以有重复的键。提供了其他方法来处理具有重复键的标头。

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

class email.message.EmailMessage(policy=default)

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

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

将整个消息作为字符串返回。当可选 unixfrom 为真时,包络头包含在返回的字符串中。 unixfrom 默认为 False。对于具有基本 Message 类别 maxheaderlen 的向后合并性,接受,但是默认为 None,这意味着在默认情况下,线路长度由策略的 max_line_length 控制。 policy 参数可以用于覆盖从消息实例获得的默认策略。这可以用于控制由该方法产生的一些格式化,因为指定的 policy 将被传递到 Generator

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

请注意,此方法是为了方便而提供,可能不是在应用程序中序列化消息的最有用的方法,特别是如果您处理多个消息。有关用于序列化消息的更灵活的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 为真时,包络头包含在返回的字符串中。 unixfrom 默认为 Falsepolicy 参数可以用于覆盖从消息实例获得的默认策略。这可以用于控制由该方法产生的一些格式化,因为指定的 policy 将被传递到 BytesGenerator

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

请注意,此方法是为了方便而提供,可能不是在应用程序中序列化消息的最有用的方法,特别是如果您处理多个消息。有关用于序列化消息的更灵活的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 不包括冒号字段分隔符。如果标题缺失,则返回 NoneKeyError 从不上升。

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

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

__setitem__(name, val)

在字段名为 name 和值为 val 的消息中添加标题。该字段将追加到邮件现有标题的末尾。

请注意,这会使 not 覆盖或删除具有相同名称的任何现有标题。如果要确保新标头是消息中唯一存在的字段名为 name 的消息,请先删除该字段,例如。:

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

如果 policy 将某些哈希定义为唯一的(如标准策略那样),则当已经存在时,当尝试向这样的报头分配值时,该方法可以产生 ValueError。这种行为是为了一致性的目的,但不依赖于它,因为我们可能选择使这种分配在未来自动删除现有的头。

__delitem__(name)

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

keys()

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

values()

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

items()

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

get(name, failobj=None)

返回指定头字段的值。这与 __getitem__() 相同,除非如果指定的头缺失(failobj 默认为 None),则返回可选的 failobj

这里有一些额外的有用的标题相关的方法:

get_all(name, failobj=None)

返回名为 name 的字段的所有值的列表。如果消息中没有这样的命名头,则返回 failobj (默认为 None)。

add_header(_name, _value, **_params)

扩展头设置。此方法类似于 __setitem__(),除了可以提供附加头参数作为关键字参数。 _name 是要添加的报头字段,_value 是报头的 primary 值。

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

如果值包含非ASCII字符,则可以通过将值指定为格式为 (CHARSET, LANGUAGE, VALUE) 的三元组来明确地控制字符集和语言,其中 CHARSET 是命名要用于对值进行编码的字符集的字符串,LANGUAGE 通常可以是设置为 None 或空字符串(对于其他可能性请参见 RFC 2231),VALUE 是包含非ASCII代码点的字符串值。如果三元组未通过且值包含非ASCII字符,则使用 utf-8CHARSETNoneLANGUAGERFC 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,并追加新的参数值。可选 headerContent-Type 指定替代标题。

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

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

不推荐将 requote 参数与 EmailMessage 对象一起使用。

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

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

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

Content-Type 头中完全删除给定的参数。标题将重新写入到位,不带参数或其值。可选 header 指定 Content-Type 的替代方法。

不推荐将 requote 参数与 EmailMessage 对象一起使用。

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 参数设置为 boundaryset_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_attachment现在是一个方法而不是属性,以与 is_multipart() 一致。

get_content_disposition()

返回消息的 Content-Disposition 头的低位值(无参数),如果它有一个或 None。如果消息遵循 RFC 2183,则此方法的可能值为 inlineattachmentNone

3.5 新版功能.

以下方法涉及询问和操纵消息的内容(有效载荷)。

walk()

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

下面是打印多部分消息结构的每个部分的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 调试助手函数在我们的示例中看到这一点:

>>> 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() 返回 Truewalk 下降到子部分。

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

返回作为消息的“主体”的最佳候选者的MIME部分。

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

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

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

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

如果部件具有 Content-Disposition 头部,则只要头部的值是 inline,则只考虑部分候选匹配。

如果没有候选项匹配 preferneclist 中的任何偏好,则返回 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)

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

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

make_alternative(boundary=None)

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

make_mixed(boundary=None)

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

如果消息是 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_manager 传递适当的选项,此方法可用于显式附件(Content-Disposition: attachmentinline 附件(Content-Disposition: inline))。

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 一样,如果没有结语文本,则该属性将是 None

defects

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

class email.message.MIMEPart(policy=default)

此类表示MIME消息的子部分。它与 EmailMessage 相同,除了当调用 set_content() 时没有添加 MIME-Version 头部,因为子部分不需要它们自己的 MIME-Version 头部。

脚注

[1]

最初添加在3.4作为 临时模块。将旧消息类的文档移动到 email.message.Message:使用 compat32 API表示电子邮件