email.message.Message:使用 compat32 API 表示电子邮件消息 — Python 文档

来自菜鸟教程
Python/docs/3.9/library/email.compat32-message
跳转至:导航、​搜索

email.message.Message:使用 compat32 API 表示电子邮件

Message 类与 EmailMessage 类非常相似,没有该类添加的方法,并且某些其他方法的默认行为略有不同。 我们还在此处记录了一些方法,虽然 EmailMessage 类支持这些方法,但除非您处理遗留代码,否则不推荐这些方法。

这两个类的哲学和结构在其他方面是相同的。

本文档描述了默认(对于 Message)策略 Compat32 下的行为。 如果您打算使用其他策略,则应改用 EmailMessage 类。

电子邮件消息由 标头有效载荷 组成。 标头必须是 RFC 5322 样式名称和值,其中字段名称和值由冒号分隔。 冒号不是字段名称或字段值的一部分。 有效载荷可以是简单的文本消息、二进制对象或结构化的子消息序列,每个子消息都有自己的一组标头和自己的有效载荷。 后一种类型的有效载荷由具有 MIME 类型的消息指示,例如 multipart/*message/rfc822

Message 对象提供的概念模型是一个有序的标头字典,带有额外的方法,用于访问来自标头的专用信息、访问有效载荷、生成消息的序列化版本以及递归遍历对象树。 请注意,支持重复标头,但必须使用特殊方法来访问它们。

Message 伪字典由标头名称索引,标头名称必须是 ASCII 值。 字典的值是应该只包含 ASCII 字符的字符串; 对非 ASCII 输入有一些特殊处理,但它并不总是产生正确的结果。 标题以保留大小写的形式存储和返回,但字段名称不区分大小写匹配。 也可能有一个信封头,也称为 Unix-From 头或 From_ 头。 payload 是一个字符串或字节,在简单消息对象的情况下,或 Message 对象的列表,用于 MIME 容器文档(例如 multipart/*message/rfc822)。

以下是 Message 类的方法:

class email.message.Message(policy=compat32)

如果指定了 policy(它必须是 policy 类的实例),则使用它指定的规则来更新和序列化消息的表示。 如果未设置 policy,请使用 compat32 策略,该策略保持与电子邮件包的 Python 3.2 版本的向后兼容性。 有关更多信息,请参阅 policy 文档。

3.3 版更改: 添加了 policy 关键字参数。

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

以字符串形式返回整条消息。 当可选 unixfrom 为 true 时,信封头包含在返回的字符串中。 unixfrom 默认为 False。 出于向后兼容的原因,maxheaderlen 默认为 0,所以如果你想要一个不同的值,你必须显式覆盖它(在策略中为 max_line_length 指定的值将是此方法忽略)。 policy 参数可用于覆盖从消息实例获得的默认策略。 这可用于控制该方法产生的某些格式,因为指定的 policy 将传递给 Generator

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

请注意,此方法是为了方便而提供的,可能并不总是按照您想要的方式格式化消息。 例如,默认情况下,它不会对 unix mbox 格式所需的以 From 开头的行进行修改。 为了获得更大的灵活性,请实例化 Generator 实例并直接使用其 flatten() 方法。 例如:

from io import StringIO
from email.generator import Generator
fp = StringIO()
g = Generator(fp, mangle_from_=True, maxheaderlen=60)
g.flatten(msg)
text = fp.getvalue()

如果消息对象包含未根据 RFC 标准编码的二进制数据,则不合规的数据将被 unicode“未知字符”代码点替换。 (另见 as_bytes()BytesGenerator。)

3.4 版更改:添加了 policy 关键字参数。

__str__()

相当于 as_string()。 允许 str(msg) 生成包含格式化消息的字符串。

as_bytes(unixfrom=False, policy=None)

返回整条消息扁平化为字节对象。 当可选 unixfrom 为 true 时,信封头包含在返回的字符串中。 unixfrom 默认为 Falsepolicy 参数可用于覆盖从消息实例获得的默认策略。 这可用于控制该方法产生的某些格式,因为指定的 policy 将传递给 BytesGenerator

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

请注意,此方法是为了方便而提供的,可能并不总是按照您想要的方式格式化消息。 例如,默认情况下,它不会对 unix mbox 格式所需的以 From 开头的行进行修改。 为了获得更大的灵活性,请实例化 BytesGenerator 实例并直接使用其 flatten() 方法。 例如:

from io import BytesIO
from email.generator import BytesGenerator
fp = BytesIO()
g = BytesGenerator(fp, mangle_from_=True, maxheaderlen=60)
g.flatten(msg)
text = fp.getvalue()

3.4 版中的新功能。

__bytes__()

相当于 as_bytes()。 允许 bytes(msg) 生成一个包含格式化消息的字节对象。

3.4 版中的新功能。

is_multipart()

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

set_unixfrom(unixfrom)

将消息的信封头设置为 unixfrom,它应该是一个字符串。

get_unixfrom()

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

attach(payload)

将给定的 payload 添加到当前有效负载中,该负载必须是 None 或调用前的 Message 对象列表。 调用后,有效负载将始终是 Message 对象的列表。 如果要将有效负载设置为标量对象(例如 字符串),请改用 set_payload()

这是一种遗留方法。 在 EmailMessage 类上,它的功能被 set_content() 和相关的 makeadd 方法取代。

get_payload(i=None, decode=False)

返回当前的payload,当is_multipart()True时为Message对象列表,is_multipart()时为字符串是 False。 如果有效负载是一个列表并且您改变了列表对象,则您就地修改了消息的有效负载。

使用可选参数 iget_payload() 将返回有效载荷的第 i 个元素,从零开始计数,如果 is_multipart() ] 是 True。 如果 i 小于 0 或大于或等于有效负载中的项目数,则会引发 IndexError。 如果有效载荷是一个字符串(即 is_multipart()False) 并给出 i,引发 TypeError

可选的 decode 是根据 Content-Transfer-Encoding 标头指示是否应解码有效载荷的标志。 当 True 且消息不是多部分时,如果此标头的值为 quoted-printablebase64,则将解码有效负载。 如果使用了其他编码,或者缺少 Content-Transfer-Encoding 标头,则有效负载按原样返回(未解码)。 在所有情况下,返回值都是二进制数据。 如果消息是多部分的并且 decode 标志是 True,则返回 None。 如果有效负载是 base64 并且它没有完美地形成(缺少填充、base64 字母表之外的字符),那么将在消息的缺陷属性中添加适当的缺陷(分别为 InvalidBase64PaddingDefectInvalidBase64CharactersDefect) )。

decodeFalse(默认值)时,正文作为字符串返回,而不解码 Content-Transfer-Encoding。 但是,对于 8 位的 Content-Transfer-Encoding,尝试使用 Content-Type 标头指定的 charset 解码原始字节,使用replace 错误处理程序。 如果未指定 charset,或者如果电子邮件包无法识别给定的 charset,则使用默认 ASCII 字符集对正文进行解码。

这是一种遗留方法。 在 EmailMessage 类上,它的功能被 get_content()iter_parts() 取代。

set_payload(payload, charset=None)

将整个消息对象的有效负载设置为 payload。 确保有效载荷不变是客户的责任。 可选 charset 设置消息的默认字符集; 有关详细信息,请参阅 set_charset()

这是一种遗留方法。 在 EmailMessage 类上,它的功能被 set_content() 取代。

set_charset(charset)

将有效负载的字符集设置为 charset,它可以是 Charset 实例(请参阅 email.charset)、命名字符集的字符串,或None。 如果是字符串,则会转换为 Charset 实例。 如果 charsetNone,则 charset 参数将从 Content-Type 标头中删除(消息不会被另外修改)。 其他任何事情都会产生 TypeError

如果没有现有的 MIME-Version 标头,则会添加一个。 如果没有现有的 Content-Type 标头,则会添加一个值为 text/plain 的标头。 无论 Content-Type 头是否已经存在,其 charset 参数都会设置为 charset.output_charset。 如果 charset.input_charsetcharset.output_charset 不同,payload 将被重新编码为 output_charset。 如果没有现有的 Content-Transfer-Encoding 标头,则如果需要,将使用指定的 Charset 对有效负载进行传输编码,并且具有适当值的标头将是添加。 如果 Content-Transfer-Encoding 标头已存在,则假定有效负载已使用该 Content-Transfer-Encoding 正确编码且未修改。

这是一种遗留方法。 在 EmailMessage 类中,它的功能被 email.emailmessage.EmailMessage.set_content() 方法的 charset 参数替换。

get_charset()

返回与消息有效负载关联的 Charset 实例。

这是一种遗留方法。 在 EmailMessage 类上,它总是返回 None

以下方法实现了一个类似于映射的接口,用于访问消息的 RFC 2822 标头。 请注意,这些方法和法线映射之间存在一些语义差异(即 字典)界面。 例如,在字典中没有重复的键,但这里可能有重复的消息头。 此外,在字典中,keys() 返回的键的顺序没有保证,但在 Message 对象中,标题总是按照它们在原始消息中出现的顺序返回,或稍后添加到消息中。 任何删除然后重新添加的标题总是附加到标题列表的末尾。

这些语义差异是有意的,偏向于最大程度的便利。

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

在从字节生成的模型中,任何(违反 RFC)包含非 ASCII 字节的标头值在通过此接口检索时将表示为 Header 对象,其字符集为 未知-8位。

__len__()

返回标题的总数,包括重复项。

__contains__(name)

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

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

返回命名头字段的值。 name 不应包含冒号字段分隔符。 如果缺少header,则返回NoneKeyError 永远不会被提出。

请注意,如果命名字段在消息的标题中出现多次,那么将返回这些字段值中的哪一个是未定义的。 使用 get_all() 方法获取所有现存命名头的值。

__setitem__(name, val)

使用字段名称 name 和值 val 向消息添加标题。 该字段附加到消息现有字段的末尾。

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

del msg['subject']
msg['subject'] = 'Python roolz!'
__delitem__(name)

从邮件的标题中删除所有出现的名称为 name 的字段。 如果标题中不存在命名字段,则不会引发异常。

keys()

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

values()

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

items()

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

get(name, failobj=None)

返回命名头字段的值。 这与 __getitem__() 相同,除了可选的 failobj 在指定的头文件丢失时返回(默认为 None)。

以下是一些额外的有用方法:

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-8CHARSET 自动编码为 RFC 2231 格式] 和 NoneLANGUAGE

下面是一个例子:

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'))

其中产生

Content-Disposition: attachment; filename*="iso-8859-1''Fu%DFballer.ppt"
replace_header(_name, _value)

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

get_content_type()

返回消息的内容类型。 返回的字符串被强制转换为 maintype/subtype 形式的小写。 如果消息中没有 Content-Type 标头,则将返回 get_default_type() 给出的默认类型。 由于根据 RFC 2045,消息总是有一个默认类型,get_content_type() 将总是返回一个值。

RFC 2045 将消息的默认类型定义为 text/plain,除非它出现在 multipart/digest 容器中,在这种情况下它将是 消息/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 标头中。

get_params(failobj=None, header='content-type', unquote=True)

以列表形式返回消息的 Content-Type 参数。 返回列表的元素是键/值对的 2 元组,在 '=' 符号上拆分。 '='的左边是键,右边是值。 如果参数中没有 '=' 符号,则值为空字符串,否则该值如 get_param() 中所述,并且如果可选 unquote 是不加引号的True(默认)。

如果没有 Content-Type 标头,可选的 failobj 是要返回的对象。 可选的 header 是要搜索的标头,而不是 Content-Type

这是一种遗留方法。 在 EmailMessage 类中,它的功能被头访问方法返回的各个头对象的 params 属性所取代。

get_param(param, failobj=None, header='content-type', unquote=True)

以字符串形式返回 Content-Type 标头参数 param 的值。 如果消息没有 Content-Type 头或没有这样的参数,则返回 failobj(默认为 None)。

可选的 header 如果给定,则指定要使用的消息头而不是 Content-Type

参数键总是不区分大小写进行比较。 如果参数是 RFC 2231 编码,则返回值可以是字符串或三元组。 当它是一个 3 元组时,值的元素的形式是 (CHARSET, LANGUAGE, VALUE)。 请注意,CHARSETLANGUAGE 都可以是 None,在这种情况下,您应该考虑将 VALUE 编码为 us-ascii 字符集。 您通常可以忽略 LANGUAGE

如果您的应用程序不关心参数是否按照 RFC 2231 进行编码,您可以通过调用 email.utils.collapse_rfc2231_value() 折叠参数值, 传入来自 get_param() 的返回值。 当值是元组时,这将返回一个适当解码的 Unicode 字符串,如果不是,则返回不带引号的原始字符串。 例如:

rawparam = msg.get_param('foo')
param = email.utils.collapse_rfc2231_value(rawparam)

在任何情况下,参数值(返回的字符串或 3 元组中的 VALUE 项)总是不带引号的,除非 unquote 设置为 False

这是一种遗留方法。 在 EmailMessage 类中,它的功能被头访问方法返回的各个头对象的 params 属性所取代。

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

Content-Type 标头中设置参数。 如果该参数已存在于头文件中,则其值将替换为 value。 如果尚未为此消息定义 Content-Type 标头,则将其设置为 text/plain 并且将按照 附加新参数值]RFC 2045

可选的 header 指定了 Content-Type 的替代标头,所有参数将在必要时被引用,除非可选的 requoteFalse(默认)是 True)。

如果指定了可选的 charset,则参数将根据 RFC 2231 进行编码。 可选 language 指定 RFC 2231 语言,默认为空字符串。 charsetlanguage 都应该是字符串。

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

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

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

Content-Type 标头中完全删除给定的参数。 标头将在没有参数或其值的情况下重写。 除非 requoteFalse(默认值为 True),则所有值都将根据需要引用。 可选的 header 指定了 Content-Type 的替代。

set_type(type, header='Content-Type', requote=True)

设置 Content-Type 标头的主要类型和子类型。 type 必须是 maintype/subtype 形式的字符串,否则会引发 ValueError

此方法替换 Content-Type 标头,保留所有参数。 如果 requoteFalse,这将保留现有标题的引用,否则参数将被引用(默认)。

可以在 header 参数中指定替代标头。 当设置 Content-Type 标头时,还会添加 MIME-Version 标头。

这是一种遗留方法。 在 EmailMessage 类上,它的功能被 make_add_ 方法取代。

get_filename(failobj=None)

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

get_boundary(failobj=None)

返回消息的 Content-Type 标头的 boundary 参数的值,如果标头丢失或没有 [,则返回 failobj X163X] 参数。 根据 email.utils.unquote(),返回的字符串将始终不加引号。

set_boundary(boundary)

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

请注意,使用此方法与删除旧的 Content-Type 标头并通过 add_header() 添加具有新边界的新标头略有不同,因为 set_boundary()[ X195X] 保留 Content-Type 标头在标头列表中的顺序。 但是,它确实 not 保留了原始 Content-Type 标头中可能存在的任何连续行。

get_content_charset(failobj=None)

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

请注意,此方法与 get_charset() 不同,后者返回 Charset 实例作为消息正文的默认编码。

get_charsets(failobj=None)

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

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

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 调试辅助函数在我们的示例中看到这一点:

>>> 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 下降到子部分。

Message 对象还可以选择包含两个实例属性,可以在生成 MIME 消息的纯文本时使用。

preamble

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

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

请注意,如果消息对象没有前导,则 前导 属性将为 None

epilogue

epilogue 属性的作用与 preamble 属性相同,不同之处在于它包含出现在消息最后边界和结尾之间的文本。

您不需要将结尾设置为空字符串,以便 Generator 在文件末尾打印换行符。

defects

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