19.1.1. email.message:表示电子邮件

源代码: Lib / email / message.py

email包中的中心类是从email.message模块导入的Message类。它是email对象模型的基类。Message提供了设置和查询标头字段以及访问消息体的核心功能。

概念上,Message对象由有效载荷组成。标头是 RFC 2822样式字段名称和值,其中字段名称和值由冒号分隔。冒号不是字段名称或字段值的一部分。

标题以保存形式存储和返回,但不区分大小写。还可以有单个包络头,也称为Unix-From头或From_头。有效载荷是在简单消息对象的情况下的字符串或者对于MIME容器文档的Message对象的列表。multipart / *message / rfc822)。

Message对象提供用于访问消息头的映射样式接口,以及用于访问头和净荷的显式接口。它提供了方便的方法来生成消息对象树的平面文本表示,用于访问常用的头参数,以及递归地遍历对象树。

以下是Message类的方法:

class email.message.Message(policy=compat32)

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

在版本3.3中已更改:添加了策略关键字参数。

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

返回全部消息以字符串的形式当可选unixfrom为真时,包络头将包含在返回的字符串中。unixfrom默认为False对于向后合并的原因,maxheaderlen默认为0,因此如果您想要不同的值,则必须明确覆盖它(max_line_length该策略将被此方法忽略)。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中已更改: t>>添加了策略关键字参数。

__str__()

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

as_bytes(unixfrom=False, policy=None)

返回作为字节对象展平的整个消息。当可选unixfrom为真时,包络头将包含在返回的字符串中。unixfrom默认为Falsepolicy参数可用于覆盖从消息实例获取的默认策略。这可以用于控制由该方法生成的某些格式,因为指定的策略将传递到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()

如果邮件的有效内容是sub Message对象的列表,则返回True,否则返回Falseis_multipart()返回False时,有效内容应为字符串对象。(请注意,is_multipart()返回True并不一定意味着“msg.get_content_maintype()=='multipart'”将返回True例如,当Message类型为message/rfc822时,is_multipart将返回True

set_unixfrom(unixfrom)

将邮件的包络头设置为unixfrom,应为字符串。

get_unixfrom()

返回邮件的信封头如果信封标题从未设置,则默认为None

attach(payload)

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

get_payload(i=None, decode=False)

返回当is_multipart()True时,Message对象的列表,或is_multipart()False如果有效载荷是一个列表,并且您改变列表对象,您就可以修改消息的有效载荷。

使用可选参数iget_payload()将返回有效负载的i元素,如果is_multipart()True如果i小于0或大于或等于有效载荷中的项目数,则会引发IndexError如果有效载荷是字符串(即,is_multipart()False)和i时,会出现TypeError

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

解码False(默认值)时,主体作为字符串返回,而不解码Content-Transfer-Encoding但是,对于8比特的内容传输编码,尝试使用由内容类型指定的charset >标头,使用replace错误处理程序。如果未指定charset,或者如果给定的charset无法被电子邮件包识别,则使用默认的ASCII字符集解码正文。

set_payload(payload, charset=None)

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

set_charset(charset)

将有效负载的字符集设置为charset,可以是Charset实例(请参阅email.charset),设置,或None如果它是一个字符串,它将被转换为Charset实例。如果字符集None,则charset参数将从Content-Type否则修改)。任何其他将生成TypeError

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

get_charset()

返回与消息的有效内容相关联的Charset实例。

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

这些语义差异是有意的,并且偏向于最大的方便。

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

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

__len__()

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

__contains__(name)

如果消息对象具有名为name的字段,则返回true。匹配不区分大小写,名称不应包含结尾冒号。用于in操作符,例如

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

返回指定头字段的值。名称不应包含冒号字段分隔符。如果标头缺失,则返回None;从不引发KeyError

请注意,如果命名字段在消息的标头中多次出现,则不确定将返回哪些字段值。使用get_all()方法获取所有现有命名标头的值。

__setitem__(name, val)

在字段名称名称和值val的邮件中添加标题。该字段将追加到消息的现有字段的末尾。

请注意,不会覆盖或删除任何具有相同名称的现有标题。如果您想要确保新标头是邮件中只有一个字段名为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是头的值。

对于关键字参数字典_params中的每个项目,将键作为参数名称,将下划线转换为破折号(因为破折号在Python标识符中是非法的)。通常,该参数将作为key="value"添加,除非该值为None,在这种情况下将仅添加密钥。如果值包含非ASCII字符,则可以指定为(CHARSET, LANGUAGE, VALUE) t3格式的三元组>,其中CHARSET是用于对值进行编码的字符集的字符串,LANGUAGE通常可以设置为None或空字符串(有关其他可能性,请参见 RFC 2231),VALUE是包含非ASCII代码点的字符串值。If a three tuple is not passed and the value contains non-ASCII characters, it is automatically encoded in RFC 2231 format using a CHARSET of utf-8 and a LANGUAGE of 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 t4 >。

get_content_maintype()

返回邮件的主要内容类型。这是由get_content_type()返回的字符串的主类型部分。

get_content_subtype()

返回邮件的子内容类型。这是由get_content_type()返回的字符串的子类型部分。

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()中所述,如果可选,unquoteTrue(默认值)。

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

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

Content-Type头参数param的值作为字符串返回。如果消息没有Content-Type头,或者如果没有此类参数,则返回failobj(默认为None)。

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

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

If your application doesn’t care whether the parameter was encoded as in RFC 2231, you can collapse the parameter value by calling email.utils.collapse_rfc2231_value(), passing in the return value from get_param(). 当值是元组时,将返回一个适当解码的Unicode字符串,否则返回原始字符串。例如:

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

In any case, the parameter value (either the returned string, or the VALUE item in the 3-tuple) is always unquoted, unless unquote is set to False.

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

Content-Type标题中设置参数。如果参数已存在于标头中,则其值将替换为value如果Content-Type头尚未为此消息定义,则它将设置为text / plain,新参数值将根据 RFC 2045

Optional header specifies an alternative header to Content-Type, and all parameters will be quoted as necessary unless optional requote is False (the default is True).

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

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

在版本3.4中已更改: replace添加了关键字。

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

Content-Type标题中完全删除给定的参数。标题将重新写入到位,没有参数或其值。除非requoteFalse(默认值为True),否则所有值都将被引用。可选指定Content-Type的替代方法。

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

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

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

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

get_filename(failobj=None)

返回消息的Content-Disposition标头的filename参数的值。如果标头没有filename参数,此方法将回到在Content-Type标头上寻找name参数。如果没有找到,或者标头丢失,则返回failobj返回的字符串将始终不按照email.utils.unquote()引用。

get_boundary(failobj=None)

返回邮件Content-Type标头的boundary参数的值,如果标头缺失或没有,则返回failobj boundary参数。返回的字符串将始终不按照email.utils.unquote()引用。

set_boundary(boundary)

Content-Type标头的boundary参数设为boundaryset_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参数,或者不是文本主MIME类型,在返回的列表中将是failobj

get_content_disposition()

返回消息的Content-Disposition头的低位值(无参数)(如果有),或NoneThe possible values for this method are inline, attachment or None if the message follows RFC 2183.

版本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 iterates over the subparts of any part where is_multipart() returns True, even though msg.get_content_maintype() == 'multipart' may return 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感知读取器中查看邮件时,此文本可能会变为可见。

前导码属性包含MIME文档的此前导装饰文本。Parser发现标头之后但在第一个边界字符串之前的一些文本时,它将此文本分配给消息的前导码属性。Generator写出MIME消息的纯文本表示形式,并且它发现该消息具有前导码属性时,它将该文本写入标题和第一个边界。有关详细信息,请参见email.parseremail.generator

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

epilogue

结尾属性的行为与前导符属性的行为相同,除了它包含出现在消息的最后边界和结尾之间的文本。

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

defects

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