email.message
:表示电子邮件消息¶
源代码: Lib/email/message.py
3.6 版新增: [1]
email
包中的核心类是 EmailMessage
类,从 email.message
模块导入。它是 email
对象模型的基本类。 EmailMessage
提供了设置和查询标头字段、访问消息正文以及创建或修改结构化消息的核心功能。
电子邮件消息由标头和有效负载(也称为内容)组成。标头是 RFC 5322 或 RFC 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
。另请注意,当utf8
为False
(这是默认值)时,此方法仅限于生成序列化为“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 的默认值为
False
。policy 参数可用于覆盖从消息实例获取的默认策略。这可用于控制方法生成的部分格式,因为指定的 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__()
相同,但如果指定的标题不存在,则返回可选的failobj(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 字符,则会使用CHARSET
为utf-8
和LANGUAGE
为None
的 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'))
- 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/plain或message/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 替换其值。当header 为
Content-Type
(默认值)并且头尚未在消息中存在时,添加该头,将其值设置为 text/plain,并附加新的参数值。可选的header 指定 Content-Type 的备用头。如果该值包含非 ASCII 字符,则可以使用可选的charset 和language 参数明确指定字符集和语言。可选的language 指定 RFC 2231 语言,默认为空字符串。charset 和language 都应为字符串。默认情况下,使用
utf8
charset 和None
作为language。如果replace 为
False
(默认值),则将头移动到头列表的末尾。如果replace 为True
,则将就地更新头。在
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,则此方法的可能值为 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
调试帮助器函数在我们的示例中看到这一点>>> 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 必须是来自集合
related
、html
和plain
的字符串序列,并指示返回部件的内容类型的首选项顺序。从调用
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/plain
、text/html
、multipart/related
或multipart/alternative
(除非它们通过 Content-Disposition: attachment 明确标记为附件),并返回所有剩余部分。当直接应用于multipart/related
时,返回一个迭代器,用于遍历除根部分(即由start
参数指向的部分,如果没有start
参数,或者start
参数与任何部分的 Content-ID 不匹配,则为第一部分)之外的所有相关部分。当直接应用于multipart/alternative
或非multipart
时,返回一个空迭代器。
- get_content(*args, content_manager=None, **kw)¶
调用 content_manager 的
get_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)¶
将非
multipart
或multipart/related
转换为multipart/alternative
,将任何现有的 Content- 头和有效负载移动到multipart
的(新)第一部分中。如果指定了 boundary,请将其用作 multipart 中的边界字符串,否则将边界保留为在需要时自动创建(例如,当消息被序列化时)。
- make_mixed(boundary=None)¶
将非
multipart
、multipart/related
或multipart-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
。如果消息是非multipart
或multipart/related
,调用make_alternative()
,然后按上述方式进行。如果消息是任何其他类型的multipart
,引发TypeError
。如果未指定 content_manager,请使用当前policy
指定的content_manager
。
- add_attachment(*args, content_manager=None, **kw)¶
如果消息是
multipart/mixed
,创建一个新消息对象,将所有参数传递给它的set_content()
方法,并attach()
它到multipart
。如果消息是非multipart
、multipart/related
或multipart/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.parser
和email.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 标头。
脚注