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)

message 替换与 key 对应的消息。如果邮箱中没有消息与 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-到-message 映射或一个 (key, message) 对的可迭代对象。更新邮箱,以便对于每个给定的 keymessage,将与 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)

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

如果 createTruedirname 路径存在,则它将被视为现有 maildir,而无需尝试验证其目录布局。

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

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

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

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

colon

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

import mailbox
mailbox.Maildir.colon = '!'

colon 属性也可以按实例设置。

3.13 版中已更改: Maildir 现在忽略带有前导点的文件。

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

list_folders()

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

get_folder(folder)

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

add_folder(folder)

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

remove_folder(folder)

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

clean()

删除邮箱中过去 36 小时内未访问过的临时文件。Maildir 规范规定邮件读取程序应偶尔执行此操作。

get_flags(key)

以字符串形式返回与 key 对应的消息上设置的标志。这与 get_message(key).get_flags() 相同,但速度快得多,因为它不打开消息文件。在迭代键以确定哪些消息值得获取时使用此方法。

如果您确实有一个 MaildirMessage 对象,请改用其 get_flags() 方法,因为在调用邮箱的 __setitem__() 方法之前,消息的 set_flags()add_flag()remove_flag() 方法所做的更改不会反映在此处。

在 3.13 版本加入。

set_flags(key, flags)

在与 key 对应的消息上,设置 flags 指定的标志并取消设置所有其他标志。调用 some_mailbox.set_flags(key, flags) 类似于

one_message = some_mailbox.get_message(key)
one_message.set_flags(flags)
some_mailbox[key] = one_message

但速度更快,因为它不打开消息文件。

如果您确实有一个 MaildirMessage 对象,请改用其 set_flags() 方法,因为使用此邮箱方法所做的更改不会对消息对象的 get_flags() 方法可见。

在 3.13 版本加入。

add_flag(key, flag)

在与 key 对应的消息上,设置 flag 指定的标志而不更改其他标志。要一次添加多个标志,flag 可以是包含多个字符的字符串。

使用此方法与消息对象的 add_flag() 方法的考虑因素与 set_flags() 类似;请参见那里的讨论。

在 3.13 版本加入。

remove_flag(key, flag)

在与 key 对应的消息上,取消设置 flag 指定的标志而不更改其他标志。要一次删除多个标志,flag 可以是包含多个字符的字符串。

使用此方法与消息对象的 remove_flag() 方法的考虑因素与 set_flags() 类似;请参见那里的讨论。

在 3.13 版本加入。

get_info(key)

返回一个字符串,其中包含与 key 对应的消息的信息。这与 get_message(key).get_info() 相同,但速度快得多,因为它不打开消息文件。在迭代键以确定哪些消息值得获取时使用此方法。

如果您确实有一个 MaildirMessage 对象,请改用其 get_info() 方法,因为在调用邮箱的 __setitem__() 方法之前,消息的 set_info() 方法所做的更改不会反映在此处。

在 3.13 版本加入。

set_info(key, info)

将与 key 对应的消息的信息设置为 info。调用 some_mailbox.set_info(key, flags) 类似于

one_message = some_mailbox.get_message(key)
one_message.set_info(info)
some_mailbox[key] = one_message

但速度更快,因为它不打开消息文件。

如果您确实有一个 MaildirMessage 对象,请改用其 set_info() 方法,因为使用此邮箱方法所做的更改不会对消息对象的 get_info() 方法可见。

在 3.13 版本加入。

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)

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

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

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

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

get_bytes(key, from_=False)

注意:与其他类相比,此方法有一个额外的参数(from_)。mbox 文件条目的第一行是 Unix 的“From ”行。如果 from_ 为 False,则文件中的第一行将被丢弃。

get_file(key, from_=False)

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

注意:与其他类相比,此方法有一个额外的参数(from_)。mbox 文件条目的第一行是 Unix 的“From ”行。如果 from_ 为 False,则文件中的第一行将被丢弃。

get_string(key, from_=False)

注意:与其他类相比,此方法有一个额外的参数(from_)。mbox 文件条目的第一行是 Unix 的“From ”行。如果 from_ 为 False,则文件中的第一行将被丢弃。

lock()
unlock()

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

参见

来自 tin 的 mbox 手册页

格式规范,包含锁定细节。

在 Unix 上配置 Netscape Mail:为什么 Content-Length 格式很糟糕

主张使用原始 mbox 格式而不是变体。

“mbox”是几种互不兼容的邮箱格式族

mbox 变体历史。

MH 对象

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

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

MH 是一种基于目录的邮箱格式,是为 MH Message Handling System(一种邮件用户代理)发明的。MH 邮箱中的每条消息都位于自己的文件中。MH 邮箱除了消息外,还可以包含其他 MH 邮箱(称为 文件夹)。文件夹可以无限嵌套。MH 邮箱还支持 序列,它们是用于逻辑分组消息而不将其移动到子文件夹的命名列表。序列在每个文件夹中名为 .mh_sequences 的文件中定义。

MH 类操作 MH 邮箱,但它不试图模拟 mh 的所有行为。特别是,它不修改也不受 mh 用于存储其状态和配置的 context.mh_profile 文件影响。

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

3.13 版中已更改: 支持不包含 .mh_sequences 文件的文件夹。

list_folders()

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

get_folder(folder)

返回一个 MH 实例,表示名称为 folder 的文件夹。如果文件夹不存在,则引发 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 是一个可调用对象,它接受一个类文件消息表示(其行为就像以二进制模式打开一样)并返回一个自定义表示。如果 factoryNone,则 BabylMessage 用作默认消息表示。如果 createTrue,则如果邮箱不存在,则创建邮箱。

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。因此,这个文件式对象独立于底层邮箱,但与字符串表示相比,它不节省内存。

lock()
unlock()

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

参见

版本5 Babyl 文件的格式

Babyl 格式的规范。

使用 Rmail 阅读邮件

Rmail 手册,包含一些关于 Babyl 语义的信息。

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_bytes(key, from_=False)

注意:与其他类相比,此方法有一个额外的参数(from_)。mbox 文件条目的第一行是 Unix 的“From ”行。如果 from_ 为 False,则文件中的第一行将被丢弃。

get_file(key, from_=False)

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

注意:与其他类相比,此方法有一个额外的参数(from_)。mbox 文件条目的第一行是 Unix 的“From ”行。如果 from_ 为 False,则文件中的第一行将被丢弃。

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 邮件的标准标志如下:

Flag

含义

说明

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 邮件的传统标志如下:

Flag

含义

说明

R

已读

已读

O

旧的

先前由 MUA 检测到

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 ”行,并发生以下转换:

结果状态

MaildirMessage 状态

R 标志

S 标志

O 标志

“cur”子目录

D 标志

T 标志

F 标志

F 标志

A 标志

R 标志

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

结果状态

MHMessage 状态

R 标志和 O 标志

无“unseen”序列

O 标志

“unseen”序列

F 标志

“flagged”序列

A 标志

“replied”序列

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

结果状态

BabylMessage 状态

R 标志和 O 标志

无“unseen”标签

O 标志

“unseen”标签

D 标志

“deleted”标签

A 标志

“answered”标签

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

结果状态

MMDFMessage 状态

R 标志

R 标志

O 标志

O 标志

D 标志

D 标志

F 标志

F 标志

A 标志

A 标志

MHMessage 对象

class mailbox.MHMessage(message=None)

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

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

序列

说明

未读

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

已回复

已回复

已标记

标记为重要

MHMessage 实例提供以下方法

get_sequences()

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

set_sequences(sequences)

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

add_sequence(sequence)

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

remove_sequence(sequence)

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

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

结果状态

MaildirMessage 状态

“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 特定行为的消息。参数 message 的含义与 Message 构造函数相同。

某些消息标签,称为 属性,根据约定具有特殊含义。这些属性如下:

标签

说明

未读

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

已删除

标记为后续删除

已归档

已复制到其他文件或邮箱

已回复

已回复

已转发

已转发

已编辑

已由用户修改

已重发

已重发

默认情况下,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 状态

“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 特定行为的消息。参数 message 的含义与 Message 构造函数相同。

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

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

Flag

含义

说明

R

已读

已读

O

旧的

先前由 MUA 检测到

D

已删除

标记为后续删除

F

已标记

标记为重要

A

已回复

已回复

“R”和“O”标志存储在 Status 标头中,“D”、“F”和“A”标志存储在 X-Status 标头中。这些标志和标头通常按所提及的顺序出现。

MMDFMessage 实例提供以下方法,这些方法与 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 实例创建 MMDFMessage 实例时,会根据 MaildirMessage 实例的投递日期生成“From ”行,并发生以下转换:

结果状态

MaildirMessage 状态

R 标志

S 标志

O 标志

“cur”子目录

D 标志

T 标志

F 标志

F 标志

A 标志

R 标志

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

结果状态

MHMessage 状态

R 标志和 O 标志

无“unseen”序列

O 标志

“unseen”序列

F 标志

“flagged”序列

A 标志

“replied”序列

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

结果状态

BabylMessage 状态

R 标志和 O 标志

无“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

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

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()