13.3.2 Maildir
创建Maildir格式是为了消除mbox文件并发修改存在的问题。这里不再使用单个文件,Maildir邮箱会被组织为一个目录,其中各个消息分别包含在自己单独的文件中。这种机制还允许邮箱嵌套,所以可以扩展Maildir邮箱的API,增加了一些方法来处理子文件夹。
13.3.2.1 创建Maildir邮箱
创建Maildir和创建mbox很类似,唯一的区别是Maildir构造函数的参数是一个目录名而不是文件名。与前面一样,如果邮箱不存在,那么会在具体增加消息时创建邮箱。
import mailbox
import email.utils
import os
from_addr = email.utils.formataddr(('Author','author@example.com'))
to_addr = email.utils.formataddr(('Recipient','recipient@example.com'))
payload = '''This is the body.
From (will not be escaped).
There are 3 lines.
'''
mbox = mailbox.Maildir('Example')
mbox.lock()
try:
msg = mailbox.mboxMessage()
msg.set_unixfrom('author Sat Feb 7 01:05:34 2019')
msg['From'] = from_addr
msg['To'] = to_addr
msg['Subject'] = 'Sample message 1'
msg.set_payload(payload)
mbox.add(msg)
mbox.flush()
msg = mailbox.mboxMessage()
msg.set_unixfrom('author Sat Feb 7 01:05:34 2019')
msg['From'] = from_addr
msg['To'] = to_addr
msg['Subject'] = 'Sample message 2'
msg.set_payload('THis is the second body.\n')
mbox.add(msg)
mbox.flush()
finally:
mbox.unlock()
for dirname,subdirs,files in os.walk('Example'):
print(dirname)
print(' Directories:',subdirs)
for name in files:
fullname = os.path.join(dirname,name)
print('\n***',fullname)
print(open(fullname).read())
print('*' * 20)
消息增加到邮箱时,它们会放在mew子目录中。
尽管从多个进程写同一个Maildir是安全的,但add()不是线程安全的。需要使用信号量或其他锁定机制,避免同一个进程的多个线程同时修改邮箱。
读取之后,客户可能使用MaildirMessage的set_subdir()方法把消息移动到cur子目录。
import mailbox
import os
print('Before:')
mbox = mailbox.Maildir('Example')
mbox.lock()
try:
for message_id,message in mbox.iteritems():
print('{:6} "{}"'.format(message.get_subdir(),
message['subject']))
message.set_subdir('cur')
# Tell the mailbox to update the message.
mbox[message_id] = message
finally:
mbox.flush()
mbox.close()
print('\nAfter:')
mbox = mailbox.Maildir('Example')
for message in mbox:
print('{:6} "{}"'.format(message.get_subdir(),
message['subject']))
print()
for dirname,subdirs,files in os.walk('Example'):
print(dirname)
print(' Directories:',subdirs)
for name in files:
fullname = os.path.join(dirname,name)
print(fullname)
尽管Maildir包含一个tmp目录,但set_subdir()的合法参数只有cur和new。