19.1.9. email.message.Message
:使用 compat32
API表示电子邮件¶
Message
类非常类似于 EmailMessage
类,没有该类添加的方法,并且某些其他方法的默认行为略有不同。我们还在这里记录了一些方法,虽然 EmailMessage
类支持,不推荐,除非你在处理遗留代码。
两个类的哲学和结构在其他方面是一样的。
本文档描述了默认(对于 Message
)策略 Compat32
的行为。如果你要使用另一个策略,你应该使用 EmailMessage
类。
电子邮件由 headers 和 payload 组成。标题必须是 RFC 5233 样式的名称和值,其中字段名称和值由冒号分隔。冒号不是字段名称或字段值的一部分。有效载荷可以是简单文本消息,或二进制对象或子消息的结构化序列,每个子消息具有它们自己的一组头部和它们自己的有效载荷。后一类型的有效载荷由具有诸如 multipart/* 或 message/rfc822 的MIME类型的消息指示。
Message
对象提供的概念模型是头部的有序字典,具有用于从头部访问专用信息,用于访问有效载荷,用于生成mssage的序列化版本以及用于递归地遍历对象树的附加方法。请注意,支持重复的标头,但必须使用特殊方法来访问它们。
Message
psuedo字典由标题名称索引,标题名称必须是ASCII值。字典的值是应该只包含ASCII字符的字符串;有一些特殊的处理非ASCII输入,但它并不总是产生正确的结果。头以字节保存的形式存储和返回,但字段名匹配大小写不敏感。还可以存在单个包络报头,也称为 Unix-From 报头或 From_
报头。对于MIME容器文档(例如 multipart/* 和 message/rfc822),payload 是在简单消息对象的情况下的字符串或字节,或者是 Message
对象的列表。
这里是 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 为真时,包络头包含在返回的字符串中。 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 为真时,包络头包含在返回的字符串中。 unixfrom 默认为
False
。 policy 参数可以用于覆盖从消息实例获得的默认策略。这可以用于控制由该方法产生的一些格式化,因为指定的 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()
和重现的make
和add
方法代替。
-
get_payload
(i=None, decode=False)¶ 返回当前有效负载,当
is_multipart()
是True
时,它将是一个Message
对象的列表,或者当is_multipart()
是False
时是一个字符串。如果有效内容是一个列表,并且您改变列表对象,您就可以修改消息的有效内容。使用可选参数 i,
get_payload()
将返回有效载荷的第 i 个元素,如果is_multipart()
是True
,则从零开始计数。如果 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。然而,对于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
实例。如果 charset 是None
,则将从 Content-Type 标题中移除charset
参数(该消息不会被另外修改)。任何其他将生成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.emailmessage.EmailMessage.set_content()
方法的 charset 参数代替。
以下方法实现类似映射的接口来访问消息的 RFC 2822 头。注意,在这些方法和正常映射(即字典)接口之间存在一些语义差异。例如,在字典中没有重复的键,但在这里可能有重复的邮件标题。另外,在字典中,
keys()
返回的键没有保证顺序,但是在Message
对象中,标头总是按照它们在原始消息中出现的顺序返回,或者稍后添加到消息中。任何头删除,然后重新添加总是附加到头列表的末尾。这些语义差异是有意的,并且偏向于最大的方便。
注意,在所有情况下,消息中存在的任何包络头都不包括在映射接口中。
在从字节生成的模型中,任何(违反RFC)包含非ASCII字节的标头值将通过此接口检索时,表示为具有 unknown-8bit 字符集的
Header
对象。-
__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 的消息中添加标题。该字段将追加到消息的现有字段的末尾。
请注意,这会使 not 覆盖或删除具有相同名称的任何现有标题。如果要确保新标头是消息中唯一存在的字段名为 name 的消息,请先删除该字段,例如。:
del msg['subject'] msg['subject'] = 'Python roolz!'
-
__delitem__
(name)¶ 从邮件标头中删除名称为 name 的所有字段。如果指定的字段不存在于标头中,则不会引发异常。
-
keys
()¶ 返回所有消息的头字段名称的列表。
-
values
()¶ 返回所有消息的字段值的列表。
-
items
()¶ 返回包含所有消息的字段标头和值的2元组列表。
-
get
(name, failobj=None)¶ 返回指定头字段的值。这与
__getitem__()
相同,除非如果指定的标头缺失(默认为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-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"
-
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 容器内,在这种情况下它将是 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
(默认值),则该值为非引号。如果没有 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元组。当它是一个3元组,值的元素是
(CHARSET, LANGUAGE, VALUE)
的形式。注意,CHARSET
和LANGUAGE
都可以是None
,在这种情况下,您应该考虑VALUE
在us-ascii
字符集中进行编码。你通常可以忽略LANGUAGE
。如果您的应用程序不关心参数是否编码为 RFC 2231 中,您可以通过调用
email.utils.collapse_rfc2231_value()
来折叠参数值,传入来自get_param()
的返回值。当值为元组时,将返回一个适当解码的Unicode字符串,否则返回原始字符串unquoted。例如: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 标题的顺序。然而,它确实 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,则此方法的可能值为 inline,attachment 或None
。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()
返回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 属性相同,除了它包含出现在消息的最后边界和结尾之间的文本。
您不需要将结尾设置为空字符串,以便
Generator
在文件末尾打印换行符。
-
defects
¶ defects 属性包含解析此消息时发现的所有问题的列表。有关可能的解析缺陷的详细描述,请参阅
email.errors
。
-