mailbox — 操作各种格式的邮箱

源代码: Lib/mailbox.py


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

参见

模块 email

表示和操作邮件。

Mailbox 对象

class mailbox.Mailbox

一个可以检查和修改的邮箱。

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

Mailbox 接口类似于字典,其中小的键对应于邮件。键由将使用它们的 Mailbox 实例发出,并且仅对该 Mailbox 实例有意义。即使修改了相应的邮件(例如,用另一封邮件替换它),键也会继续标识该邮件。

可以使用类似集合的方法 add() 将邮件添加到 Mailbox 实例中,并使用 del 语句或类似集合的方法 remove()discard() 将其删除。

Mailbox 接口语义在某些值得注意的方面与字典语义不同。每次请求邮件时,都会根据邮箱的当前状态生成一个新的表示形式(通常是 Message 实例)。类似地,当将邮件添加到 Mailbox 实例时,将复制提供的邮件表示形式的内容。在这两种情况下,Mailbox 实例都不会保留对邮件表示形式的引用。

默认的 Mailbox 迭代器 迭代邮件表示形式,而不是像默认的 字典 迭代器那样迭代键。此外,在迭代期间修改邮箱是安全且定义明确的。创建迭代器后添加到邮箱中的邮件将不会被迭代器看到。在迭代器产生邮件之前从邮箱中删除的邮件将被静默跳过,尽管如果随后删除了相应的邮件,则使用迭代器中的键可能会导致 KeyError 异常。

警告

修改可能同时被其他进程更改的邮箱时要非常小心。用于此类任务的最安全的邮箱格式是 Maildir;尽量避免使用单文件格式(例如 mbox)进行并发写入。如果您要修改邮箱,则 *必须* 在读取文件中的任何邮件或通过添加或删除邮件进行任何更改 *之前*,通过调用 lock()unlock() 方法对其进行锁定。未能锁定邮箱可能会导致邮件丢失或整个邮箱损坏。

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() 相同,只是返回的是 list 而不是 迭代器

itervalues()
__iter__()

返回一个遍历所有邮件表示形式的 迭代器。除非在初始化 Mailbox 实例时指定了自定义邮件工厂,否则邮件将表示为相应格式特定 Message 子类的实例。

注意

__iter__() 的行为与字典不同,字典迭代的是键。

values()

itervalues() 相同,只是返回的是 list 而不是 迭代器

iteritems()

返回一个遍历 (key, message) 对的 迭代器,其中 key 是键,message 是邮件表示形式。除非在初始化 Mailbox 实例时指定了自定义邮件工厂,否则邮件将表示为相应格式特定 Message 子类的实例。

items()

iteritems() 相同,只是返回的是成对的 list 而不是成对的 迭代器

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

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

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*。除非在初始化 Mailbox 实例时指定了自定义消息工厂,否则消息将表示为相应的格式特定 Message 子类的实例。

popitem()

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

update(arg)

参数 *arg* 应为 *key*-to-*message* 映射或 ( *key*, *message* ) 对的可迭代对象。更新邮箱,以便对于每个给定的 *key* 和 *message*,与 *key* 对应的消息都设置为 *message*,就像使用 __setitem__() 一样。与 __setitem__() 一样,每个 *key* 必须已经对应于邮箱中的一条消息,否则将引发 KeyError 异常,因此通常 *arg* 不应该是 Mailbox 实例。

注意

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

flush()

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

lock()

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

unlock()

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

close()

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

Maildir 对象

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

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

如果 createTruedirname 路径存在,则将其视为现有邮件目录,而不会尝试验证其目录布局。

由于历史原因,dirname 被命名为此名称而不是 path

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

Maildir 邮箱包含三个子目录,即:tmpnewcur。邮件会在 tmp 子目录中短暂创建,然后移动到 new 子目录以完成传递。邮件用户代理随后可以将邮件移动到 cur 子目录,并将有关邮件状态的信息存储在其文件名的特殊“信息”部分中。

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

colon

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)

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

参见

来自 Courier 的 maildir 联机帮助页

格式规范。描述了用于支持文件夹的常见扩展。

使用 maildir 格式

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

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() 系统调用。

参见

tin 的 mbox 联机帮助页

格式规范,包含有关锁定的详细信息。

在 Unix 上配置 Netscape Mail:为什么 Content-Length 格式不好

使用原始 mbox 格式而不是变体的理由。

“mbox”是几个互不兼容的邮箱格式的统称

mbox 变体的历史。

MH 对象

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

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

MH 是为 MH 邮件处理系统(一种邮件用户代理)发明的基于目录的邮箱格式。MH 邮箱中的每封邮件都驻留在自己的文件中。除了邮件之外,MH 邮箱还可以包含其他 MH 邮箱(称为 文件夹)。文件夹可以无限嵌套。MH 邮箱还支持 序列,这些序列是用于在不将邮件移动到子文件夹的情况下对其进行逻辑分组的命名列表。序列在每个文件夹中名为 .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(一个映射到键列表的名称字典,如 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 许可书籍,其中包含一些有关邮箱格式的信息。

Babyl 对象

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

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

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

Babyl 邮箱中的邮件有两组标头,原始标头和所谓的可见标头。可见标头通常是原始标头的子集,这些标头已被重新格式化或缩短以使其更具吸引力。Babyl 邮箱中的每条邮件还附带一个 标签 列表,或记录有关邮件的额外信息的短字符串,并且在 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 手册,其中包含一些有关 Babyl 语义的信息。

MMDF 对象

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

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

MMDF 是一种为多通道备忘录分发工具(一种邮件传输代理)发明的单文件邮箱格式。每条邮件的格式与 mbox 邮件相同,但在前后用包含四个 Control-A ('\001') 字符的行括起来。与 mbox 格式一样,每条邮件的开头由其前五个字符为“From ”的行表示,但在存储邮件时,“From ”的其他出现不会转换为“>From ”,因为额外的邮件分隔符行可以防止将此类出现误认为是后续邮件的开头。

MMDF 实现的一些 Mailbox 方法值得特别说明

get_file(key)

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

lock()
unlock()

使用了三种锁定机制:点锁定以及(如果可用)flock()lockf() 系统调用。

参见

tin 的 mmdf 联机帮助页

来自新闻阅读器 tin 的文档中有关 MMDF 格式的规范。

MMDF

一篇描述多通道备忘录分发工具的维基百科文章。

Message 对象

class mailbox.Message(message=None)

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

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

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

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

MaildirMessage 对象

class mailbox.MaildirMessage(message=None)

具有 Maildir 特定行为的消息。参数 message 的含义与 Message 构造函数相同。

通常,邮件用户代理应用程序会在用户第一次打开和关闭邮箱后,将 new 子目录中的所有邮件移动到 cur 子目录中,并记录这些邮件是旧邮件,而不管它们是否已被实际读取。 cur 中的每封邮件在其文件名中都添加了一个“info”部分,用于存储有关其状态的信息。(某些邮件阅读器也可能会向 new 中的邮件添加“info”部分。)“info”部分可以采用以下两种形式之一:它可以包含“2”,后跟标准化标志列表(例如,“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 可以是包含多个字符的字符串。无论当前“info”是否包含实验性信息(而不是标志),都会被覆盖。

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” 子目录

“unseen” 序列

“cur” 子目录和 S 标志

无 “unseen” 序列

F 标志

“flagged” 序列

R 标志

“replied” 序列

当根据 BabylMessage 实例创建 MaildirMessage 实例时,会进行以下转换

结果状态

BabylMessage 状态

“cur” 子目录

“unseen” 标签

“cur” 子目录和 S 标志

无 “unseen” 标签

P 标志

“forwarded” 或 “resent” 标签

R 标志

“answered” 标签

T 标志

“deleted” 标签

mboxMessage 对象

class mailbox.mboxMessage(message=None)

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

mbox 邮箱中的消息存储在一个文件中。发件人的信封地址和递送时间通常存储在以“From”开头的行中,该行用于指示消息的开头,尽管在不同的 mbox 实现中,此数据的格式存在很大差异。指示消息状态的标志(例如,消息是否已读或标记为重要)通常存储在 StatusX-Status 标头中。

mbox 消息的常规标志如下

标志

含义

说明

R

已阅读

已阅读

O

先前由 MUA 检测到

D

D

标记为随后删除

F

已标记

标记为重要

已删除

A

已回复

已回复

“R”和“O”标志存储在 Status 标头中,“D”、“F”和“A”标志存储在 X-Status 标头中。标志和标头通常按上述顺序出现。

mboxMessage 实例提供以下方法

get_from()

返回一个字符串,表示在 mbox 邮箱中标记消息开头的“From”行。不包括前导“From”和尾随换行符。

set_from(from_, time_=None)

将“From”行设置为 from_,应在不带前导“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”行,并进行以下转换

R 标志

S 标志

O 标志

“cur” 子目录

D 标志

T 标志

F 标志

F 标志

A 标志

R 标志

MaildirMessage 状态

结果状态

MHMessage 状态

当根据 MHMessage 实例创建 mboxMessage 实例时,会进行以下转换

无 “unseen” 序列

O 标志

“unseen” 序列

F 标志

“flagged” 序列

A 标志

“replied” 序列

R 标志和 O 标志

结果状态

BabylMessage 状态

当根据 MHMessage 实例创建 mboxMessage 实例时,会进行以下转换

无 “unseen” 标签

O 标志

“unseen” 标签

D 标志

“deleted” 标签

A 标志

“answered” 标签

当根据 BabylMessage 实例创建 mboxMessage 实例时,会进行以下转换

结果状态

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

R 标志

R 标志

O 标志

O 标志

D 标志

D 标志

F 标志

F 标志

A 标志

A 标志

MMDFMessage 状态

class mailbox.MHMessage(message=None)

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

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

序列

说明

unseen

未读,但先前已被 MUA 检测到

replied

已回复

flagged

标记为重要

MHMessage 实例提供以下方法

get_sequences()

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

set_sequences(sequences)

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

add_sequence(sequence)

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

remove_sequence(sequence)

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

当基于 MaildirMessage 实例创建 MHMessage 实例时,将进行以下转换

结果状态

当根据 MaildirMessage 实例创建 mboxMessage 实例时,将根据 MaildirMessage 实例的递送日期生成“From”行,并进行以下转换

“unseen” 序列

无 S 标志

“replied” 序列

R 标志

“flagged” 序列

F 标志

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

结果状态

mboxMessageMMDFMessage 状态

“unseen” 序列

无 R 标志

“replied” 序列

A 标志

“flagged” 序列

F 标志

当基于 BabylMessage 实例创建 MHMessage 实例时,将进行以下转换

结果状态

BabylMessage 状态

“unseen” 序列

“unseen” 标签

“replied” 序列

“answered” 标签

BabylMessage 对象

class mailbox.BabylMessage(message=None)

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

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

标签

说明

unseen

未读,但先前已被 MUA 检测到

deleted

标记为随后删除

filed

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

answered

已回复

forwarded

已转发

edited

用户修改

resent

已转发

默认情况下,Rmail 仅显示可见的标头。但是,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-ToToCCSubject 添加到可见标头中。

当基于 MaildirMessage 实例创建 BabylMessage 实例时,将进行以下转换

结果状态

当根据 MaildirMessage 实例创建 mboxMessage 实例时,将根据 MaildirMessage 实例的递送日期生成“From”行,并进行以下转换

“unseen” 标签

无 S 标志

“deleted” 标签

T 标志

“answered” 标签

R 标志

“forwarded” 标签

P 标志

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

结果状态

mboxMessageMMDFMessage 状态

“unseen” 标签

无 R 标志

“deleted” 标签

D 标志

“answered” 标签

A 标志

当基于 MHMessage 实例创建 BabylMessage 实例时,将进行以下转换

结果状态

MHMessage 状态

“unseen” 标签

“unseen” 序列

“answered” 标签

“replied” 序列

MMDFMessage 对象

class mailbox.MMDFMessage(message=None)

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

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

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

标志

含义

说明

R

已阅读

已阅读

O

先前由 MUA 检测到

D

D

标记为随后删除

F

已标记

标记为重要

已删除

A

已回复

已回复

MMDFMessage 实例提供以下方法,这些方法与 mboxMessage 提供的方法相同

get_from()

get_from()

set_from(from_, time_=None)

set_from(from_, time_=None)

get_flags()

get_flags()

set_flags(flags)

set_flags(flags)

add_flag(flag)

add_flag(flag)

remove_flag(flag)

remove_flag(flag)

当根据 MaildirMessage 实例创建 MMDFMessage 实例时,将根据 MaildirMessage 实例的发送日期生成“From”行,并进行以下转换

结果状态

当根据 MaildirMessage 实例创建 mboxMessage 实例时,将根据 MaildirMessage 实例的递送日期生成“From”行,并进行以下转换

R 标志

S 标志

O 标志

“cur” 子目录

D 标志

T 标志

F 标志

F 标志

A 标志

R 标志

当根据 MHMessage 实例创建 MMDFMessage 实例时,将进行以下转换

结果状态

MHMessage 状态

当根据 MHMessage 实例创建 mboxMessage 实例时,会进行以下转换

无 “unseen” 序列

O 标志

“unseen” 序列

F 标志

“flagged” 序列

A 标志

“replied” 序列

当根据 BabylMessage 实例创建 MMDFMessage 实例时,将进行以下转换

结果状态

BabylMessage 状态

当根据 MHMessage 实例创建 mboxMessage 实例时,会进行以下转换

无 “unseen” 标签

O 标志

“unseen” 标签

D 标志

“deleted” 标签

A 标志

“answered” 标签

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

结果状态

mboxMessage 状态

R 标志

R 标志

O 标志

O 标志

D 标志

D 标志

F 标志

F 标志

A 标志

A 标志

异常

mailbox 模块中定义了以下异常类

exception mailbox.Error

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

exception mailbox.NoSuchMailboxError

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

exception mailbox.NotEmptyError

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

exception mailbox.ExternalClashError

当程序控制范围之外的某些邮箱相关条件导致程序无法继续时引发,例如当无法获取另一个程序已持有的锁时,或者当唯一生成的文件名已存在时引发。

exception mailbox.FormatError

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

示例

一个简单的示例,用于打印邮箱中所有看起来有趣的邮件的主题

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

将 Babyl 邮箱中的所有邮件复制到 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()