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_
头部。对于简单消息对象,有效负载是字符串或字节;对于 MIME 容器文档(例如 multipart/* 和 message/rfc822),它是 Message
对象的列表。
以下是 Message
类的方法
- class email.message.Message(policy=compat32)¶
如果指定了 policy(它必须是
policy
类的一个实例),则使用它指定的规则来更新和序列化消息的表示。如果未设置 policy,则使用compat32
策略,该策略维护与 Python 3.2 版 email 包的向后兼容性。有关更多信息,请参阅policy
文档。3.3 版更改: 添加了 policy 关键字参数。
- as_string(unixfrom=False, maxheaderlen=0, policy=None)¶
将整个消息扁平化为字符串返回。当可选参数 unixfrom 为 true 时,返回的字符串中包含信封头部。unixfrom 默认为
False
。出于向后兼容性原因,maxheaderlen 默认为0
,因此如果需要不同的值,必须显式覆盖它(此方法将忽略策略中为 max_line_length 指定的值)。policy 参数可用于覆盖从消息实例获取的默认策略。这可用于控制方法产生的一些格式,因为指定的 policy 将传递给Generator
。扁平化消息可能会触发对
Message
的更改,如果需要填充默认值以完成到字符串的转换(例如,可能会生成或修改 MIME 边界)。请注意,此方法仅为方便而提供,可能并不总是按照您希望的方式格式化消息。例如,默认情况下,它不会对以
From
开头的行进行混乱处理,而 Unix mbox 格式需要这种处理。为了获得更大的灵活性,请实例化一个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 默认为
False
。policy 参数可用于覆盖从消息实例获取的默认策略。这可用于控制方法产生的一些格式,因为指定的 policy 将传递给BytesGenerator
。扁平化消息可能会触发对
Message
的更改,如果需要填充默认值以完成到字符串的转换(例如,可能会生成或修改 MIME 边界)。请注意,此方法仅为方便而提供,可能并不总是按照您希望的方式格式化消息。例如,默认情况下,它不会对以
From
开头的行进行混乱处理,而 Unix mbox 格式需要这种处理。为了获得更大的灵活性,请实例化一个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()
以及相关的make
和add
方法取代。
- get_payload(i=None, decode=False)¶
返回当前有效负载,当
is_multipart()
为True
时,它将是Message
对象的列表;当is_multipart()
为False
时,它将是一个字符串。如果有效负载是列表并且您修改了列表对象,则您将就地修改消息的有效负载。使用可选参数 i,如果
is_multipart()
为True
,get_payload()
将返回有效负载的第 i 个元素,从零开始计数。如果 i 小于 0 或大于或等于有效负载中的项目数,则会引发IndexError
。如果有效负载是字符串(即is_multipart()
为False
)并且给出了 i,则会引发TypeError
。可选的 decode 是一个标志,指示是否应根据 Content-Transfer-Encoding 头部解码有效负载。当
True
且消息不是多部分时,如果此头部的值为quoted-printable
或base64
,则有效负载将被解码。如果使用了其他编码,或者缺少 Content-Transfer-Encoding 头部,则有效负载按原样返回(未解码)。在所有情况下,返回值都是二进制数据。如果消息是多部分且 decode 标志为True
,则返回None
。如果有效负载是 base64 且格式不完美(缺少填充、字符不在 base64 字母表中),则会向消息的缺陷属性添加相应的缺陷(InvalidBase64PaddingDefect
或InvalidBase64CharactersDefect
)。当 decode 为
False
(默认值)时,主体作为字符串返回,不解码 Content-Transfer-Encoding。但是,对于 8bit 的 Content-Transfer-Encoding,尝试使用 Content-Type 头部指定的charset
解码原始字节,并使用replace
错误处理程序。如果未指定charset
,或者给定的charset
不被 email 包识别,则使用默认的 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
实例。如果 charset 是None
,则charset
参数将从 Content-Type 头部中删除(消息不会以其他方式修改)。任何其他值将生成TypeError
。如果没有现有的 MIME-Version 头部,则会添加一个。如果没有现有的 Content-Type 头部,则会添加一个值为 text/plain 的头部。无论 Content-Type 头部是否已存在,其
charset
参数都将设置为 charset.output_charset。如果 charset.input_charset 和 charset.output_charset 不同,则有效负载将重新编码为 output_charset。如果没有现有的 Content-Transfer-Encoding 头部,则在需要时,将使用指定的Charset
对有效负载进行传输编码,并添加具有适当值的头部。如果 Content-Transfer-Encoding 头部已存在,则假定有效负载已使用该 Content-Transfer-Encoding 正确编码,并且不会修改。这是一个遗留方法。在
EmailMessage
类上,其功能由email.message.EmailMessage.set_content()
方法的 charset 参数取代。
- get_charset()¶
返回与消息有效负载关联的
Charset
实例。这是一个遗留方法。在
EmailMessage
类上,它总是返回None
。
以下方法实现了一个类似映射的接口,用于访问消息的 RFC 2822 头部。请注意,这些方法与普通映射(即字典)接口之间存在一些语义差异。例如,在字典中没有重复的键,但这里可能存在重复的消息头部。此外,在字典中,
keys()
返回的键没有保证的顺序,但在Message
对象中,头部始终按它们在原始消息中出现的顺序或后来添加到消息中的顺序返回。任何已删除然后重新添加的头部都始终附加到头部列表的末尾。这些语义差异是故意的,并且倾向于最大的便利性。
请注意,在所有情况下,消息中存在的任何信封头部都不包含在映射接口中。
在从字节生成的模型中,任何(违反 RFC 的)包含非 ASCII 字节的头部值,在通过此接口检索时,将表示为
Header
对象,其字符集为unknown-8bit
。- __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()
方法获取所有现有命名头部的值。
- __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 是头部的主值。对于关键字参数字典 _params 中的每个项,键被视为参数名,下划线转换为破折号(因为破折号在 Python 标识符中是非法的)。通常,参数将添加为
key="value"
,除非值为None
,在这种情况下将只添加键。如果值包含非 ASCII 字符,则可以将其指定为格式为(CHARSET, LANGUAGE, VALUE)
的三元组,其中CHARSET
是命名用于编码值的字符集的字符串,LANGUAGE
通常可以设置为None
或空字符串(有关其他可能性,请参阅 RFC 2231),而VALUE
是包含非 ASCII 代码点的字符串值。如果未传递三元组且值包含非 ASCII 字符,则会自动使用utf-8
的CHARSET
和None
的LANGUAGE
以 RFC 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'))
结果是
Content-Disposition: attachment; filename*="iso-8859-1''Fu%DFballer.ppt"
- get_content_type()¶
返回消息的内容类型。返回的字符串将转换为小写形式 maintype/subtype。如果消息中没有 Content-Type 头部,则将返回
get_default_type()
给出的默认类型。由于根据 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/plain 或 message/rfc822,尽管这并非强制执行。默认内容类型不存储在 Content-Type 头部中。
- get_params(failobj=None, header='content-type', unquote=True)¶
返回消息的 Content-Type 参数,作为一个列表。返回列表的元素是键/值对的 2 元组,按
'='
符号分割。'='
左侧是键,右侧是值。如果参数中没有'='
符号,则值为字符串,否则值为get_param()
中所述,如果可选参数 unquote 为True
(默认值),则取消引用。可选参数 failobj 是在没有 Content-Type 头部时返回的对象。可选参数 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。
参数键始终不区分大小写进行比较。返回值可以是字符串,也可以是 3 元组,如果参数是 RFC 2231 编码的。当它是 3 元组时,值的元素形式为
(CHARSET, LANGUAGE, VALUE)
。请注意,CHARSET
和LANGUAGE
都可以是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 的替代头部,并且所有参数都将根据需要引用,除非可选参数 requote 为
False
(默认为True
)。如果指定了可选参数 charset,则参数将根据 RFC 2231 进行编码。可选参数 language 指定 RFC 2231 语言,默认为空字符串。charset 和 language 都应该是字符串。
如果 replace 为
False
(默认值),则头部将移至头部列表的末尾。如果 replace 为True
,则头部将就地更新。3.4 版更改: 添加了
replace
关键字。
- del_param(param, header='content-type', requote=True)¶
从 Content-Type 头部中完全删除给定参数。头部将在原地重写,不带参数或其值。除非 requote 为
False
(默认为True
),否则所有值都将根据需要引用。可选参数 header 指定 Content-Type 的替代头部。
- set_type(type, header='Content-Type', requote=True)¶
设置 Content-Type 头部的主类型和子类型。type 必须是 maintype/subtype 形式的字符串,否则会引发
ValueError
。此方法替换 Content-Type 头部,保留所有参数。如果 requote 为
False
,则保持现有头部的引用不变,否则参数将被引用(默认)。可以在 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
参数的值,如果头部缺失或没有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 头部在头部列表中的顺序。但是,它不保留原始 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,此方法的可能值是 inline、attachment 或None
。在 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()
返回True
,并且walk
进入子部分。
Message
对象还可以选择包含两个实例属性,这些属性在生成 MIME 消息的纯文本时可以使用。- preamble¶
MIME 文档的格式允许在头部后面的空行与第一个多部分边界字符串之间存在一些文本。通常,此文本在支持 MIME 的邮件阅读器中永远不可见,因为它超出标准 MIME 封装。但是,在查看消息的原始文本或在不支持 MIME 的阅读器中查看消息时,此文本可能会变得可见。
preamble 属性包含 MIME 文档的此开头额外封装文本。当
Parser
在头部之后但在第一个边界字符串之前发现一些文本时,它会将此文本分配给消息的 preamble 属性。当Generator
写入 MIME 消息的纯文本表示时,如果它发现消息具有 preamble 属性,它将在头部和第一个边界之间的区域中写入此文本。有关详细信息,请参阅email.parser
和email.generator
。请注意,如果消息对象没有前导码,则 preamble 属性将为
None
。
- epilogue¶
epilogue 属性的作用与 preamble 属性相同,只是它包含出现在最后一个边界和消息末尾之间的文本。
您无需将 epilogue 设置为空字符串,以便
Generator
在文件末尾打印换行符。
- defects¶
defects 属性包含解析此消息时发现的所有问题的列表。有关可能解析缺陷的详细描述,请参阅
email.errors
。