email.message:代表电子邮件

源代码: Lib/email/message.py


3.6 版的新Function:[1]

email包中的中心类是EmailMessage类,从email.message模块导入。它是email对象模型的 Base Class。 EmailMessage提供了用于设置和查询头字段,访问消息正文以及创建或修改结构化消息的核心Function。

电子邮件由* header payload (也称为 content )组成。Headers 是 RFC 5322 RFC 6532样式的字段名称和值,其中字段名称和值之间用冒号分隔。冒号既不是字段名也不是字段值的一部分。有效负载可以是简单的文本消息,也可以是二进制对象,也可以是子消息的结构化序列,每个子消息都具有自己的 Headers 集和自己的有效负载。有效负载的后一种类型由具有 MIME 类型的消息(例如 multipart/* message/rfc822 *)指示。

EmailMessage对象提供的概念模型是标题的有序词典的模型,该模板与表示消息的 RFC 5322正文的* payload *耦合,该正文可能是 subEmailMessage对象的列表。除了用于访问 Headers 名称和值的常规词典方法之外,还有一些方法可以从 Headers 访问特殊信息(例如 MIMEContent Type),对有效负载进行操作,生成消息的序列化版本以及递归地遍历对象树。

EmailMessage类似字典的接口由 Headers 名称索引,Headers 名称必须是 ASCII 值。字典的值是带有一些额外方法的字符串。Headers 以保留大小写的形式存储和返回,但是字段名称不区分大小写。与 true 的字典不同,这些键有一个排序,并且可以有重复的键。提供了其他方法来处理具有重复键的 Headers。

对于简单的邮件对象,对于诸如* multipart/* message/rfc822 邮件对象之类的 MIME 容器文档, payload *是字符串对象或字节对象,或者是EmailMessage对象列表。

    • class * email.message. EmailMessage(* policy = default *)
    • 如果指定了* policy ,则使用规则指定更新和序列化消息表示的规则。如果未设置 policy *,请使用default策略,该策略遵循电子邮件 RFC 的规则,但行尾除外(而不是 RFC 强制的\r\n,它使用 Python 标准\n行尾)。有关更多信息,请参见policy文档。
  • as_string(* unixfrom = False maxheaderlen = None policy = None *)

    • 返回整平为字符串的整个消息。当可选的* unixfrom *为 true 时,信封头包含在返回的字符串中。 * unixfrom 默认为False。为了与 Base ClassMessage向后兼容 maxheaderlen *,但默认值为None,这意味着默认情况下,行长由策略的max_line_length控制。 * policy 参数可用于覆盖从消息实例获得的默认策略。由于指定的 policy *将传递给Generator,因此可以用来控制该方法产生的某些格式。

如果需要填写默认值以完成对字符串的转换(例如,可能会生成或修改 MIME 边界),则拼合消息可能会触发对EmailMessage的更改。

请注意,此方法是为了方便起见而提供的,可能不是在应用程序中序列化消息的最有用的方法,尤其是在处理多个消息时。有关用于序列化消息的更灵活的 API,请参见email.generator.Generator。另请注意,当utf8False时(默认设置),该方法仅限于生成序列化为“ 7 位清除”的消息。

在版本 3.6 中更改:未指定* maxheaderlen 时的默认行为已从策略更改为默认值至默认值* 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,因此可以用来控制该方法产生的某些格式。

如果需要填写默认值以完成对字符串的转换(例如,可能会生成或修改 MIME 边界),则拼合消息可能会触发对EmailMessage的更改。

请注意,此方法是为了方便起见而提供的,可能不是在应用程序中序列化消息的最有用的方法,尤其是在处理多个消息时。有关用于序列化消息的更灵活的 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 *)

    • 将邮件的信封 Headers 设置为* unixfrom *,它应该是一个字符串。 (有关此 Headers 的简要说明,请参见mboxMessage。)
  • get_unixfrom ( )

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

以下方法实现了用于访问消息头的类 Map 接口。请注意,这些方法与常规 Map(即字典)接口之间在语义上有所不同。例如,在词典中没有重复的键,但是这里可能有重复的消息头。同样,在字典中并没有保证keys()返回的键的 Sequences,但是在EmailMessage对象中,Headers 总是按照它们在原始消息中出现的 Sequences 返回,或者以后又添加到消息中。删除然后重新添加的所有 Headers 始终附加在 Headers 列表的末尾。

这些语义差异是有意的,在最常见的用例中偏向于方便。

请注意,在所有情况下,消息中存在的任何信封头都不会包含在 Map 接口中。

  • __len__ ( )

    • 返回标题总数,包括重复项。
  • __contains__(* name *)

    • 如果消息对象具有名为* name 的字段,则返回True。匹配时不考虑大小写,并且 name *不包括结尾的冒号。用于in运算符。例如:
if 'message-id' in myMessage:
   print('Message-ID:', myMessage['message-id'])
  • __getitem__(* name *)
    • 返回命名标题字段的值。 名称不包含冒号字段分隔符。如果缺少标题,则返回None;否则,返回_。永远不会提出KeyError

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

使用标准(非compat32)策略,返回值是email.headerregistry.BaseHeader子类的实例。

  • __setitem__(* name val *)
    • 向消息添加 Headers,其字段名称为* name ,值为 val *。该字段将附加到邮件现有标题的末尾。

请注意,这不会覆盖或删除任何具有相同名称的现有 Headers。如果要确保新标题是消息中字段名称为* name *的唯一字段,请首先删除该字段,例如:

del msg['subject']
msg['subject'] = 'Python roolz!'

如果policy将某些 Headers 定义为唯一(如标准策略所做的那样),则当try为某个 Headers 分配值(如果已经存在)时,此方法可能会引发ValueError。出于一致性考虑,此行为是有意的,但不依赖于此行为,因为我们将来可能会选择使此类分配对现有 Headers 进行自动删除。

  • __delitem__(* name *)

    • 从邮件标题中删除所有出现的名称为* name *的字段。如果标题字段中不存在命名字段,则不会引发异常。
  • keys ( )

    • 返回所有消息标题字段名称的列表。
  • values ( )

    • 返回所有消息字段值的列表。
  • items ( )

    • 返回一个包含所有消息字段标题和值的 2Tuples 列表。
  • get(* name failobj = None *)

    • 返回命名标题字段的值。这与getitem()相同,除了如果缺少指定的 Headers 则返回可选的* failobj ( failobj *默认为None)。

以下是一些其他有用的 Headers 相关方法:

  • get_all(* name failobj = None *)

    • 返回名为* name 的字段的所有值的列表。如果消息中没有这样的命名头,则返回 failobj *(默认为None)。
  • add_header(* _name _value ** _ params *)

    • 扩展头设置。此方法与setitem()相似,不同之处在于可以提供其他 Headers 参数作为关键字参数。 * _name 是要添加的标题字段, _ value 是标题的 primary *值。

对于关键字参数字典* _params *中的每个项目,都将键作为参数名称,并将下划线转换为破折号(因为破折号在 Python 标识符中是非法的)。通常,除非值是None,否则参数将被添加为key="value",在这种情况下,仅会添加键。

如果值包含非 ASCII 字符,则可以pass以(CHARSET, LANGUAGE, VALUE)格式将值指定为三个 Tuples 来显式控制字符集和语言,其中CHARSET是一个字符串,用于命名用于对值进行编码的字符集,LANGUAGE通常可以是设置为None或空字符串(其他可能性请参见 RFC 2231),而VALUE是包含非 ASCII 代码点的字符串值。如果未传递三个 Tuples 并且该值包含非 ASCII 字符,则会使用utf-8CHARSETNoneLANGUAGE自动以 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 *匹配的消息中找到的第一个 Headers,保留 HeadersSequences 和原始 Headers 的字段名称大小写。如果找不到匹配的 Headers,请引发KeyError
  • get_content_type ( )

    • 返回消息的 Content Type,强制为小写形式* maintype/subtype 。如果消息中没有 Content-Type Headers,则返回get_default_type()返回的值。如果 Content-Type *Headers 无效,则返回text/plain

(根据 RFC 2045,消息始终具有默认类型,get_content_type()将始终返回值。 RFC 2045将消息的默认类型定义为* text/plain ,除非它出现在 multipart/digest 容器内,在这种情况下将是 message/rfc822 。如果 Content-Type Headers 具有无效的类型规范,则 RFC 2045要求默认类型为 text/plain *。)

  • get_content_maintype ( )

    • 返回消息的主要 Content Type。这是get_content_type()返回的字符串的* maintype *部分。
  • get_content_subtype ( )

    • 返回消息的子 Content Type。这是get_content_type()返回的字符串的* subtype *部分。
  • get_default_type ( )

    • 返回默认的 Content Type。大多数消息的默认 Content Type 为* text/plain ,但作为 multipart/digest 容器的子部分的消息除外。这些子部分的默认 Content Type 为 message/rfc822 *。
  • set_default_type(* ctype *)

    • 设置默认的 Content Type。 * ctype 应该是 text/plain message/rfc822 ,尽管这不是强制性的。默认 Content Type 未存储在 Content-Type Headers 中,因此,仅当消息中没有 Content-Type *Headers 时,它才会影响get_content_type方法的返回值。
  • set_param((param value header ='Content-Type' requote = True charset = None language ='' replace = False *)

    • 在* Content-Type Headers 中设置一个参数。如果 Headers 中已经存在该参数,则将其值替换为 value 。当 header Content-Type(默认值)并且邮件中尚不存在标题时,添加它,将其值设置为 text/plain ,并附加新的参数值。可选的 header 指定 Content-Type *的替代标题。

如果该值包含非 ASCII 字符,则可以使用可选的* charset language 参数明确指定字符集和语言。可选的 language 指定 RFC 2231语言,默认为空字符串。 * charset language 都应为字符串。默认值是utf8 字符集None作为语言

如果* replace False(默认值),则标题将移动到标题列表的末尾。如果 replace *为True,则标题将被适当更新。

不建议对EmailMessage个对象使用* requote *参数。

注意,可以pass Headers 值的params属性(例如msg['Content-Type'].params['charset'])访问 Headers 的现有参数值。

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

  • del_param(* param header ='content-type' requote = True *)
    • 从* Content-Type Headers 中完全删除给定的参数。Headers 将在没有参数或其值的情况下被重写。可选的 header 指定 Content-Type *的替代形式。

不建议对EmailMessage个对象使用* requote *参数。

  • get_filename(* failobj = None *)

    • 返回消息的* Content-Disposition Headers 的filename参数的值。如果标题没有filename参数,则此方法将退回到在 Content-Type 标题上寻找name参数。如果两者均未找到,或者标题丢失,则返回 failobj *。返回的字符串将始终按照email.utils.unquote()取消引用。
  • get_boundary(* failobj = None *)

    • 返回消息的* Content-Type Headers 的boundary参数的值;如果 Headers 丢失或没有boundary参数,则返回 failobj *。返回的字符串将始终按照email.utils.unquote()取消引用。
  • set_boundary(* boundary *)

    • 将* Content-Type Headers 的boundary参数设置为 boundary 。如有必要,set_boundary()将始终引用 boundary 。如果消息对象没有 Content-Type *Headers,则引发HeaderParseError

请注意,使用此方法与passadd_header()删除旧的* Content-Type Headers 并添加具有新边界的新方法有一点不同,因为set_boundary()保留了 Content-Type *Headers 在 Headers 列表中的 Sequences。

  • get_content_charset(* failobj = None *)

    • 返回* Content-Type Headers 的charset参数(强制小写)。如果没有 Content-Type 头,或者该头没有charset参数,则返回 failobj *。
  • get_charsets(* failobj = None *)

    • 返回包含消息中字符集名称的列表。如果消息是* multipart *,则列表将为有效负载中的每个子部分包含一个元素,否则,它将为长度为 1 的列表。

列表中的每个项目都是一个字符串,它是表示子部分的* Content-Type 标题中charset参数的值。如果子部分没有 Content-Type 头,没有charset参数或者不是 text 主 MIME 类型,则返回列表中的该项将是 failobj *。

  • is_attachment ( )
    • 如果存在* Content-Disposition *Headers 且其(不区分大小写)值为attachment,则返回True,否则返回False

在版本 3.4.2 中更改:为了与is_multipart()保持一致,is_attachment 现在是方法而不是属性。

  • get_content_disposition ( )
    • 返回消息的* Content-Disposition Headers 的小写值(不带参数)(如果有的话)或None。如果消息遵循 RFC 2183,则此方法的可能值为 inline attachment *或None

3.5 版中的新Function。

以下方法与查询和处理消息的内容(有效负载)有关。

  • walk ( )
    • walk()方法是一种通用生成器,可用于按深度优先的遍历 Sequences 遍历消息对象树的所有部分和子部分。通常,您将在for循环中使用walk()作为迭代器;每次迭代都会返回下一个子部分。

这是一个打印 Multipart 消息结构的每个部分的 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。我们可以pass使用_structure debug helper 函数在示例中看到这一点:

>>> 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()返回Truewalk下降到子部分。

  • get_body(* preferencelist =('related''html''plain')*)
    • 返回最适合作为邮件“正文”的 MIME 部分。
  • preferencelist *必须是一组来自relatedhtmlplain的字符串序列,并指示对返回的 Component 的 Content Type 的偏好 Sequences。

开始寻找与调用get_body方法的对象匹配的候选对象。

如果related没有包含在* preferencelist *中,则如果(子)部分与首选项匹配,则将遇到的任何相关的根部分(或根部分的子部分)视为候选对象。

遇到multipart/related时,请检查start参数,并且如果找到具有匹配的* Content-ID *的 Component,则在查找候选匹配项时仅考虑它。否则,仅考虑multipart/related的第一部分(默认根)。

如果 Component 具有* Content-Disposition *Headers,则仅当 Headers 的值为inline时,才将该 Component 视为候选匹配项。

如果没有候选人符合* preferencelist *中的任何偏好,则返回None

注意:(1)对于大多数应用程序,唯一 true 有意义的* preferencelist 组合是('plain',)('html', 'plain')和默认的('related', 'html', 'plain')。 (2)因为匹配从调用get_body的对象开始,所以在multipart/related上调用get_body将返回对象本身,除非 preferencelist 具有非默认值。 (3)未指定 Content-Type Content-Type *Headers 无效的消息(或消息部分)将被视为text/plain类型,这有时会导致get_body返回意外结果。

  • iter_attachments ( )

    • 在消息的所有直接子部分(不是候选“正文”部分)上返回迭代器。也就是说,跳过text/plaintext/htmlmultipart/relatedmultipart/alternative中的每一个的第一次出现(除非它们pass* Content-Disposition:attachment 显式标记为附件),然后返回所有其余部分。直接应用于multipart/related时,在除根部分(即start参数指向的部分,如果没有start参数或start参数不匹配的第一部分)之外的所有相关部分上返回迭代器任何部分的 Content-ID *)。直接应用于multipart/alternative或非multipart时,返回一个空的迭代器。
  • iter_parts ( )

    • 在消息的所有直接子部分上返回一个迭代器,对于非multipart,它将为空。 (另请参见walk()。)
  • get_content((args content_manager = None ** kw *)

    • 调用* content_manager get_content()方法,将 self 作为消息对象传递,并将其他任何参数或关键字作为附加参数传递。如果未指定 content_manager *,请使用当前policy指定的content_manager
  • set_content((args content_manager = None ** kw *)

    • 调用* content_manager set_content()方法,将 self 作为消息对象传递,并将其他任何参数或关键字作为附加参数传递。如果未指定 content_manager *,请使用当前policy指定的content_manager
  • make_related(* boundary = None *)

    • 将非multipart消息转换为multipart/related消息,将任何现有* Content- Headers 和有效负载移动到multipart的(新)第一部分。如果指定了 boundary *,则将其用作 Multipart 中的边界字符串,否则在需要时(例如,在序列化消息时)保留要自动创建的边界。
  • make_alternative(* boundary = None *)

    • 将非multipartmultipart/related转换为multipart/alternative,将任何现有* Content- Headers 和有效负载移动到multipart的(新)第一部分。如果指定了 boundary *,则将其用作 Multipart 中的边界字符串,否则在需要时(例如,在序列化消息时)保留要自动创建的边界。
  • make_mixed(* boundary = None *)

    • 将非multipartmultipart/relatedmultipart-alternative转换为multipart/mixed,将任何现有* Content- Headers 和有效负载移动到multipart的(新)第一部分。如果指定了 boundary *,则将其用作 Multipart 中的边界字符串,否则在需要时(例如,在序列化消息时)保留要自动创建的边界。
  • add_related((args content_manager = None ** kw *)

    • 如果消息是multipart/related,则创建一个新的消息对象,将所有参数传递给其set_content()方法,然后将attach()传递给multipart。如果消息不是multipart,请致电make_related(),然后按照上述步骤进行。如果消息是其他任何类型的multipart,请举起TypeError。如果未指定* content_manager ,请使用当前policy指定的content_manager。如果添加的部分没有 Content-Disposition *Headers,则添加一个值为inline的 Headers。
  • add_alternative((args content_manager = None ** kw *)

    • 如果消息是multipart/alternative,则创建一个新的消息对象,将所有参数传递给其set_content()方法,然后将attach()传递给multipart。如果消息不是multipartmultipart/related,请致电make_alternative(),然后按照上述步骤进行操作。如果消息是multipart的任何其他类型,请举起TypeError。如果未指定* content_manager *,请使用当前policy指定的content_manager
  • add_attachment((args content_manager = None ** kw *)

    • 如果消息是multipart/mixed,请创建一个新的消息对象,将所有参数传递给其set_content()方法,然后将attach()传递给multipart。如果消息不是multipartmultipart/relatedmultipart/alternative,请致电make_mixed(),然后按上述步骤 continue。如果未指定* content_manager ,请使用当前policy指定的content_manager。如果添加的部分没有 Content-Disposition Headers,则添加一个值为attachment的 Headers。pass将适当的选项传递给content_manager,此方法可用于显式附件( Content-Disposition:attachment )和inline附件( Content-Disposition:inline *)。
  • clear ( )

    • 删除有效负载和所有 Headers。
  • clear_content ( )

    • 删除有效负载和所有Content-Headers,并保留所有其他 Headers 并保持其原始 Sequences。

EmailMessage个对象具有以下实例属性:

  • preamble
    • MIME 文档的格式允许在标题后的空白行和第一个 Multipart 边界字符串之间添加一些文本。通常,此文本在支持 MIME 的邮件阅读器中永远不可见,因为它不在标准 MIME 防护范围内。但是,在查看邮件的原始文本时,或在不支持 MIME 的阅读器中查看邮件时,此文本可能会变得可见。
  • preamble 属性包含 MIME 文档的前导多余的装甲文本。当Parser在标题之后但在第一个边界字符串之前发现一些文本时,它将将此文本分配给消息的 preamble 属性。当Generator写出 MIME 消息的纯文本表示形式时,如果发现该消息具有 preamble *属性,它将在 Headers 和第一个边界之间的区域中写入此文本。有关详细信息,请参见email.parseremail.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 Headers,因为子部分不需要它们自己的 MIME-Version *Headers。

Footnotes