19.4. mailbox - 处理各种格式的邮箱

源代码: Lib / mailbox.py

此模块定义了两个类,MailboxMessage,用于访问和操作磁盘邮箱及其包含的邮件。Mailbox提供从键到邮件的类似字典的映射。Message extends the email.message module’s Message class with format-specific state and behavior. 支持的邮箱格式有Maildir,mbox,MH,Babyl和MMDF。

也可以看看

模块email
表示和操作消息。

19.4.1. Mailbox objects

class mailbox.Mailbox

邮箱,可以检查和修改。

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

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

可以使用set-like方法add()将邮件添加到Mailbox实例中,并使用del语句或类似set方法remove()discard()

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

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

警告

在修改可能由其他进程同时更改的邮箱时,请务必谨慎。用于这些任务的最安全的邮箱格式是Maildir;尽量避免使用单文件格式(如mbox)进行并发写入。If you’re modifying a mailbox, you must lock it by calling the lock() and unlock() methods before reading any messages in the file or making any changes by adding or deleting a message. 未能锁定邮箱运行丢失邮件或破坏整个邮箱的风险。

Mailbox实例具有以下方法:

add(message)

消息添加到邮箱,并返回已分配给它的键。

Parameter message may be a Message instance, an email.message.Message instance, a string, a byte string, or a file-like object (which should be open in binary mode). 如果消息是相应格式特定Message子类的实例(例如,如果它是mboxMessage实例,并且这是mbox实例),使用其格式特定信息。否则,使用格式特定信息的合理默认值。

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

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

从邮箱中删除对应的邮件。

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

__setitem__(key, message)

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

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

iterkeys()
keys()

如果调用iterkeys()则返回所有键的迭代器;如果调用keys(),则返回键列表。

itervalues()
__iter__()
values()

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

注意

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

iteritems()
items()

返回迭代器(消息),其中是键,消息 ,如果调用iteritems()或返回此类对的列表,如果调用items()消息被表示为适当的格式特定Message子类的实例,除非在Mailbox实例初始化时指定了自定义消息工厂。

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

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

get_message(key)

对应的消息的表示形式返回为适当的格式特定Message子类的实例,或引发KeyError异常消息存在。

get_bytes(key)

返回与对应的消息的字节表示,或如果不存在此类消息,则引发KeyError

版本3.2中的新功能。

get_string(key)

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

get_file(key)

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

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

注意

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

__contains__(key)

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

__len__()

返回邮箱中的邮件数。

clear()

删除邮箱中的所有邮件。

pop(key, default=None)

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

popitem()

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

update(arg)

参数arg应为 -to- 消息映射或迭代的()对。更新邮箱,以便对于每个给定的消息,与相对应的消息设置为消息如同使用__setitem__()__setitem__()一样,每个必须已经对应于邮箱中的消息,否则将引发KeyError异常, argMailbox实例是不正确的。

注意

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

flush()

将任何挂起的更改写入文件系统。对于某些Mailbox子类,更改总是立即写入,而且flush()什么都不做,但是您仍然应该习惯调用此方法。

lock()

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

unlock()

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

close()

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

19.4.1.1. Maildir

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

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

出于历史原因,dirname以此命名,而不是路径

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

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

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

注意

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

import mailbox
mailbox.Maildir.colon = '!'

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

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

list_folders()

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

get_folder(folder)

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

add_folder(folder)

创建名称为文件夹的文件夹,并返回代表该文件夹的Maildir实例。

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

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

也可以看看

来自qmail的maildir手册页
格式的原始规范。
使用maildir格式
它的发明人对Maildir的注释。包括更新的名称创建方案和“信息”语义的详细信息。
来自Courier的maildir手册页
另一个格式规范。描述支持文件夹的公共扩展。

19.4.1.2. mbox

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

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

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

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

mbox实现的一些Mailbox方法值得特别注释:

get_file(key)

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

lock()
unlock()

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

也可以看看

来自qmail的mbox手册页
格式及其变体的规范。
mbox man page from tin
另一个规范的格式,有锁定的详细信息。
在Unix上配置Netscape Mail:为什么Content-Length格式不正确
使用原始mbox格式而不是变体的参数。
“mbox”是几个互不兼容的邮箱格式的家庭
mbox变体的历史。

19.4.1.3. MH

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

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

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

MH类操作MH邮箱,但它不会尝试模拟所有mh的行为。特别地,它不修改并且不受由mh使用以存储其状态和配置的context.mh_profile文件的影响。

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

list_folders()

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

get_folder(folder)

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

add_folder(folder)

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

remove_folder(folder)

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

get_sequences()

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

set_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:Email for Users&程序员
mhnmh上获得GPL许可的书籍,以及邮箱格式的一些信息。

19.4.1.4. Babyl

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

用于Babyl格式的邮箱的Mailbox的子类。参数factory是一个可调用对象,它接受类似文件的消息表示(其行为好像以二进制模式打开)并返回自定义表示。如果工厂NoneBabylMessage用作默认消息表示。如果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邮箱中,邮件的标题不与邮件正文连续存储。为了生成类文件表示,标题和主体被一起复制到一个具有与文件相同的API的io.BytesIO实例中。因此,类文件对象真正独立于底层邮箱,但与字符串表示形式相比并不节省内存。

lock()
unlock()

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

也可以看看

版本5 Babyl文件的格式
Babyl格式的规范。
使用Rmail阅读邮件
Rmail手册,有一些关于Babyl语义的信息。

19.4.1.5. MMDF

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

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

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

MMDF实施的某些Mailbox方法值得特别注释:

get_file(key)

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

lock()
unlock()

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

也可以看看

mmdf来自tin的手册页
来自锡文档的MMDF格式规范,新闻阅读器。
MMDF
维基百科文章描述多渠道备忘录分发设施。

19.4.2. Message objects

class mailbox.Message(message=None)

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

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

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

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

19.4.2.1. MaildirMessage

class mailbox.MaildirMessage(message=None)

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

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

含义说明
D草案组成下
F已标记标记为重要
P通过转发,重新发送或退回
R回答已回复
S看到
T已删除标记为后续删除

MaildirMessage实例提供以下方法:

get_subdir()

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

注意

在邮件被访问后,无论该邮件是否已被读取,邮件通常都会从new移至cur如果“S” msg.get_flags() t2时读取了msg >为True

set_subdir(subdir)

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

get_flags()

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

set_flags(flags)

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

add_flag(flag)

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

remove_flag(flag)

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

get_date()

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

set_date(date)

将邮件的递送日期设置为日期,表示自纪元以来的秒数的浮点数。

get_info()

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

set_info(info)

将“info”设置为info,其应为字符串。

当基于mboxMessageMMDFMessage实例创建MaildirMessage实例时,状态状态标头,并进行以下转换:

结果状态mboxMessageMMDFMessage状态
“cur”子目录O标志
F标志F标志
R标志一个标志
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特定行为的消息。参数消息Message构造函数的含义相同。

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

mbox消息的常规标志如下:

含义说明
R
O以前由MUA检测
D已删除标记为后续删除
F已标记标记为重要
一个回答已回复

The “R” and “O” flags are stored in the Status header, and the “D”, “F”, and “A” flags are stored in the X-Status header. 标志和标题通常按所提及的顺序显示。

mboxMessage实例提供以下方法:

get_from()

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

set_from(from_, time_=None)

将“From”行设置为从_,应该在没有前导“From”或尾随换行符的情况下指定。为方便起见,可以指定时间_,并将格式适当地格式化,并从_附加到If time_ is specified, it should be a time.struct_time instance, a tuple suitable for passing to time.strftime(), or True (to use time.gmtime()).

get_flags()

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

set_flags(flags)

设置标志指定的标志,并取消所有其他标志。参数标志应当是'R''O''D''F''A'

add_flag(flag)

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

remove_flag(flag)

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

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

结果状态MaildirMessage状态
R标志S标志
O标志“cur”子目录
D标志T标志
F标志F标志
一个标志R标志

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

结果状态MHMessage状态
R标志和O标志没有“未见”序列
O标志“未见”序列
F标志“标记”序列
一个标志“回复”序列

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

结果状态BabylMessage状态
R标志和O标志没有“未见”标签
O标志“unseen”标签
D标志“已删除”标签
一个标志“已回答”标签

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

结果状态MMDFMessage状态
R标志R标志
O标志O标志
D标志D标志
F标志F标志
一个标志一个标志

19.4.2.3. MHMessage

class mailbox.MHMessage(message=None)

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

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

序列说明
看不见未读,但以前由MUA检测
回答已回复
标记标记为重要

MHMessage实例提供以下方法:

get_sequences()

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

set_sequences(sequences)

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

add_sequence(sequence)

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

remove_sequence(sequence)

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

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

结果状态MaildirMessage状态
“未见”序列无S标志
“回复”序列R标志
“标记”序列F标志

当基于mboxMessageMMDFMessage实例创建MHMessage实例时,状态状态标头,并进行以下转换:

结果状态mboxMessageMMDFMessage状态
“未见”序列无R标志
“回复”序列一个标志
“标记”序列F标志

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

结果状态BabylMessage状态
“未见”序列“unseen”标签
“回复”序列“已回答”标签

19.4.2.4. BabylMessage

class mailbox.BabylMessage(message=None)

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

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

标签说明
看不见未读,但以前由MUA检测
删除标记为后续删除
提交已复制到另一个文件或邮箱
回答已回复
转发转发
编辑由用户修改
怨恨怨恨

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

BabylMessage实例提供以下方法:

get_labels()

返回消息上的标签列表。

set_labels(labels)

将邮件上的标签列表设置为标签

add_label(label)

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

remove_label(label)

从邮件上的标签列表中删除标签

get_visible()

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

set_visible(visible)

将邮件的可见标头设置为与邮件中的标头相同。Parameter visible should be a Message instance, an email.message.Message instance, a string, or a file-like object (which should be open in text mode).

update_visible()

BabylMessage实例的原始标题被修改时,可见的标题不会自动修改为对应。此方法更新可见标头,如下:将具有相应原始标头的每个可见标头设置为原始标头的值,删除没有相应原始标头的每个可见标头,并且Date 自出现的回覆至CC主题在原始标头,但不是可见的标头添加到可见标头。

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

结果状态MaildirMessage状态
“unseen”标签无S标志
“已删除”标签T标志
“已回答”标签R标志
“转发”标签P标志

当基于mboxMessageMMDFMessage实例创建BabylMessage实例时,状态状态标头,并进行以下转换:

结果状态mboxMessageMMDFMessage状态
“unseen”标签无R标志
“已删除”标签D标志
“已回答”标签一个标志

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

结果状态MHMessage状态
“unseen”标签“未见”序列
“已回答”标签“回复”序列

19.4.2.5. MMDFMessage

class mailbox.MMDFMessage(message=None)

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

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

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

含义说明
R
O以前由MUA检测
D已删除标记为后续删除
F已标记标记为重要
一个回答已回复

The “R” and “O” flags are stored in the Status header, and the “D”, “F”, and “A” flags are stored in the X-Status header. 标志和标题通常按所提及的顺序显示。

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

get_from()

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

set_from(from_, time_=None)

将“From”行设置为从_,应该在没有前导“From”或尾随换行符的情况下指定。为方便起见,可以指定时间_,并将格式适当地格式化,并从_附加到If time_ is specified, it should be a time.struct_time instance, a tuple suitable for passing to time.strftime(), or True (to use time.gmtime()).

get_flags()

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

set_flags(flags)

设置由标志指定的标志,并取消所有其他标志。参数标志应当是'R''O''D''F''A'

add_flag(flag)

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

remove_flag(flag)

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

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

结果状态MaildirMessage状态
R标志S标志
O标志“cur”子目录
D标志T标志
F标志F标志
一个标志R标志

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

结果状态MHMessage状态
R标志和O标志没有“未见”序列
O标志“未见”序列
F标志“标记”序列
一个标志“回复”序列

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

结果状态BabylMessage状态
R标志和O标志没有“未见”标签
O标志“unseen”标签
D标志“已删除”标签
一个标志“已回答”标签

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

结果状态mboxMessage状态
R标志R标志
O标志O标志
D标志D标志
F标志F标志
一个标志一个标志

19.4.3. Exceptions

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

exception mailbox.Error

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

exception mailbox.NoSuchMailboxError

Raised when a mailbox is expected but is not found, such as when instantiating a Mailbox subclass with a path that does not exist (and with the create parameter set to False), or when opening a folder that does not exist.

exception mailbox.NotEmptyError

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

exception mailbox.ExternalClashError

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

exception mailbox.FormatError

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

19.4.4. Examples

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

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