:使用 – 表示电子邮件消息 – – 电子邮件和MIME处理包(Python教程)(参考资料)
email.message.Message
:使用compat32
API表示电子邮件
Message
类与EmailMessage
class,没有由theclass添加的方法,并且某些其他方法的默认行为略有不同。我们还在这里记录了一些方法,这些方法虽然得到了EmailMessage
除非你要使用传统代码,否则不推荐使用.
两个类的理念和结构是相同的.
本文档描述了默认(对于Message
)策略Compat32
下的行为。如果你要使用另一个策略,你应该使用EmailMessage
类来代替
电子邮件由headers和payload组成。标题必须是 RFC 5233 样式名称和值,其中字段名称和值由冒号分隔。冒号不是字段名称或字段值的一部分。有效载荷可以是简单的文本消息,或二进制对象,或者是子消息的结构化序列,每个子消息具有它们自己的标题集和它们自己的有效载荷。后一种类型的有效负载由具有MIME类型的消息表示,例如multipart/*或message/rfc822.
Message
对象提供的概念模型是带有附加的标题的有序字典的模型用于从头部访问特定信息,用于访问有效载荷,用于生成消息的序列化版本以及用于递归地遍历对象树的方法。请注意,支持重复的标题,但必须使用特殊的方法来访问它们.
Message
伪字典由标题名称索引,标题名称必须是ASCII值。字典的值是仅包含ASCII字符的字符串;对于非ASCII输入有一些特殊处理,但它并不总能产生正确的结果。Headers存储并以保留大小写的形式返回,但字段名称不匹配。可能还有一个信封标题,也称为Unix-From标题或From_
标题。payload是字符串或字节,对于简单的消息对象,或者是Message
对象的列表,对于MIME容器文档(例如multipart/*和message/rfc822).
以下是Message
类的方法:
- class
email.message.
Message
(policy=compat32) -
如果指定policy(它必须是一个实例一个
policy
class)使用它指定的规则来更新和序列化消息的表示。如果policy未设置,请使用compat32
策略,保持与Python 3.2版本的电子邮件包的向后兼容性。有关更多信息,请参阅policy
documentation.更改版本3.3:添加了policy关键字参数
as_string
(unixfrom=False, maxheaderlen=0, policy=None)-
将整个消息展平为字符串。当可选unixfrom为真时,信封标题包含在返回的字符串中.unixfrom默认为
False
。出于向后兼容的原因,maxheaderlen默认为0
,所以如果你想要一个不同的值,你必须明确地覆盖它(这个方法将忽略为策略中的max_line_length指定的值)。policy参数可以用来覆盖从消息实例中获取的默认策略。这可以用来控制由方法生成的一些格式,因为指定的policy将被传递给Generator
.展平消息可能会触发对
Message
ifdefaults需要填写以完成对字符串的转换(例如,可以生成或修改MIME边界).请注意,此方法是为了方便而提供的,并且可能无法始终按照您的方式格式化消息想。例如,默认情况下,它不会对以unix mbox格式所需的
From
开头的行进行修改。为了更灵活,实例化一个Generator
实例并直接使用它的flatten()
方法。例如:from io import StringIOfrom email.generator import Generatorfp = 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
.展平消息可能会触发对
Message
的更改if iffaults需要填写以完成对字符串的转换(例如,可能会生成或修改MIME边界).请注意,此方法是为方便起见而提供的,并不总是按照您希望的方式格式化消息。例如,默认情况下,它不会对以unix mbox格式所需的
From
开头的行进行修改。为了更加灵活,实例化一个BytesGenerator
实例并直接使用它的flatten()
方法。例如:from io import BytesIOfrom email.generator import BytesGeneratorfp = BytesIO()g = BytesGenerator(fp, mangle_from_=True, maxheaderlen=60)g.flatten(msg)text = fp.getvalue()
版本3.4.
__bytes__
()-
相当于
as_bytes()
。允许bytes(msg)
生成包含格式化消息的abytes对象.版本3.4.
is_multipart
()-
返回
True
如果消息的有效载荷是子列表Message
对象,否则返回False
。当is_multipart()
返回False
,有效载荷应该是一个stringobject(可能是CTE编码的二进制有效载荷)。(注意is_multipart()
返回True
并不一定意味着“msg.get_content_maintype()==’multipart’”将返回True
。例如,is_multipart
将返回True
当。。。的时候Message
是message/rfc822
。)
set_unixfrom
(unixfrom)-
将邮件的信封标题设置为unixfrom,这应该是一个字符串.
get_unixfrom
()-
返回邮件的信封标题。如果从未设置过信封标题,则默认为
None
attach
// (payload)-
将给定的payload添加到当前有效负载中,在调用之前必须是
None
或Message
对象列表。通话结束后,thepayload将始终是Message
对象。如果要将有效负载固定为标量对象(例如字符串),请使用set_payload()
代替。这是一种传统方法。在
EmailMessage
它的功能是由set_content()
替换的make
和add
方法.
get_payload
(i=None, decode=False)-
返回当前有效负载,当
Message
是is_multipart()
时,它将是True
对象的列表,当is_multipart()
是False
时,它是astring。如果有效负载是一个列表,你改变了列表对象,你就可以修改消息的有效负载了带有可选参数i,
get_payload()
将返回i – 有效负载的元素,从零开始计算,如果is_multipart()
是True
。如果IndexError
小于0或大于或等于有效载荷中的项目数,则i将被引发。如果thepayload是一个字符串(即is_multipart()
是False
)和i被接受,则TypeError
被提出可选decode是一个标志,指示有效负载是否应该被解码,根据Content-Transfer-Encoding标头。当
True
并且消息不是多部分时,如果此标头的值为quoted-printable
或base64
,则有效负载将被解码。如果使用其他编码,或者Content-Transfer-Encoding标头丢失,有效负载按原样返回(未解码)。在所有情况下,返回的值都是binarydata。如果消息是一个多部分并且decode标志是True
,那么None
退回。如果有效负载是base64并且它没有完美地形成(缺少填充,base64alphabet之外的字符),那么将在消息的缺陷属性中添加一个适当的缺陷(InvalidBase64PaddingDefect
或InvalidBase64CharactersDefect
,分别).当decode是
False
(默认值)时,身体将以字符串形式返回而不解码Content-Transfer-Encoding。但是,对于Content-Transfer-Encoding8位,尝试使用解码原始字节charset
由指定Content-Type标题,使用replace
错误处理程序。如果没有charset
是指定,还是charset
如果没有通过电子邮件包识别,则使用defaultASCII charset解码正文.这是一种传统方法。在
EmailMessage
类的功能是由get_content()
和iter_parts()
.
set_payload
(payload, charset=None)-
将整个消息对象的有效负载设置为payload。客户的责任是确保有效载荷不变量。可选charset设置消息的默认字符集;看
set_charset()
详情.这是一种传统方法。在
EmailMessage
类的功能是由set_content()
.
set_charset
(charset)-
将有效负载的字符集设置为charset,可以是
Charset
instance(请参阅email.charset
),字符串命名字符集或None
。如果是字符串,它将被转换为Charset
实例。如果charset是None
,charset
参数将从Content-Type标题(该消息不会被修改)。其他任何东西都会生成一个TypeError
.如果没有现有的MIME-Version标题就会产生一个问题。如果没有Content-Type标题,one将添加值text/plain。无论Content-Type标题是否已存在,其
charset
参数都将设置为charset.output_charset。如果charset.input_charset和charset.output_charset不同,有效载荷将重新编码到output_charset。如果没有Content-Transfer-Encoding标题,然后有效负载将根据需要使用指定的转移编码Charset
,并添加具有适当值的标题。如果存在Content-Transfer-Encoding headeral,则假定有效负载已经使用Content-Transfer-Encoding正确编码并且未被修改.这是一种传统方法。在
EmailMessage
类中它的功能被charset方法的email.emailmessage.EmailMessage.set_content()
参数替换.
get_charset
()-
返回
Charset
与themessage的有效载荷相关的实例.这是一种传统方法。在
EmailMessage
它总是返回None
.
以下方法实现了一个类似于映射的接口来访问themessage的 RFC 2822 头。注意,这些方法与普通映射(即字典)接口之间存在一些语义差异。例如,在字典中没有重复的键,但这里可能有重复的消息头。此外,在词典中,
keys()
,但是在Message
对象,标题始终按它们在原始消息中出现的顺序返回,或者稍后添加到消息中。删除和重新添加的任何标题始终附加到标题列表的末尾.这些语义差异是有意的,并且偏向于最大的便利性.
请注意,在所有情况下,消息中存在的任何信封标题都不包含在映射界面中.
在从字节生成的模型中,任何通过此接口检索的(违反RFC)包含非ASCII字节的标头值将表示为
Header
对象与未知-8位的字符集.__len__
()-
返回标题总数,包括重复数.
__contains__
(name)-
如果消息对象有一个名为name。匹配是不区分大小写的,name不应该包含尾随冒号。用于
in
操作符,例如:if "message-id" in myMessage: print("Message-ID:", myMessage["message-id"])
__getitem__
(name)-
返回指定标题字段的值。name不应包括colon字段分隔符。如果缺少标题,则返回
None
;aKeyError
永远不会被提升.注意如果命名字段在消息的标题中出现不止一次,那么将确定返回哪些字段值。使用
get_all()
方法获取所有现有命名标题的值.
__setitem__
(name, val)-
用字段名称//添加标题name和值val。字段附加到消息现有字段的末尾.
注意这样做not覆盖或删除任何具有相同名称的现有标题。如果你想确保新标题是featuressage中唯一一个字段名为name的标题,请首先删除该字段,例如:
del msg["subject"]msg["subject"] = "Python roolz!"
__delitem__
(name)-
从消息的标题中删除名称为name的所有字段。如果在标题中没有指定的字段,则不会引发异常.
keys
()-
返回所有消息标题字段名称的列表.
values
()-
返回所有消息字段值的列表.
items
()-
返回包含所有消息的字段标题和值的2元组列表.
get
(name, failobj=None)-
返回指定标头字段的值。这与
__getitem__()
完全相同,只是如果缺少waitamed标题,则返回可选的failobj(默认为None
).
以下是一些其他有用的方法:
get_all
(name, failobj=None)-
返回名为name的字段的所有值的列表。如果消息中没有这样的命名标题,failobj返回(默认为
None
).
add_header
(_name, _value, **_params)-
扩展页眉设置。此方法类似于
__setitem__()
,但可以将其他标头参数作为keywordarguments提供。_name是要添加的标题字段,_value是标题的primary值.对于关键字参数字典中的每个项目_params,密钥作为参数名称,下划线转换为破折号(在Python标识符中,sincedashes是非法的)。通常,参数将添加为
key="value"
,除非值为None
,在这种情况下,只会添加密钥。如果值包含非ASCII字符,则可以将其指定为(CHARSET, LANGUAGE, VALUE)
格式的三元组,其中CHARSET
是一个字符串命名用于编码值的字符串,LANGUAGE
通常可以设置为None
或空字符串(参见 RFC 2231 其他可能性)和VALUE
是包含非ASCII代码点的字符串值。如果没有传递三个元组,并且该值包含非ASCII字符,则使用自动编码为 RFC 2231CHARSET
对utf-8
和LANGUAGE
对None
.这是一个例子:
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
()-
返回邮件的主要内容类型。这是maintype由
get_content_type()
.
get_content_subtype
()-
返回的字符串的一部分//返回消息的子内容类型。这是subtype由
get_content_type()
.
get_default_type
()-
返回的字符串的一部分//返回默认的内容类型。大多数邮件的默认内容类型为text/plain,除了作为multipart/digest容器的子部分的消息。这些子部分的默认内容类型为message/rfc822.
set_default_type
(ctype)-
设置默认内容类型。ctype应该是text/plain或message/rfc822,虽然这不是强制性的。默认内容类型不存储在Content-Type header.
get_params
(failobj=None, header=”content-type”, unquote=True)-
返回消息的Content-Type参数,作为list。返回列表的元素是2元组的键/值对,在
"="
符号上是assplit。"="
的左侧是键,而右侧是值。如果参数中没有"="
符号,则该值为空字符串,否则该值如get_param()
所示,如果可选unquote是True
则不加引号(默认).可选failobj是没有Content-Type标题时返回的对象。可选header是标题tosearch而不是Content-Type.
这是一种遗留方法。在
EmailMessage
类上它的功能由params属性.
get_param
(param, failobj=None, header=”content-type”, unquote=True)-
将Content-Type header的参数param的值作为字符串返回。如果消息没有Content-Type标题或者没有这样的参数,则返回failobj(默认为
None
).可选header如果给定,则指定要使用的消息头而不是Content-Type.
参数键总是在不区分大小写的情况下进行比较。返回值可以是字符串,如果参数是RFC 2231 编码。当它是一个3元组时,值的元素的形式为
(CHARSET, LANGUAGE, VALUE)
。注意CHARSET
和LANGUAGE
都可以是None
,在这种情况下你应该考虑VALUE
在us-ascii
charset编码。您通常可以忽略LANGUAGE
.如果您的应用程序不关心参数是否编码为 RFC 2231 ,你可以通过调用
email.utils.collapse_rfc2231_value()
来折叠参数值,传入get_param()
。当值为元组时,这将返回适当解码的Unicodestring,如果不是,则返回未引用的原始字符串。例如: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标题中完全删除给定的参数。标题将在没有参数orits值的情况下重新编写。除非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)-
返回
filename
消息的Content-Disposition标题的参数。如果headerdoes没有filename
参数,这个方法可以回到查找name
上的Content-Type头。如果找不到,或者标题丢失,则返回failobj。返回的字符串将始终不加引号email.utils.unquote()
.
get_boundary
(failobj=None)-
返回
boundary
Content-Type消息的标题,或failobj如果缺少标题,或者没有boundary
参数。返回字符串将始终不加引号email.utils.unquote()
.
set_boundary
(boundary)-
设置
boundary
的Content-Type标题为boundary.set_boundary()
总会引用boundary如果必要的话。一个HeaderParseError
如果themessage对象没有Content-Typeheader.请注意,使用此方法与删除旧的Content-Type标题,并通过
add_header()
添加一个新的边界,因为set_boundary()
在头部列表中保存Content-Type标题的顺序。但它确实not保留原来可能存在的任何延续线Content-Type header.
get_content_charset
(failobj=None)-
返回的
charset
参数Content-Type标题,胁迫小写。如果没有Content-Type标题,或者如果标题没有charset
参数,则failobj返回.注意这个方法不同于
get_charset()
返回Charset
instance用于消息体的默认编码.
get_charsets
(failobj=None)-
返回包含消息中字符集名称的列表。如果主题是multipart,然后列表将包含有效负载中每个子部分的一个元素,否则,它将是一个长度为1.的列表
列表中的每个项目都是一个字符串,它是
charset
所有子部分的Content-Type标题中的参数。但是,如果子部分没有Content-Type标题,没有charset
参数,或者不是text主MIME类型,然后返回列表中的该项将是failobj.
get_content_disposition
()-
返回消息的Content-Disposition标题的小写值(不带参数)如果它有一个,或
None
。这个方法的可能值是inline, attachment或None
如果消息如下 RFC 2183 .版本3.5中的新内容
walk
//()-
walk()
method是一个通用的生成器,可用于对消息对象树的所有部分和子部分进行深思熟虑,即深度优先遍历顺序。你通常会使用walk()
作为中的主人for
环;每次迭代都会返回下一个子部分.这是一个打印多部分消息结构的每个部分的MIME类型的示例:
>>> for part in msg.walk():... print(part.get_content_type())multipart/reporttext/plainmessage/delivery-statustext/plaintext/plainmessage/rfc822text/plain
walk
迭代is_multipart()
返回True
的任何部分的子部分,即使msg.get_content_maintype() == "multipart"
可能会返回False
。我们可以通过使用_structure
debughelper function:>>> for part in msg.walk():... print(part.get_content_maintype() == "multipart",... part.is_multipart())True TrueFalse FalseFalse TrueFalse FalseFalse FalseFalse TrueFalse 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属性包含此主要的额外装甲文本MIMEdocuments。当
Parser
在标题之后但在第一个边界字符串之前发现一些文本时,它会将此文本分配给消息的preamble属性。当。。。的时候Generator
正在写出MIME消息的纯文本表示,并且它发现themessage具有preamble属性,它将在头文件和第一个边界之间的文本中写入此文本。见email.parser
和email.generator
详情.请注意,如果消息对象没有前导码,则preamble属性将是
None
.
epilogue
-
epilogue属性的行为与preamble属性,除了它包含出现在消息的最后一个边界和结尾之间的文本.
你不需要将结尾设置为空字符串以便
Generator
在文件末尾打印换行符.
defects
-
defects属性包含解析此消息时发现的所有问题的列表。见
email.errors
有关可能的解析缺陷的详细说明.