Skip to main content

19.4. mailbox —以各种格式处理邮箱

源代码: Lib/mailbox.py


此模块定义了两个类,MailboxMessage,用于访问和操作磁盘邮箱及其包含的消息。 Mailbox 提供从键到消息的类似字典的映射。 Message 使用格式特定的状态和行为扩展了 email.message 模块的 Message 类。支持的邮箱格式有Maildir,mbox,MH,Babyl和MMDF。

参见

模块 email

表示和操作消息。

19.4.1. Mailbox 对象

class mailbox.Mailbox

邮箱,可以检查和修改。

Mailbox 类定义了一个接口,并且不打算被实例化。相反,格式特定的子类应该继承 Mailbox,你的代码应该实例化一个特定的子类。

Mailbox 接口是类似字典的,具有对应于消息的小键。密钥由它们将被使用的 Mailbox 实例发布,并且仅对该 Mailbox 实例有意义。即使相应的消息被修改,例如通过用另一消息替换它,密钥仍继续识别消息。

可以使用集合类方法 add() 将消息添加到 Mailbox 实例,并使用 del 语句或类集合方法 remove()discard() 来删除消息。

Mailbox 接口语义不同于字典语义在一些值得注意的方式。每次请求消息时,基于邮箱的当前状态生成新的表示(通常为 Message 实例)。类似地,当消息被添加到 Mailbox 实例时,复制所提供的消息表示的内容。在这两种情况下都不是对 Mailbox 实例保存的消息表示的引用。

默认的 Mailbox 迭代器迭代消息表示,而不是默认字典迭代器。此外,在迭代期间修改邮箱是安全和明确的。迭代器创建后添加到邮箱的消息不会被迭代器看到。在迭代器生成它们之前从邮箱中删除的邮件将被静默地跳过,但是如果相应的消息随后被删除,则从迭代器使用密钥可能导致 KeyError 异常。

警告

在修改可能由其他进程同时更改的邮箱时,请务必谨慎。用于这些任务的最安全的邮箱格式是Maildir;尽量避免使用单文件格式(如mbox)进行并发写入。如果您正在修改邮箱,您 must 通过调用 lock()unlock() 方法锁定邮箱,before 读取该文件中的任何邮件或通过添加或删除邮件进行任何更改。未能锁定邮箱运行丢失邮件或破坏整个邮箱的风险。

Mailbox 实例有以下方法:

add(message)

message 添加到邮箱,并返回已分配给它的密钥。

参数 message 可以是 Message 实例,email.message.Message 实例,字符串,字节字符串或类文件对象(应以二进制模式打开)。如果 message 是适当的格式特定的 Message 子类的实例(例如,如果它是 mboxMessage 实例并且这是 mbox 实例),则使用其格式特定的信息。否则,使用格式特定信息的合理默认值。

在 3.2 版更改: 增加了对二进制输入的支持。

remove(key)
__delitem__(key)
discard(key)

从邮箱中删除与 key 对应的消息。

如果不存在这样的消息,则如果方法被调用为 remove()__delitem__(),则引发 KeyError 异常,但是如果该方法被称为 discard(),则不引发异常。如果底层邮箱格式支持其他进程的并发修改,则 discard() 的行为可能是优选的。

__setitem__(key, message)

将对应于 key 的消息替换为 message。如果没有消息已对应于 key,则引发 KeyError 异常。

add() 一样,参数 message 可以是 Message 实例,email.message.Message 实例,字符串,字节字符串或类文件对象(应以二进制模式打开)。如果 message 是适当的格式特定的 Message 子类的实例(例如,如果它是 mboxMessage 实例并且这是 mbox 实例),则使用其格式特定的信息。否则,当前对应于 key 的消息的格式特定信息保持不变。

iterkeys()
keys()

如果被称为 iterkeys(),则返回所有键上的迭代器,或者如果被称为 keys(),则返回键列表。

itervalues()
__iter__()
values()

如果被称为 itervalues()__iter__(),则返回对所有消息的表示的迭代器,或者如果被称为 values() 则返回这样的表示的列表。消息表示为适当的格式特定 Message 子类的实例,除非在初始化 Mailbox 实例时指定了自定义消息工厂。

注解

__iter__() 的行为不同于在键上迭代的字典的行为。

iteritems()
items()

通过(keymessage)对返回迭代器,其中 key 是密钥,message 是消息表示,如果被称为 iteritems(),或者返回这样的对的列表,如果被称为 items()。消息被表示为适当的格式特定 Message 子类的实例,除非在初始化 Mailbox 实例时指定了自定义消息工厂。

get(key, default=None)
__getitem__(key)

返回与 key 对应的消息的表示。如果不存在这样的消息,则如果方法被调用为 get() 则返回 default,并且如果该方法被调用为 __getitem__(),则引发 KeyError 异常。该消息表示为适当的格式特定的 Message 子类的实例,除非在 Mailbox 实例被初始化时指定了自定义消息工厂。

get_message(key)

返回对应于 key 的消息的表示作为适当的格式特定 Message 子类的实例,或者如果不存在这样的消息则引发 KeyError 异常。

get_bytes(key)

返回与 key 对应的消息的字节表示,或者如果不存在此类消息,则抛出 KeyError 异常。

3.2 新版功能.

get_string(key)

返回与 key 对应的消息的字符串表示,或者如果不存在此类消息,则抛出 KeyError 异常。该消息通过 email.message.Message 处理,以将其转换为7位清除表示。

get_file(key)

返回对应于 key 的消息的类文件表示,或者如果不存在这样的消息则引发 KeyError 异常。类似文件的对象的行为就像在二进制模式下打开一样。此文件在不再需要时应关闭。

在 3.2 版更改: 文件对象真的是一个二进制文件;以前它在文本模式下不正确返回。此外,类文件对象现在支持上下文管理协议:您可以使用 with 语句自动关闭它。

注解

与消息的其他表示不同,类文件表示不一定独立于创建它们的 Mailbox 实例或底层邮箱。每个子类提供更具体的文档。

__contains__(key)

如果 key 对应于消息,则返回 True,否则返回 False

__len__()

返回邮箱中的邮件数。

clear()

删除邮箱中的所有邮件。

pop(key, default=None)

返回与 key 对应的消息的表示,并删除该消息。如果不存在这样的消息,则返回 default。该消息表示为适当的特定于格式的 Message 子类的实例,除非在初始化 Mailbox 实例时指定了自定义消息工厂。

popitem()

返回任意(keymessage)对,其中 key 是关键字,message 是消息表示,并删除相应的消息。如果邮箱为空,则引发 KeyError 异常。该消息表示为适当的格式特定的 Message 子类的实例,除非在 Mailbox 实例被初始化时指定了自定义消息工厂。

update(arg)

参数 arg 应该是 keymessage 映射或(keymessage)对的可迭代。更新邮箱,使得对于每个给定的 keymessage,与 key 相对应的消息被设置为 message,如同通过使用 __setitem__()。与 __setitem__() 一样,每个 key 必须已经对应于邮箱中的消息,否则将引发 KeyError 异常,因此通常 arg 不是 Mailbox 实例是不正确的。

注解

与字典不同,不支持关键字参数。

flush()

将任何挂起的更改写入文件系统。对于一些 Mailbox 子类,更改总是立即写入,flush() 不执行任何操作,但是您仍然应该习惯调用此方法。

lock()

获取邮箱的独占咨询锁,以便其他进程知道不要修改它。如果锁不可用,则引发 ExternalClashError。所使用的特定锁定机制取决于邮箱格式。您应该 always 锁定邮箱,然后对其内容进行任何修改。

unlock()

释放邮箱上的锁(如果有)。

close()

刷新邮箱,如有必要,解锁它,然后关闭所有打开的文件。对于一些 Mailbox 子类,此方法不执行任何操作。

19.4.1.1. Maildir

class mailbox.Maildir(dirname, factory=None, create=True)

MailDir格式的邮箱的 Mailbox 子类。参数 factory 是一个可调用对象,它接受类似文件的消息表示(其行为好像以二进制模式打开)并返回自定义表示。如果 factoryNone,则 MaildirMessage 用作默认消息表示。如果 createTrue,则如果邮箱不存在,则创建邮箱。

出于历史原因,dirname 被这样命名而不是 path

Maildir是为qmail邮件传输代理发明的基于目录的邮箱格式,现在被其他程序广泛支持。 Maildir邮箱中的邮件存储在公共目录结构中的单独文件中。此设计允许Maildir邮箱被多个不相关的程序访问和修改,而不会损坏数据,因此不需要文件锁定。

Maildir邮箱包含三个子目录,即:tmpnewcur。消息在 tmp 子目录中瞬间创建,然后移动到 new 子目录以完成交付。邮件用户代理可以随后将消息移动到 cur 子目录并且将关于消息的状态的信息存储在附加到其文件名的特殊“信息”部分中。

还支持由Courier邮件传输代理引入的样式的文件夹。如果 '.' 是其名称中的第一个字符,则主邮箱的任何子目录都将被视为文件夹。文件夹名称由 Maildir 表示,不带前导 '.'。每个文件夹本身是一个Maildir邮箱,但不应包含其他文件夹。相反,使用 '.' 来指示逻辑嵌套以定界层次,例如“Archived.2005.07”。

注解

Maildir规范要求在某些消息文件名中使用冒号(':')。但是,某些操作系统不允许在文件名中使用此字符。如果您希望在此类操作系统上使用类似Maildir的格式,则应指定要使用的另一个字符。惊叹号('!')是一个受欢迎的选择。例如:

import mailbox
mailbox.Maildir.colon = '!'

还可以基于每个实例来设置 colon 属性。

除了以下内容之外,Maildir 实例还具有 Mailbox 的所有方法:

list_folders()

返回所有文件夹的名称列表。

get_folder(folder)

返回表示名称为 folder 的文件夹的 Maildir 实例。如果文件夹不存在,则会引发 NoSuchMailboxError 异常。

add_folder(folder)

创建一个名称为 folder 的文件夹,并返回一个代表它的 Maildir 实例。

remove_folder(folder)

删除名称为 folder 的文件夹。如果文件夹包含任何消息,则会引发 NotEmptyError 异常,并且不会删除该文件夹。

clean()

删除邮箱中在最近36小时内未访问的临时文件。 Maildir规范说邮件阅读程序应该偶尔这样做。

Maildir 实施的一些 Mailbox 方法值得特别注意:

add(message)
__setitem__(key, message)
update(arg)

警告

这些方法基于当前进程ID生成唯一的文件名。当使用多个线程时,可能会发生未检测到的名称冲突,并且会导致邮箱损坏,除非协调线程,以避免使用这些方法同时处理同一个邮箱。

flush()

将立即应用对Maildir邮箱的所有更改,因此此方法不执行任何操作。

lock()
unlock()

Maildir邮箱不支持(或需要)锁定,因此这些方法什么都不做。

close()

Maildir 实例不保留任何打开的文件,并且底层邮箱不支持锁定,因此此方法不执行任何操作。

get_file(key)

根据主机平台,可能无法在返回的文件保持打开时修改或删除底层消息。

参见

maildir从qmail的手册页

格式的原始规范。

使用maildir格式

发明人对Maildir的注释。包括更新的名称创建方案和有关“信息”语义的详细信息。

maildir从快递的人页

另一个格式规范。描述支持文件夹的公共扩展。

19.4.1.2. mbox

class mailbox.mbox(path, factory=None, create=True)

mbox格式的邮箱的 Mailbox 子类。参数 factory 是一个可调用对象,它接受类似文件的消息表示(其行为好像以二进制模式打开)并返回自定义表示。如果 factoryNone,则 mboxMessage 用作默认消息表示。如果 createTrue,则如果邮箱不存在,则创建邮箱。

mbox格式是用于在Unix系统上存储邮件的经典格式。 mbox邮箱中的所有邮件都存储在一个文件中,每个邮件的开头由前五个字符为“From”的行指示。

mbox格式的几种变体存在以解决原始的感知缺点。为了兼容性,mbox 实现原始格式,其有时被称为 mboxo。这意味着 Content-Length 头(如果存在)被忽略,并且在存储消息时,消息正文中的行开头处的“From”的任何出现都会转换为“> From”,但“> From”的出现是在读取消息时不会转换为“From”。

mbox 实施的一些 Mailbox 方法值得特别注意:

get_file(key)

mbox 实例上调用 flush()close() 之后使用该文件可能会产生不可预测的结果或引发异常。

lock()
unlock()

使用三种锁定机制—点锁定和 flock()lockf() 系统调用(如果可用)。

参见

从qmail的mbox手册页

格式及其变体的规范。

mbox从锡的人页

另一个规范的格式,有锁定的详细信息。

在Unix上配置Netscape Mail:为什么Content-Length格式是错误的

使用原始mbox格式而不是变体的参数。

“mbox”是几个互不兼容的邮箱格式的家庭

mbox变体的历史。

19.4.1.3. MH

class mailbox.MH(path, factory=None, create=True)

MH格式的邮箱的 Mailbox 子类。参数 factory 是一个可调用对象,它接受类似文件的消息表示(其行为好像以二进制模式打开)并返回自定义表示。如果 factoryNone,则 MHMessage 用作默认消息表示。如果 createTrue,则如果邮箱不存在,则创建邮箱。

MH是为MH消息处理系统发明的基于目录的邮箱格式,邮件用户代理。 MH邮箱中的每个消息都驻留在自己的文件中。除了消息之外,MH邮箱还可以包含其他MH邮箱(称为 folders)。文件夹可以无限嵌套。 MH邮箱还支持 sequences,这些名称列表用于逻辑分组邮件,而不将邮件移动到子文件夹。序列在每个文件夹中名为 .mh_sequences 的文件中定义。

MH 类操纵MH邮箱,但它不试图模仿所有 mh 的行为。特别地,它不修改并且不受 mh 用来存储其状态和配置的 context.mh_profile 文件的影响。

除了以下内容之外,MH 实例还具有 Mailbox 的所有方法:

list_folders()

返回所有文件夹的名称列表。

get_folder(folder)

返回表示名称为 folder 的文件夹的 MH 实例。如果文件夹不存在,则会引发 NoSuchMailboxError 异常。

add_folder(folder)

创建一个名称为 folder 的文件夹,并返回一个代表它的 MH 实例。

remove_folder(folder)

删除名称为 folder 的文件夹。如果文件夹包含任何消息,则会引发 NotEmptyError 异常,并且不会删除该文件夹。

get_sequences()

返回映射到键列表的序列名称字典。如果没有序列,则返回空字典。

set_sequences(sequences)

根据 sequences 重新定义邮箱中存在的序列,sequences 是映射到键列表的名称的字典,如 get_sequences() 返回。

pack()

根据需要重命名邮箱中的邮件,以消除编号中的空白。序列列表中的条目将相应更新。

注解

已经发出的密钥由此操作无效,不应随后使用。

MH 实施的一些 Mailbox 方法值得特别注意:

remove(key)
__delitem__(key)
discard(key)

这些方法立即删除消息。不使用通过在其名称前面添加逗号来标记邮件以进行删除的MH约定。

lock()
unlock()

使用三种锁定机制—点锁定和 flock()lockf() 系统调用(如果可用)。对于MH邮箱,锁定邮箱意味着锁定 .mh_sequences 文件,并且仅在影响它们的任何操作期间锁定单个邮件文件。

get_file(key)

根据主机平台,可能无法在返回的文件保持打开时删除基础消息。

flush()

将立即应用对MH邮箱的所有更改,因此此方法不执行任何操作。

close()

MH 实例不保留任何打开的文件,因此此方法等效于 unlock()

参见

nmh - 消息处理系统

nmh 的主页,原始 mh 的更新版本。

MH&nmh:用户和程序员的电子邮件

mhnmh 的GPL授权的书,有关邮箱格式的一些信息。

19.4.1.4. Babyl

class mailbox.Babyl(path, factory=None, create=True)

Babyl格式的邮箱的 Mailbox 子类。参数 factory 是一个可调用对象,它接受类似文件的消息表示(其行为好像以二进制模式打开)并返回自定义表示。如果 factoryNone,则 BabylMessage 用作默认消息表示。如果 createTrue,则如果邮箱不存在,则创建邮箱。

Babyl是Emacs附带的Rmail邮件用户代理使用的单文件邮箱格式。消息的开始由包含两个字符Control-Underscore('\037')和Control-L('\014')的行指示。消息的结束由下一个消息的开始指示,或者在最后一个消息的情况下由包含Control-Underscore('\037')字符的行指示。

Babyl邮箱中的邮件有两组标头,原始标头和所谓的可见标头。可见头部通常是原始头部的子集,已被重新格式化或缩短以使其更有吸引力。 Babyl邮箱中的每个邮件还有 labels 附带的列表,或记录有关邮件的额外信息的短字符串,并且在邮箱中找到的所有用户定义标签的列表保存在Babyl选项部分。

除了以下内容之外,Babyl 实例还具有 Mailbox 的所有方法:

get_labels()

返回邮箱中使用的所有用户定义标签的名称列表。

注解

将检查实际邮件以确定邮箱中存在哪些标签,而不是查阅Babyl选项部分中的标签列表,但是每当邮箱被修改时,Babyl段都会更新。

Babyl 实施的一些 Mailbox 方法值得特别注意:

get_file(key)

在Babyl邮箱中,邮件的标题不与邮件正文连续存储。为了生成类文件表示,将标题和主体一起复制到 io.BytesIO 实例中,该实例具有与文件的API相同的API。因此,类文件对象真正独立于底层邮箱,但与字符串表示相比并不节省内存。

lock()
unlock()

使用三种锁定机制—点锁定和 flock()lockf() 系统调用(如果可用)。

参见

版本5 Babyl文件的格式

Babyl格式的规范。

使用Rmail读取邮件

Rmail手册,有一些关于Baby语义的信息。

19.4.1.5. MMDF

class mailbox.MMDF(path, factory=None, create=True)

MMDF格式的邮箱的 Mailbox 子类。参数 factory 是一个可调用对象,它接受类似文件的消息表示(其行为好像以二进制模式打开)并返回自定义表示。如果 factoryNone,则 MMDFMessage 用作默认消息表示。如果 createTrue,则如果邮箱不存在,则创建邮箱。

MMDF是为多通道备忘录分发设施(邮件传输代理)发明的单文件邮箱格式。每个消息的格式与mbox消息的格式相同,但在包含四个Control-A('\001')字符的行之前和之后加上括号。与mbox格式一样,每个消息的开始由前五个字符为“From”的行指示,但是存储消息时附加的“From”出现不会转换为“> From”,因为额外的消息分隔符行将这样的事件误认为后续消息的开始。

MMDF 实施的一些 Mailbox 方法值得特别注意:

get_file(key)

MMDF 实例上调用 flush()close() 之后使用该文件可能会产生不可预测的结果或引发异常。

lock()
unlock()

使用三种锁定机制—点锁定和 flock()lockf() 系统调用(如果可用)。

参见

mmdf的手册页

来自锡文档的MMDF格式规范,新闻阅读器。

MMDF

维基百科文章描述多渠道备忘录分发设施。

19.4.2. Message 对象

class mailbox.Message(message=None)

email.message 模块的 Message 的子类。 mailbox.Message 的子类添加邮箱格式特定的状态和行为。

如果省略 message,则以默认的空状态创建新实例。如果 messageemail.message.Message 实例,则复制其内容;此外,如果 messageMessage 实例,则尽可能地转换任何格式特定信息。如果 message 是字符串,字节字符串或文件,它应该包含 RFC 2822 兼容消息,这是读取和解析。文件应以二进制模式打开,但文本模式文件被接受为向后兼容。

子类提供的特定于格式的状态和行为会有所不同,但通常只是不支持特定邮箱的属性(虽然这些属性特定于特定邮箱格式)。例如,不保留单文件邮箱格式的文件偏移和基于目录的邮箱格式的文件名,因为它们仅适用于原始邮箱。但是诸如消息是否已被用户读取或被标记为重要的状态被保留,因为它应用于消息本身。

没有要求 Message 实例用于表示使用 Mailbox 实例检索的消息。在某些情况下,生成 Message 表示所需的时间和内存可能是不可接受的。对于这种情况,Mailbox 实例还提供字符串和文件样表示,并且可以在初始化 Mailbox 实例时指定自定义消息工厂。

19.4.2.1. MaildirMessage

class mailbox.MaildirMessage(message=None)

具有Maildir特定行为的邮件。参数 messageMessage 构造函数具有相同的含义。

通常,邮件用户代理应用程序在用户第一次打开和关闭邮箱之后,将 new 子目录中的所有邮件移动到 cur 子目录,记录邮件是否是旧的,无论它们是否已被读取。 cur 中的每个消息都有一个“info”部分添加到其文件名中以存储有关其状态的信息。 (某些邮件阅读器也可以在 new 中的消息中添加“info”部分。)“info”部分可以采用两种形式之一:它可以包含“2”,后面是标准化标记列表(例如“ FR“)或它可以包含”1“,随后是所谓的实验信息。 Maildir消息的标准标志如下:

含义

说明

D

草案

组成下

F

已标记

标记为重要

P

通过

转发,重新发送或退回

R

回答

已回复

S

看到

T

已删除

标记为后续删除

MaildirMessage 实例提供以下方法:

get_subdir()

返回“new”(如果消息应存储在 new 子目录中)或“cur”(如果消息应存储在 cur 子目录中)。

注解

在访问邮箱之后,无论邮件是否已被读取,邮件通常都从 new 移到 cur。如果 "S" in msg.get_flags()True,则已读取消息 msg

set_subdir(subdir)

设置消息应存储的子目录。参数 subdir 必须是“new”或“cur”。

get_flags()

返回一个字符串,指定当前设置的标志。如果消息符合标准Maildir格式,则结果是 'D''F''P''R''S''T' 中的每一个的零或一次出现的字母顺序的级联。如果没有设置标志或者如果“info”包含实验语义,则返回空字符串。

set_flags(flags)

设置由 flags 指定的标志并取消所有其他标志。

add_flag(flag)

设置由 flag 指定的标志,而不更改其他标志。要一次添加多个标志,flag 可能是一个多个字符的字符串。无论是否包含实验信息而不是标志,当前的“信息”都会被覆盖。

remove_flag(flag)

取消设置由 flag 指定的标志,而不更改其他标志。要一次删除多个标志,flag 可能是一个多个字符的字符串。如果“info”包含实验信息而不是标志,则不修改当前的“info”。

get_date()

将消息的交货日期作为浮点数返回,表示自纪元以来的秒数。

set_date(date)

将消息的交货日期设置为 date,表示自纪元以来的秒数的浮点数。

get_info()

返回包含消息的“info”的字符串。这对于访问和修改实验性的“info”非常有用(即不是标志列表)。

set_info(info)

设置“info”到 info,它应该是一个字符串。

当基于 mboxMessageMMDFMessage 实例创建 MaildirMessage 实例时,省略 StatusX-Status 报头,并进行以下转换:

结果状态

mboxMessageMMDFMessage 状态

“cur”子目录

O标志

F标志

F标志

R标志

A标志

S标志

R标志

T标志

D标志

当基于 MHMessage 实例创建 MaildirMessage 实例时,将发生以下转换:

结果状态

MHMessage 状态

“cur”子目录

“未见”序列

“cur”子目录和S标志

没有“未见”序列

F标志

“标记”序列

R标志

“回复”序列

当基于 BabylMessage 实例创建 MaildirMessage 实例时,将发生以下转换:

结果状态

BabylMessage 状态

“cur”子目录

“unseen”标签

“cur”子目录和S标志

没有“未见”标签

P标志

“转发”或“重新发送”标签

R标志

“已回答”标签

T标志

“已删除”标签

19.4.2.2. mboxMessage

class mailbox.mboxMessage(message=None)

具有mbox特定行为的消息。参数 messageMessage 构造函数具有相同的含义。

mbox邮箱中的邮件一起存储在单个文件中。发送方的包络地址和递送时间通常存储在以“From”开头的行中,该行用于指示消息的开始,尽管在mbox实现中该数据的确切格式有相当大的变化。指示消息状态的标志,例如它是否已被读取或被标记为重要,通常存储在 StatusX-Status 报头中。

mbox消息的常规标志如下:

含义

说明

R

O

以前由MUA检测

D

已删除

标记为后续删除

F

已标记

标记为重要

一个

回答

已回复

“R”和“O”标志存储在 Status 标题中,“D”,“F”和“A”标志存储在 X-Status 标题中。标志和标题通常按所提及的顺序显示。

mboxMessage 实例提供以下方法:

get_from()

在mbox邮箱中返回表示标记邮件开头的“From”行的字符串。排除前导“From”和尾部换行符。

set_from(from_, time_=None)

将“发件人”行设置为 from_,应在没有前导“开始”或结束换行符的情况下指定。为了方便起见,可以指定 time_ 并将其格式化并附加到 from_。如果指定 time_,它应该是 time.struct_time 实例,适合传递到 time.strftime() 的元组或 True (使用 time.gmtime())。

get_flags()

返回一个字符串,指定当前设置的标志。如果消息符合常规格式,则结果是 'R''O''D''F''A' 中的每一个的零或一次出现的顺序的级联。

set_flags(flags)

设置由 flags 指定的标志并取消所有其他标志。参数 flags 应当是 'R''O''D''F''A' 中的每一个的零个或多个出现的任何顺序的级联。

add_flag(flag)

设置由 flag 指定的标志,而不更改其他标志。要一次添加多个标志,flag 可能是一个多个字符的字符串。

remove_flag(flag)

取消设置由 flag 指定的标志,而不更改其他标志。要一次删除多个标志,flag 可能是一个多个字符的字符串。

当基于 MaildirMessage 实例创建 mboxMessage 实例时,将基于 MaildirMessage 实例的交货日期生成“From”行,并进行以下转换:

结果状态

MaildirMessage 状态

R标志

S标志

O标志

“cur”子目录

D标志

T标志

F标志

F标志

A标志

R标志

当基于 MHMessage 实例创建 mboxMessage 实例时,将发生以下转换:

结果状态

MHMessage 状态

R标志和O标志

没有“未见”序列

O标志

“未见”序列

F标志

“标记”序列

A标志

“回复”序列

当基于 BabylMessage 实例创建 mboxMessage 实例时,将发生以下转换:

结果状态

BabylMessage 状态

R标志和O标志

没有“未见”标签

O标志

“unseen”标签

D标志

“已删除”标签

A标志

“已回答”标签

当基于 MMDFMessage 实例创建 Message 实例时,将复制“From”行,并且所有标志直接对应:

结果状态

MMDFMessage 状态

R标志

R标志

O标志

O标志

D标志

D标志

F标志

F标志

A标志

A标志

19.4.2.3. MHMessage

class mailbox.MHMessage(message=None)

具有MH特定行为的消息。参数 messageMessage 构造函数具有相同的含义。

MH消息不支持传统意义上的标记或标记,但是它们支持序列,其是任意消息的逻辑分组。一些邮件阅读程序(虽然不是标准的 mhnmh)以与其他格式使用标志的方式大致相同的方式使用序列,如下所示:

序列

说明

看不见

未读,但以前由MUA检测

回答

已回复

标记

标记为重要

MHMessage 实例提供以下方法:

get_sequences()

返回包含此消息的序列名称的列表。

set_sequences(sequences)

设置包含此消息的序列列表。

add_sequence(sequence)

sequence 添加到包含此消息的序列列表中。

remove_sequence(sequence)

从包含此消息的序列列表中删除 sequence

当基于 MaildirMessage 实例创建 MHMessage 实例时,将发生以下转换:

结果状态

MaildirMessage 状态

“未见”序列

无S标志

“回复”序列

R标志

“标记”序列

F标志

当基于 mboxMessageMMDFMessage 实例创建 MHMessage 实例时,省略 StatusX-Status 报头,并进行以下转换:

结果状态

mboxMessageMMDFMessage 状态

“未见”序列

无R标志

“回复”序列

A标志

“标记”序列

F标志

当基于 BabylMessage 实例创建 MHMessage 实例时,将发生以下转换:

结果状态

BabylMessage 状态

“未见”序列

“unseen”标签

“回复”序列

“已回答”标签

19.4.2.4. BabylMessage

class mailbox.BabylMessage(message=None)

带有婴儿特定行为的消息。参数 messageMessage 构造函数具有相同的含义。

某些消息标签(称为 attributes)按照惯例定义为具有特殊含义。属性如下:

标签

说明

看不见

未读,但以前由MUA检测

删除

标记为后续删除

提交

已复制到另一个文件或邮箱

回答

已回复

转发

转发

编辑

由用户修改

怨恨

怨恨

默认情况下,电子邮件只显示可见标题。然而,BabylMessage 类使用原始头,因为它们更完整。如果需要,可以明确地访问可见头部。

BabylMessage 实例提供以下方法:

get_labels()

返回消息上的标签列表。

set_labels(labels)

将消息上的标签列表设置为 labels

add_label(label)

label 添加到邮件上的标签列表中。

remove_label(label)

从消息上的标签列表中删除 label

get_visible()

返回一个 Message 实例,其头是消息的可见头,且其主体为空。

set_visible(visible)

将邮件的可见标头设置为与 message 中的标头相同。参数 visible 应该是 Message 实例,email.message.Message 实例,字符串或类文件对象(应在文本模式下打开)。

update_visible()

BabylMessage 实例的原始标题被修改时,可见的标题不会被自动修改为对应。该方法如下更新可见标题:将具有相应原始标题的每个可见标题设置为原始标题的值,删除没有相应原始标题的每个可见标题,并且 DateFromReply-ToToCC ,以及存在于原始报头中但不存在于可见报头中的 Subject 被添加到可见报头。

当基于 MaildirMessage 实例创建 BabylMessage 实例时,将发生以下转换:

结果状态

MaildirMessage 状态

“unseen”标签

无S标志

“已删除”标签

T标志

“已回答”标签

R标志

“转发”标签

P标志

当基于 mboxMessageMMDFMessage 实例创建 BabylMessage 实例时,省略 StatusX-Status 报头,并进行以下转换:

结果状态

mboxMessageMMDFMessage 状态

“unseen”标签

无R标志

“已删除”标签

D标志

“已回答”标签

A标志

当基于 MHMessage 实例创建 BabylMessage 实例时,将发生以下转换:

结果状态

MHMessage 状态

“unseen”标签

“未见”序列

“已回答”标签

“回复”序列

19.4.2.5. MMDFMessage

class mailbox.MMDFMessage(message=None)

具有MMDF特定行为的消息。参数 messageMessage 构造函数具有相同的含义。

与mbox邮箱中的邮件一样,MMDF邮件与发件人的地址和交货日期一起存储在以“From”开头的初始行中。同样,指示消息的状态的标志通常存储在 StatusX-Status 报头中。

MMDF消息的常规标志与mbox消息的标志相同,如下所示:

含义

说明

R

O

以前由MUA检测

D

已删除

标记为后续删除

F

已标记

标记为重要

一个

回答

已回复

“R”和“O”标志存储在 Status 标题中,“D”,“F”和“A”标志存储在 X-Status 标题中。标志和标题通常按所提及的顺序显示。

MMDFMessage 实例提供以下方法,它们与 mboxMessage 提供的方法相同:

get_from()

在mbox邮箱中返回表示标记邮件开头的“From”行的字符串。排除前导“From”和尾部换行符。

set_from(from_, time_=None)

将“发件人”行设置为 from_,应在没有前导“开始”或结束换行符的情况下指定。为了方便起见,可以指定 time_ 并将其格式化并附加到 from_。如果指定 time_,它应该是 time.struct_time 实例,适合传递到 time.strftime() 的元组或 True (使用 time.gmtime())。

get_flags()

返回一个字符串,指定当前设置的标志。如果消息符合常规格式,则结果是 'R''O''D''F''A' 中的每一个的零或一次出现的顺序的级联。

set_flags(flags)

设置由 flags 指定的标志并取消所有其他标志。参数 flags 应当是 'R''O''D''F''A' 中的每一个的零个或多个出现的任何顺序的级联。

add_flag(flag)

设置由 flag 指定的标志,而不更改其他标志。要一次添加多个标志,flag 可能是一个多个字符的字符串。

remove_flag(flag)

取消设置由 flag 指定的标志,而不更改其他标志。要一次删除多个标志,flag 可能是一个多个字符的字符串。

当基于 MaildirMessage 实例创建 MMDFMessage 实例时,将基于 MaildirMessage 实例的交货日期生成“From”行,并进行以下转换:

结果状态

MaildirMessage 状态

R标志

S标志

O标志

“cur”子目录

D标志

T标志

F标志

F标志

A标志

R标志

当基于 MHMessage 实例创建 MMDFMessage 实例时,将发生以下转换:

结果状态

MHMessage 状态

R标志和O标志

没有“未见”序列

O标志

“未见”序列

F标志

“标记”序列

A标志

“回复”序列

当基于 BabylMessage 实例创建 MMDFMessage 实例时,将发生以下转换:

结果状态

BabylMessage 状态

R标志和O标志

没有“未见”标签

O标志

“unseen”标签

D标志

“已删除”标签

A标志

“已回答”标签

当基于 mboxMessage 实例创建 MMDFMessage 实例时,将复制“From”行,并且所有标志直接对应:

结果状态

mboxMessage 状态

R标志

R标志

O标志

O标志

D标志

D标志

F标志

F标志

A标志

A标志

19.4.3. 例外

以下异常类在 mailbox 模块中定义:

exception mailbox.Error

基于类的所有其他模块特定异常。

exception mailbox.NoSuchMailboxError

在预期邮箱但未找到时引发,例如在实例化具有不存在(以及 create 参数设置为 False)的路径的 Mailbox 子类时,或打开不存在的文件夹时。

exception mailbox.NotEmptyError

在邮箱不为空但预期为空时引发,例如删除包含邮件的文件夹时引发。

exception mailbox.ExternalClashError

在某些超出程序控制的邮箱相关条件导致无法继续操作(例如,无法获取另一个程序已持有锁定的锁定)时,或当唯一生成的文件名称已存在时引发。

exception mailbox.FormatError

在无法解析文件中的数据时引发,例如当 MH 实例尝试读取损坏的 .mh_sequences 文件时。

19.4.4. 例子

一个简单的例子,打印邮件中的所有邮件的主题看起来很有趣:

import mailbox
for message in mailbox.mbox('~/mbox'):
    subject = message['subject']       # Could possibly be None.
    if subject and 'python' in subject.lower():
        print(subject)

要将所有邮件从Baby邮箱复制到MH邮箱,请转换可转换的所有格式特定信息:

import mailbox
destination = mailbox.MH('~/Mail')
destination.lock()
for message in mailbox.Babyl('~/RMAIL'):
    destination.add(mailbox.MHMessage(message))
destination.flush()
destination.unlock()

此示例将邮件从多个邮件列表分类到不同的邮箱,小心避免由于其他程序的并发修改导致的邮件损坏,由于程序中断而导致的邮件丢失或由于邮箱中的格式不正确的邮件而过早终止:

import mailbox
import email.errors

list_names = ('python-list', 'python-dev', 'python-bugs')

boxes = {name: mailbox.mbox('~/email/%s' % name) for name in list_names}
inbox = mailbox.Maildir('~/Maildir', factory=None)

for key in inbox.iterkeys():
    try:
        message = inbox[key]
    except email.errors.MessageParseError:
        continue                # The message is malformed. Just leave it.

    for name in list_names:
        list_id = message['list-id']
        if list_id and name in list_id:
            # Get mailbox to use
            box = boxes[name]

            # Write copy to disk before removing original.
            # If there's a crash, you might duplicate a message, but
            # that's better than losing a message completely.
            box.lock()
            box.add(message)
            box.flush()
            box.unlock()

            # Remove original message
            inbox.lock()
            inbox.discard(key)
            inbox.flush()
            inbox.unlock()
            break               # Found destination, so stop looking.

for box in boxes.itervalues():
    box.close()