18.4. mailbox — 様々な形式のメールボックス操作

このモジュールでは二つのクラス Mailbox および Message をディスク上のメールボックスとそこに収められたメッセージへのアクセスと操作のために定義しています。 Mailbox は辞書のようなキーからメッセージへの対応付けを提供しています。 Messageemail.message モジュールの Message を拡張して形式ごとの状態と振る舞いを追加しています。サポートされるメールボックスの形式は Maildir, mbox, MH, Babyl, MMDF です。

参考

email モジュール
メッセージの表現と操作。

18.4.1. Mailbox オブジェクト

class mailbox.Mailbox

メールボックス。内容を確認したり変更したりできます。

Mailbox 自体はインタフェースを定義し形式ごとのサブクラスに継承されるように意図されたもので、インスタンス化されることは想定されていません。インスタンス化したいならばサブクラスを代わりに使うべきです。

Mailbox のインタフェースは辞書風で、小さなキーがメッセージに対応します。キーは対象となる Mailbox インスタンスが発行するもので、そのインスタンスに対してのみ意味を持ちます。一つのキーは一つのメッセージにひも付けられ、その対応はメッセージが他のメッセージで置き換えられるような更新をされたあとも続きます。

メッセージを Mailbox インスタンスに追加するには集合風のメソッド add() を使います。また削除は del 文または集合風の remove()discard() を使って行ないます。

Mailbox インタフェースのセマンティクスと辞書のそれとは注意すべき違いがあります。メッセージは、要求されるたびに新しい表現(典型的には Message インスタンス)が現在のメールボックスの状態に基づいて生成されます。同様に、メッセージが Mailbox インスタンスに追加される時も、渡されたメッセージ表現の内容がコピーされます。どちらの場合も Mailbox インスタンスにメッセージ表現への参照は保たれません。

デフォルトの Mailbox イテレータはメッセージ表現ごとに繰り返すもので、辞書のイテレータのようにキーごとの繰り返しではありません。さらに、繰り返し中のメールボックスを変更することは安全であり整合的に定義されています。イテレータが作られた後にメールボックスに追加されたメッセージはそのイテレータからは見えません。そのイテレータが yield するまえにメールボックスから削除されたメッセージは黙ってスキップされますが、イテレータからのキーを使ったときにはそのキーに対応するメッセージが削除されているならば KeyError を受け取ることになります。

警告

十分な注意を、何か他のプロセスによっても同時に変更される可能性のあるメールボックスを更新する時は、払わなければなりません。そのようなタスクをこなすのに最も安全なメールボックス形式は Maildir で、 mbox のような単一ファイルの形式を並行した書き込みに利用するのは避けるように努力しましょう。メールボックスを更新する場面では、 必ず lock()unlock() メソッドを、ファイル内のメッセージを読んだり書き込んだり削除したりといった操作をする に、呼び出してロックします。メールボックスをロックし損なうと、メッセージを失ったりメールボックス全体をぐちゃぐちゃにしたりする羽目に陥ります。

Mailbox インスタンスには次のメソッドがあります:

add(message)

メールボックスに message を追加し、それに割り当てられたキーを返します。

引数 messageMessage インスタンス、 email.message.Message インスタンス、文字列、ファイル風オブジェクト (テキストモードで開かれていなければなりませんが)を使えます。 message が適切な形式に特化した Message サブクラスのインスタンス (例えばメールボックスが mbox インスタンスのときの mboxMessage インスタンス)であれば、形式ごとの情報が利用されます。そうでなければ、形式ごとに必要な情報は適当なデフォルトが使われます。

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 サブクラスのインスタンス (例えばメールボックスが mbox インスタンスのときの mboxMessage インスタンス)であれば、形式ごとの情報が利用されます。そうでなければ、現在 key に対応するメッセージの形式ごとの情報が変更されずに残ります。

iterkeys()
keys()

iterkeys() として呼び出されると全てのキーについてのイテレータを返しますが、 keys() として呼び出されるとキーのリストを返します。

itervalues()
__iter__()
values()

itervalues() または __iter__() として呼び出されると全てのメッセージの表現についてのイテレータを返しますが、 values() として呼び出されるとその表現のリストを返します。メッセージは適切な形式ごとの Message サブクラスのインスタンスとして表現されるのが普通ですが、 Mailbox インスタンスが初期化されるときに指定すればお好みのメッセージファクトリを使うこともできます。

注釈

__iter__() は辞書のそれのようにキーについてのイテレータではありません。

iteritems()
items()

(key, message) ペア、ただし 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_string(key)

key に対応するメッセージの文字列を返すか、そのようなメッセージが存在しない場合は KeyError 例外を送出します。

get_file(key)

key に対応するメッセージの表現をファイル風表現として返します。もし対応するメッセージが存在しなければ KeyError 例外が送出されます。ファイル風オブジェクトはバイナリモードで開かれているように振る舞います。このファイルは必要がなくなったら閉じなければなりません。

注釈

他の表現方法とは違い、ファイル風オブジェクトはそれを作り出した Mailbox インスタンスやそれが基づいているメールボックスと独立である必要がありません。より詳細な説明は各サブクラスごとにあります。

has_key(key)
__contains__(key)

key がメッセージに対応していれば True を、そうでなければ False を返します。

__len__()

メールボックス中のメッセージ数を返します。

clear()

メールボックスから全てのメッセージを削除します。

pop(key[, default])

key に対応するメッセージの表現を返し、そのメッセージを削除します。もし対応するメッセージが存在しなければ default が供給されていればその値を返し、そうでなければ KeyError 例外を送出します。メッセージは適切な形式ごとの Message サブクラスのインスタンスとして表現されるのが普通ですが、 Mailbox インスタンスが初期化されるときに指定すればお好みのメッセージファクトリを使うこともできます。

popitem()

任意に選んだ (key, message) ペアを返します。ただしここで key はキーで message はメッセージ表現です。もしメールボックスが空ならば、 KeyError 例外を送出します。メッセージは適切な形式ごとの Message サブクラスのインスタンスとして表現されるのが普通ですが、 Mailbox インスタンスが初期化されるときに指定すればお好みのメッセージファクトリを使うこともできます。

update(arg)

引数 argkey から message へのマッピングまたは (key, message) ペアのイテレート可能オブジェクトでなければなりません。メールボックスは、各 keymessage のペアについて __setitem__() を使ったかのように key に対応するメッセージが message になるように更新されます。 __setitem__() と同様に、 key は既存のメールボックス中のメッセージに対応しているものでなければならず、そうでなければ KeyError が送出されます。ですから、一般的には argMailbox インスタンスを渡すのは間違いです。

注釈

辞書と違い、キーワード引数はサポートされていません。

flush()

保留されている変更をファイルシステムに書き込みます。 Mailbox のサブクラスによっては変更はいつも直ちにファイルに書き込まれ flush() は何もしないということもありますが、それでもこのメソッドを呼ぶように習慣付けておきましょう。

lock()

メールボックスの排他的アドバイザリロックを取得し、他のプロセスが変更しないようにします。ロックが取得できない場合 ExternalClashError が送出されます。ロック機構はメールボックス形式によって変わります。メールボックスの内容に変更を加えるときは いつも ロックを掛けるべきです。

unlock()

メールボックスのロックが存在する場合は解放します。

close()

メールボックスをフラッシュし、必要ならばアンロックし、開いているファイルを閉じます。 Mailbox サブクラスによっては何もしないこともあります。

18.4.1.1. Maildir

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

Maildir 形式のメールボックスのための Mailbox のサブクラス。パラメータ factory は呼び出し可能オブジェクトで (バイナリモードで開かれているかのように振る舞う)ファイル風メッセージ表現を受け付けて好みの表現を返すものです。 factoryNone ならば、 MaildirMessage がデフォルトのメッセージ表現として使われます。 createTrue ならばメールボックスが存在しないときには作成します。

factory のデフォルトが rfc822.Message であったり、 path ではなく dirname という名前であったりというのは歴史的理由によるものです。 Maildir インスタンスが他の Mailbox サブクラスと同じように振る舞わせるためには、 factoryNone をセットしてください。

Maildir はディレクトリ型のメールボックス形式でメール転送エージェント qmail 用に発明され、現在では多くの他のプログラムでもサポートされているものです。Maildir メールボックス中のメッセージは共通のディレクトリ構造の下で個別のファイルに保存されます。このデザインにより、Maildir メールボックスは複数の無関係のプログラムからデータを失うことなくアクセスしたり変更したりできます。そのためロックは不要です。

Maildir メールボックスには三つのサブディレクトリ tmp, new, cur があります。メッセージはまず tmp サブディレクトリに瞬間的に作られた後、 new サブディレクトリに移動されて配送を完了します。メールユーザエージェントが引き続いて cur サブディレクトリにメッセージを移動しメッセージの状態についての情報をファイル名に追加される特別な "info" セクションに保存することができます。

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)

ホストのプラットフォームによっては、返されたファイルが開いている間、元になったメッセージを変更したり削除したりできない場合があります。

参考

qmail の maildir マニュアルページ
Maildir 形式のオリジナルの仕様。
Using maildir format
Maildir 形式の発明者による注意書き。更新された名前生成規則と "info" の解釈についても含まれます。
Courier の maildir マニュアルページ
Maildir 形式のもう一つの仕様。フォルダをサポートする一般的な拡張について記述されています。

18.4.1.2. mbox

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

mbox 形式のメールボックスのための Mailbox のサブクラス。パラメータ factory は呼び出し可能オブジェクトで (バイナリモードで開かれているかのように振る舞う)ファイル風メッセージ表現を受け付けて好みの表現を返すものです。 factoryNone ならば、 mboxMessage がデフォルトのメッセージ表現として使われます。 createTrue ならばメールボックスが存在しないときには作成します。

mbox 形式は Unixシステム上でメールを保存する古くからある形式です。mbox メールボックスでは全てのメッセージが一つのファイルに保存されておりそれぞれのメッセージは "From " という5文字で始まる行を先頭に付けられています。

mbox 形式には幾つかのバリエーションがあり、それぞれオリジナルの形式にあった欠点を克服すると主張しています。互換性のために、 mbox はオリジナルの(時に mboxo と呼ばれる) 形式を実装しています。すなわち、 Content-Length ヘッダはもしあっても無視され、メッセージのボディにある行頭の "From " はメッセージを保存する際に ">From " に変換されますが、この ">From " は読み出し時にも "From " に変換されません。

mbox で実装された Mailbox のいくつかのメソッドには特別な注意が必要です:

get_file(key)

mbox インスタンスに対し flush()close() を呼び出した後でファイルを使用すると予期しない結果を引き起こしたり例外が送出されたりすることがあります。

lock()
unlock()

3種類のロック機構が使われます — ドットロッキングと、もし使用可能ならば flock()lockf() システムコールです。

参考

qmail の mbox マニュアルページ
mbox 形式の仕様および種々のバリエーション。
tin の mbox マニュアルページ
もう一つの mbox 形式の仕様でロックについての詳細を含む。
Configuring Netscape Mail on Unix: Why The Content-Length Format is Bad
バリエーションの一つではなくオリジナルの mbox を使う理由。
"mbox" は相互に互換性を持たないいくつかのメールボックスフォーマットの集まりです
mbox バリエーションの歴史。

18.4.1.3. MH

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

MH 形式のメールボックスのための Mailbox のサブクラス。パラメータ factory は呼び出し可能オブジェクトで (バイナリモードで開かれているかのように振る舞う)ファイル風メッセージ表現を受け付けて好みの表現を返すものです。 factoryNone ならば、 MHMessage がデフォルトのメッセージ表現として使われます。 createTrue ならばメールボックスが存在しないときには作成します。

MH はディレクトリに基づいたメールボックス形式で MH Message Handling System というメールユーザエージェントのために発明されました。 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()

folder という名前のフォルダを削除します。フォルダにメッセージが一つでも残っていれば、NotEmptyError 例外が送出されフォルダは削除されません。

set_sequences(sequences)

シーケンス名をキーのリストに対応付ける辞書を返します。シーケンスが一つもなければ空の辞書を返します。

pack()

メールボックス中のシーケンスを get_sequences() で返されるような名前とキーのリストを対応付ける辞書 sequences に基づいて再定義します。

注釈

番号付けの間隔を詰める必要に応じてメールボックス中のメッセージの名前を付け替えます。シーケンスのリストのエントリもそれに応じて更新されます。

既に発行されたキーはこの操作によって無効になるのでそれ以降使ってはなりません:

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

これらのメソッドはメッセージを直ちに削除します。名前の前にコンマを付加してメッセージに削除の印を付けるという MH の規約は使いません。

lock()
unlock()

3種類のロック機構が使われます — ドットロッキングと、もし使用可能ならば flock()lockf() システムコールです。 MH メールボックスに対するロックとは .mh_sequences のロックと、それが影響を与える操作中だけの個々のメッセージファイルに対するロックを意味します。

get_file(key)

ホストプラットフォームにより、ファイルが開かれたままの場合はメッセージを削除することができない場合があります。

flush()

MH メールボックスへの変更は即時に適用されますのでこのメソッドは何もしません。

close()

MH インスタンスは開いたファイルを保持しませんのでこのメソッドは unlock() と同じです。

参考

nmh - Message Handling System
mh の改良版である nmh のホームページ。
MH & nmh: Email for Users & Programmers
GPLライセンスの mh および nmh の本で、このメールボックス形式についての情報があります。

18.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 を含む行で示されます。

Babyl メールボックス中のメッセージには二つのヘッダのセット、オリジナルヘッダといわゆる可視ヘッダ、があります。可視ヘッダは典型的にはオリジナルヘッダの一部を分り易いように再整形したり短くしたりしたものです。 Babyl メールボックス中のそれぞれのメッセージには ラベル というそのメッセージについての追加情報を記録する短い文字列のリストを伴い、メールボックス中に見出されるユーザが定義した全てのラベルのリストは Babyl オプションセクションに保持されます。

Babyl インスタンスには Mailbox の全てのメソッドの他に次のメソッドがあります:

get_labels()

メールボックスで使われているユーザが定義した全てのラベルのリストを返します。

注釈

メールボックスにどのようなラベルが存在するかを決めるのに、Babyl オプションセクションのリストを参考にせず、実際のメッセージを捜索しますが、Babyl セクションもメールボックスが変更されたときにはいつでも更新されます。

Babyl で実装された Mailbox のいくつかのメソッドには特別な注意が必要です:

get_file(key)

Babyl メールボックスにおいて、メッセージのヘッダはボディと繋がって格納されていません。ファイル風の表現を生成するために、ヘッダとボディが (StringIO モジュールの) ファイルと同じ API を持つ StringIO インスタンスに一緒にコピーされます。その結果、ファイル風オブジェクトは本当に元にしているメールボックスとは独立していますが、文字列表現と比べてメモリーを節約することにもなりません。

lock()
unlock()

3種類のロック機構が使われます — ドットロッキングと、もし使用可能ならば flock()lockf() システムコールです。

参考

Format of Version 5 Babyl Files
Babyl 形式の仕様。
Reading Mail with Rmail
Rmail のマニュアルで Babyl のセマンティクスについての情報も少しある。

18.4.1.5. MMDF

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

MMDF 形式のメールボックスのための Mailbox のサブクラス。パラメータ factory は呼び出し可能オブジェクトで (バイナリモードで開かれているかのように振る舞う)ファイル風メッセージ表現を受け付けて好みの表現を返すものです。 factoryNone ならば、 MMDFMessage がデフォルトのメッセージ表現として使われます。 createTrue ならばメールボックスが存在しないときには作成します。

MMDF は単一ファイルのメールボックス形式で Multichannel Memorandum Distribution Facility というメール転送エージェント用に発明されたものです。各メッセージは mbox と同様の形式で収められますが、前後を4つの Control-A ('\001') を含む行で挟んであります。mbox 形式と同じようにそれぞれのメッセージの開始は "From " の5文字を含む行で示されますが、それ以外の場所での "From " は格納の際 ">From " には変えられません。それは追加されたメッセージ区切りによって新たなメッセージの開始と見間違うことが避けられるからです。

MMDF で実装された Mailbox のいくつかのメソッドには特別な注意が必要です:

get_file(key)

MMDF インスタンスに対し flush()close() を呼び出した後でファイルを使用すると予期しない結果を引き起こしたり例外が送出されたりすることがあります。

lock()
unlock()

3種類のロック機構が使われます — ドットロッキングと、もし使用可能ならば flock()lockf() システムコールです。

参考

mmdf man page from tin
ニュースリーダ tin のドキュメント中の MMDF 形式仕様。
MMDF
Multichannel Memorandum Distribution Facility についてのウィキペディアの記事。

18.4.2. Message objects

class mailbox.Message([message])

email.Message モジュールの Message のサブクラス。 mailbox.Message のサブクラスはメールボックス形式ごとの状態と動作を追加します。

message が省略された場合、新しいインスタンスはデフォルトの空の状態で生成されます。 messageemail.message.Message インスタンスならばその内容がコピーされます。さらに、 messageMessage インスタンスならば、形式固有の情報も可能な限り変換されます。 message が文字列またはファイルならば、読まれ解析されるべき RFC 2822 準拠のメッセージを含んでいなければなりません。

サブクラスにより提供される形式ごとの状態と動作は様々ですが、一般に或るメールボックスに固有のものでないプロパティだけがサポートされます(おそらくプロパティのセットはメールボックス形式ごとに固有でしょうが)。例えば、単一ファイルメールボックス形式におけるファイルオフセットやディレクトリ式メールボックス形式におけるファイル名は保持されません、というのもそれらは元々のメールボックスにしか適用できないからです。しかし、メッセージがユーザに読まれたかどうかあるいは重要だとマークされたかどうかという状態は保持されます、というのはそれらはメッセージ自体に適用されるからです。

Mailbox インスタンスを使って取得したメッセージを表現するのに Message インスタンスが使われなければいけないとは要求していません。ある種の状況では Message による表現を生成するのに必要な時間やメモリーが受け入れられないこともあります。そういった状況では Mailbox インスタンスは文字列やファイル風オブジェクトの表現も提供できますし、 Mailbox インスタンスを初期化する際にメッセージファクトリーを指定することもできます。

18.4.2.1. MaildirMessage

class mailbox.MaildirMessage([message])

Maildir 固有の動作をするメッセージ。引数 messageMessage のコンストラクタと同じ意味を持ちます。

通常、メールユーザエージェントは new サブディレクトリにある全てのメッセージをユーザが最初にメールボックスを開くか閉じるかした後で cur サブディレクトリに移動し、メッセージが実際に読まれたかどうかを記録します。 cur にある各メッセージには状態情報を保存するファイル名に付け加えられた "info" セクションがあります。(メールリーダの中には "info" セクションを new にあるメッセージに付けることもあります。) "info" セクションには二つの形式があります。一つは "2," の後に標準化されたフラグのリストを付けたもの (たとえば "2,FR")、もう一つは "1," の後にいわゆる実験的情報を付け加えるものです。 Maildir の標準的なフラグは以下の通りです:

フラグ 意味 説明
D ドラフト(Draft) 作成中
F フラグ付き(Flagged) 重要とされたもの
P 通過(Passed) 転送、再送またはバウンス
R 返答済み(Replied) 返答されたもの
S 既読(Seen) 読んだもの
T ごみ(Trashed) 削除予定とされたもの

MaildirMessage インスタンスは以下のメソッドを提供します:

get_subdir()

"new" (メッセージが new サブディレクトリに保存されるべき場合) または "cur" (メッセージが cur サブディレクトリに保存されるべき場合)のどちらかを返します。

注釈

メッセージは通常メールボックスがアクセスされた後、メッセージが読まれたかどうかに関わらず new から cur に移動されます。メッセージ msg"S" in msg.get_flags()True ならば読まれています。

set_subdir(subdir)

メッセージが保存されるべきサブディレクトリをセットします。パラメータ subdir は "new" または "cur" のいずれかでなければなりません。

get_flags()

現在セットされているフラグを特定する文字列を返します。メッセージが標準 Maildir 形式に準拠しているならば、結果はアルファベット順に並べられたゼロまたは1回の 'D''F''P''R''S''T' をつなげたものです。空文字列が返されるのはフラグが一つもない場合、または "info" が実験的セマンティクスを使っている場合です。

set_flags(flags)

flags で指定されたフラグをセットし、他のフラグは下ろします。

add_flag(flag)

flag で指定されたフラグをセットしますが他のフラグは変えません。一度に二つ以上のフラグをセットすることは、flag に2文字以上の文字列を指定すればできます。現在の "info" はフラグの代わりに実験的情報を使っていても上書きされます。

remove_flag(flag)

flag で指定されたフラグを下ろしますが他のフラグは変えません。一度に二つ以上のフラグを取り除くことは、flag に2文字以上の文字列を指定すればできます。"info" がフラグの代わりに実験的情報を使っている場合は現在の "info" は書き換えられません。

get_date()

メッセージの配送日時をエポックからの秒数を表わす浮動小数点数で返します。

set_date(date)

メッセージの配送日時を date にセットします。date はエポックからの秒数を表わす浮動小数点数です。

get_info()

メッセージの "info" を含む文字列を返します。このメソッドは実験的 (即ちフラグのリストでない) "info" にアクセスし、また変更するのに役立ちます。

set_info(info)

"info" に文字列 info をセットします。

MaildirMessage インスタンスが mboxMessageMMDFMessage のインスタンスに基づいて生成されるとき、 Status および X-Status ヘッダは省かれ以下の変換が行われます:

結果の状態 mboxMessage または MMDFMessage の状態
"cur" サブディレクトリ O フラグ
F フラグ F フラグ
R フラグ A フラグ
S フラグ R フラグ
T フラグ D フラグ

MaildirMessage インスタンスが MHMessage インスタンスに基づいて生成されるとき、以下の変換が行われます:

結果の状態 MHMessage の状態
"cur" サブディレクトリ "unseen" シーケンス
"cur" サブディレクトリおよび S フラグ "unseen" シーケンス無し
F フラグ "flagged" シーケンス
R フラグ "replied" シーケンス

MaildirMessage インスタンスが BabylMessage インスタンスに基づいて生成されるとき、以下の変換が行われます:

結果の状態 BabylMessage の状態
"cur" サブディレクトリ "unseen" ラベル
"cur" サブディレクトリおよび S フラグ "unseen" ラベル無し
P フラグ "forwarded" または "resent" ラベル
R フラグ "answered" ラベル
T フラグ "deleted" ラベル

18.4.2.2. mboxMessage

class mailbox.mboxMessage([message])

mbox 固有の動作をするメッセージ。引数 messageMessage のコンストラクタと同じ意味を持ちます。

mbox メールボックス中のメッセージは単一ファイルにまとめて格納されています。送り主のエンベロープアドレスおよび配送日時は通常メッセージの開始を示す "From " から始まる行に記録されますが、正確なフォーマットに関しては mbox の実装ごとに大きな違いがあります。メッセージの状態を示すフラグ、たとえば読んだかどうかあるいは重要だとマークを付けられているかどうかといったようなもの、は典型的には Status および X-Status に収められます。

規定されている mbox メッセージのフラグは以下の通りです:

フラグ 意味 説明
R 読んだもの 読んだもの
O 古い(Old) 以前に MUA に発見された
D 削除(Deleted) 削除予定とされたもの
F フラグ付き(Flagged) 重要とされたもの
A 返答済み(Answered) 返答されたもの

"R" および "O" フラグは Status ヘッダに記録され、 "D"、"F"、"A" フラグは X-Status ヘッダに記録されます。フラグとヘッダは通常記述された順番に出現します。

mboxMessage インスタンスは以下のメソッドを提供します:

get_from()

mbox メールボックスのメッセージの開始を示す "From " 行を表わす文字列を返します。先頭の "From " および末尾の改行は含まれません。

set_from(from_, time_=None)

"From " 行を from_ にセットします。 from_ は先頭の "From " や末尾の改行を含まない形で指定しなければなりません。利便性のために、 time_ を指定して適切に整形して from_ に追加させることができます。 time_ を指定する場合、それは time.struct_time インスタンス、 time.strftime() に渡すのに適したタプル、または True (この場合 time.gmtime() を使います) のいずれかでなければなりません。

get_flags()

現在セットされているフラグを特定する文字列を返します。メッセージが規定された形式に準拠しているならば、結果は次の順に並べられた 0回か1回の 'R''O''D''F''A' です。

set_flags(flags)

flags で指定されたフラグをセットして、他のフラグは下ろします。flags は並べられたゼロまたは1回の 'R''O''D''F''A' です。

add_flag(flag)

flag で指定されたフラグをセットしますが他のフラグは変えません。一度に二つ以上のフラグをセットすることは、flag に2文字以上の文字列を指定すればできます。

remove_flag(flag)

flag で指定されたフラグを下ろしますが他のフラグは変えません。一二つ以上のフラグを取り除くことは、flag に2文字以上の文字列を指定すればできます。

mboxMessage インスタンスが MaildirMessage インスタンスに基づいて生成されるとき、 MaildirMessage インスタンスの配送日時に基づいて "From " 行が作り出され、次の変換が行われます:

結果の状態 MaildirMessage の状態
R フラグ S フラグ
O フラグ "cur" サブディレクトリ
D フラグ T フラグ
F フラグ F フラグ
A フラグ R フラグ

mboxMessage インスタンスが MHMessage インスタンスに基づいて生成されるとき、以下の変換が行われます:

結果の状態 MHMessage の状態
R フラグおよび O フラグ "unseen" シーケンス無し
O フラグ "unseen" シーケンス
F フラグ "flagged" シーケンス
A フラグ "replied" シーケンス

mboxMessage インスタンスが BabylMessage インスタンスに基づいて生成されるとき、以下の変換が行われます:

結果の状態 BabylMessage の状態
R フラグおよび O フラグ "unseen" ラベル無し
O フラグ "unseen" ラベル
D フラグ "deleted" ラベル
A フラグ "answered" ラベル

mboxMessage インスタンスが MMDFMessage インスタンスに基づいて生成されるとき、"From " 行はコピーされ全てのフラグは直接対応します:

結果の状態 MMDFMessage の状態
R フラグ R フラグ
O フラグ O フラグ
D フラグ D フラグ
F フラグ F フラグ
A フラグ A フラグ

18.4.2.3. MHMessage

class mailbox.MHMessage([message])

MH 固有の動作をするメッセージ。引数 messageMessage のコンストラクタと同じ意味を持ちます。

MH メッセージは伝統的な意味あいにおいてマークやフラグをサポートしません。しかし、MH メッセージにはシーケンスがあり任意のメッセージを論理的にグループ分けできます。いくつかのメールソフト(標準の mhnmh はそうではありませんが) は他の形式におけるフラグとほぼ同じようにシーケンスを使います:

シーケンス 説明
unseen 読んではいないが既にMUAに見つけられている
replied 返答されたもの
flagged 重要とされたもの

MHMessage インスタンスは以下のメソッドを提供します:

get_sequences()

このメッセージを含むシーケンスの名前のリストを返す。

set_sequences(sequences)

このメッセージを含むシーケンスのリストをセットする。

add_sequence(sequence)

sequence をこのメッセージを含むシーケンスのリストに追加する。

remove_sequence(sequence)

sequence をこのメッセージを含むシーケンスのリストから除く。

MHMessage インスタンスが MaildirMessage インスタンスに基づいて生成されるとき、以下の変換が行われます:

結果の状態 MaildirMessage の状態
"unseen" シーケンス S フラグ無し
"replied" シーケンス R フラグ
"flagged" シーケンス F フラグ

MHMessage インスタンスが mboxMessageMMDFMessage のインスタンスに基づいて生成されるとき、 Status および X-Status ヘッダは省かれ以下の変換が行われます:

結果の状態 mboxMessage または MMDFMessage の状態
"unseen" シーケンス R フラグ無し
"replied" シーケンス A フラグ
"flagged" シーケンス F フラグ

MHMessage インスタンスが BabylMessage インスタンスに基づいて生成されるとき、以下の変換が行われます:

結果の状態 BabylMessage の状態
"unseen" シーケンス "unseen" ラベル
"replied" シーケンス "answered" ラベル

18.4.2.4. BabylMessage

class mailbox.BabylMessage([message])

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)

メッセージの可視ヘッダを visible のヘッダと同じにセットします。引数 visibleMessage インスタンスまたは email.message.Message インスタンス、文字列、ファイル風オブジェクト(テキストモードで開かれてなければなりません)のいずれかです。

update_visible()

BabylMessage インスタンスのオリジナルヘッダが変更されたとき、可視ヘッダは自動的に対応して変更されるわけではありません。このメソッドは可視ヘッダを以下のように更新します。対応するオリジナルヘッダのある可視ヘッダはオリジナルヘッダの値がセットされます。対応するオリジナルヘッダの無い可視ヘッダは除去されます。そして、オリジナルヘッダにあって可視ヘッダに無い DateFromReply-ToToCCSubject は可視ヘッダに追加されます。

BabylMessage インスタンスが MaildirMessage インスタンスに基づいて生成されるとき、以下の変換が行われます:

結果の状態 MaildirMessage の状態
"unseen" ラベル S フラグ無し
"deleted" ラベル T フラグ
"answered" ラベル R フラグ
"forwarded" ラベル P フラグ

BabylMessage インスタンスが mboxMessageMMDFMessage のインスタンスに基づいて生成されるとき、 Status および X-Status ヘッダは省かれ以下の変換が行われます:

結果の状態 mboxMessage または MMDFMessage の状態
"unseen" ラベル R フラグ無し
"deleted" ラベル D フラグ
"answered" ラベル A フラグ

BabylMessage インスタンスが MHMessage インスタンスに基づいて生成されるとき、以下の変換が行われます:

結果の状態 MHMessage の状態
"unseen" ラベル "unseen" シーケンス
"answered" ラベル "replied" シーケンス

18.4.2.5. MMDFMessage

class mailbox.MMDFMessage([message])

MMDF 固有の動作をするメッセージ。引数 messageMessage のコンストラクタと同じ意味を持ちます。

mbox メールボックスのメッセージと同様に、MMDF メッセージは送り主のアドレスと配送日時が最初の "From " で始まる行に記録されています。同様に、メッセージの状態を示すフラグは通常 Status および X-Status ヘッダに収められています。

よく使われる MMDF メッセージのフラグは mbox メッセージのものと同一で以下の通りです:

フラグ 意味 説明
R 読んだもの 読んだもの
O 古い(Old) 以前に MUA に発見された
D 削除(Deleted) 削除予定とされたもの
F フラグ付き(Flagged) 重要とされたもの
A 返答済み(Answered) 返答されたもの

"R" および "O" フラグは Status ヘッダに記録され、 "D"、"F"、"A" フラグは X-Status ヘッダに記録されます。フラグとヘッダは通常記述された順番に出現します。

MMDFMessage インスタンスは mboxMessage インスタンスと同一の以下のメソッドを提供します:

get_from()

mbox メールボックスのメッセージの開始を示す "From " 行を表わす文字列を返します。先頭の "From " および末尾の改行は含まれません。

set_from(from_, time_=None)

"From " 行を from_ にセットします。 from_ は先頭の "From " や末尾の改行を含まない形で指定しなければなりません。利便性のために、 time_ を指定して適切に整形して from_ に追加させることができます。 time_ を指定する場合、それは time.struct_time インスタンス、 time.strftime() に渡すのに適したタプル、または True (この場合 time.gmtime() を使います) のいずれかでなければなりません。

get_flags()

現在セットされているフラグを特定する文字列を返します。メッセージが規定された形式に準拠しているならば、結果は次の順に並べられた 0回か1回の 'R''O''D''F''A' です。

set_flags(flags)

flags で指定されたフラグをセットして、他のフラグは下ろします。flags は並べられたゼロまたは1回の 'R''O''D''F''A' です。

add_flag(flag)

flag で指定されたフラグをセットしますが他のフラグは変えません。一度に二つ以上のフラグをセットすることは、flag に2文字以上の文字列を指定すればできます。

remove_flag(flag)

flag で指定されたフラグを下ろしますが他のフラグは変えません。一二つ以上のフラグを取り除くことは、flag に2文字以上の文字列を指定すればできます。

MMDFMessage インスタンスが MaildirMessage インスタンスに基づいて生成されるとき、"From"行が MaildirMessage インスタンスの配信日をもとに生成され、以下の変換が行われます:

結果の状態 MaildirMessage の状態
R フラグ S フラグ
O フラグ "cur" サブディレクトリ
D フラグ T フラグ
F フラグ F フラグ
A フラグ R フラグ

MMDFMessage インスタンスが MHMessage インスタンスに基づいて生成されるとき、以下の変換が行われます:

結果の状態 MHMessage の状態
R フラグおよび O フラグ "unseen" シーケンス無し
O フラグ "unseen" シーケンス
F フラグ "flagged" シーケンス
A フラグ "replied" シーケンス

MMDFMessage インスタンスが BabylMessage インスタンスに基づいて生成されるとき、以下の変換が行われます:

結果の状態 BabylMessage の状態
R フラグおよび O フラグ "unseen" ラベル無し
O フラグ "unseen" ラベル
D フラグ "deleted" ラベル
A フラグ "answered" ラベル

MMDFMessage インスタンスが mboxMessage インスタンスに基づいて生成されるとき、"From"行がコピーされ、全てのフラグが直接対応します:

結果の状態 mboxMessage の状態
R フラグ R フラグ
O フラグ O フラグ
D フラグ D フラグ
F フラグ F フラグ
A フラグ A フラグ

18.4.3. 例外

mailbox モジュールでは以下の例外クラスが定義されています:

exception mailbox.Error

他の全てのモジュール固有の例外の基底クラス。

exception mailbox.NoSuchMailboxError

メールボックスがあると思っていたが見つからなかった場合に送出されます。これはたとえば Mailbox のサブクラスを存在しないパスでインスタンス化しようとしたとき(かつ create パラメータは False であった場合)、あるいは存在しないフォルダを開こうとした時などに発生します。

exception mailbox.NotEmptyError

メールボックスが空であることを期待されているときに空でない場合、たとえばメッセージの残っているフォルダを削除しようとした時などに送出されます。

exception mailbox.ExternalClashError

メールボックスに関係したある条件がプログラムの制御を外れてそれ以上作業を続けられなくなった場合、たとえば他のプログラムが既に保持しているロックを取得しようとして失敗したとき、あるいは一意的に生成されたファイル名が既に存在していた場合などに送出されます。

exception mailbox.FormatError

ファイル中のデータが解析できない場合、たとえば MH インスタンスが壊れた .mh_sequences ファイルを読もうと試みた場合などに送出されます。

18.4.4. 非推奨のクラスとモジュール

バージョン 2.6 で撤廃.

古いバージョンの mailbox モジュールはメッセージの追加や削除といったメールボックスの変更をサポートしていませんでした。また形式ごとのメッセージプロパティを表現するクラスも提供していませんでした。後方互換性のために、古いメールボックスクラスもまだ使うことができますが、できるだけ新しいクラスを使うべきです。古いクラスは Python 3 で削除されました。

古いメールボックスオブジェクトはイテレーションと一つの公開メソッドだけを提供していました:

oldmailbox.next()

メールボックスオブジェクトのコンストラクタに渡された、オプションの factory 引数を使って、メールボックス中の次のメッセージを生成して返します。標準の設定では、 factoryrfc822.Message オブジェクトです (rfc822 モジュールを参照してください)。メールボックスの実装により、このオブジェクトの fp 属性は真のファイルオブジェクトかもしれないし、複数のメールメッセージが単一のファイルに収められているなどの場合に、メッセージ間の境界を注意深く扱うためにファイルオブジェクトをシミュレートするクラスのインスタンスであるかもしれません。次のメッセージがない場合、このメソッドは None を返します。

ほとんどの古いメールボックスクラスは現在のメールボックスクラスと違う名前ですが、 Maildir だけは例外です。そのため、新しい方の Maildir クラスには next() メソッドが定義され、コンストラクタも他の新しいメールボックスクラスとは少し異なります。

古いメールボックスのクラスで名前が新しい対応物と同じでないものは以下の通りです:

class mailbox.UnixMailbox(fp[, factory])

全てのメッセージが単一のファイルに収められ、 From (From_ として知られています) 行によって分割されているような、旧来の Unix形式のメールボックスにアクセスします。ファイルオブジェクト fp はメールボックスファイルを指します。オプションの factory パラメタは新たなメッセージオブジェクトを生成するような呼び出し可能オブジェクトです。 factory は、メールボックスオブジェクトに対して next() メソッドを実行した際に、単一の引数、 fp を伴って呼び出されます。この引数の標準の値は rfc822.Message クラスです (rfc822 モジュール – および以下 – を参照してください)。

注釈

このモジュールの実装上の理由により、 fp オブジェクトはバイナリモードで開くようにしてください。特に Windows 上では注意が必要です。

可搬性を最大限にするために、Unix 形式のメールボックス内にあるメッセージは、正確に 'From ' (末尾の空白に注意してください) で始まる文字列が、直前の正しく二つの改行の後にくるような行で分割されます。現実的には広範なバリエーションがあるため、それ以外の From_ 行について考慮すべきではないのですが、現在の実装では先頭の二つの改行をチェックしていません。これはほとんどのアプリケーションでうまく動作します。

UnixMailbox クラスでは、ほぼ正確に From_ デリミタにマッチするような正規表現を用いることで、より厳密に From_ 行のチェックを行うバージョンを実装しています。 UnixMailbox ではデリミタ行が From name time の行に分割されるものと考えます。可搬性を最大限にするためには、代わりに PortableUnixMailbox クラスを使ってください。このクラスは UnixMailbox と同じですが、個々のメッセージは From 行だけで分割されるものとみなします。

class mailbox.PortableUnixMailbox(fp[, factory])

厳密性の低い UnixMailbox のバージョンで、メッセージを分割する行は From のみであると見なします。実際に見られるメールボックスのバリエーションに対応するため、 From 行における "name time" 部分は無視されます。メール処理ソフトウェアはメッセージ中の 'From ' で始まる行をクオートするため、この分割はうまく動作します。

class mailbox.MmdfMailbox(fp[, factory])

全てのメッセージが単一のファイルに収められ、4 つの control-A 文字によって分割されているような、MMDF 形式のメールボックスにアクセスします。ファイルオブジェクト fp はメールボックスファイルをさします。オプションの factoryUnixMailbox クラスにおけるのと同様です。

class mailbox.MHMailbox(dirname[, factory])

数字で名前のつけられた別々のファイルに個々のメッセージを収めたディレクトリである、MH メールボックスにアクセスします。メールボックスディレクトリの名前は dirname で渡します。 factoryUnixMailbox クラスにおけるのと同様です。

class mailbox.BabylMailbox(fp[, factory])

MMDF メールボックスと似ている、Babyl メールボックスにアクセスします。 Babyl 形式では、各メッセージは二つのヘッダからなるセット、 original ヘッダおよび visible ヘッダを持っています。 original ヘッダは '*** EOOH ***' (End-Of-Original-Headers) だけを含む行の前にあり、visible ヘッダは EOOH 行の後にあります。Babyl 互換のメールリーダは visible ヘッダのみを表示し、 BabylMailbox オブジェクトは visible ヘッダのみを含むようなメッセージを返します。メールメッセージは EOOH 行で始まり、 '\037\014' だけを含む行で終わります。 factoryUnixMailbox クラスにおけるのと同様です。

古いメールボックスクラスを撤廃された rfc822 モジュールではなく、 email モジュールと使いたいならば、以下のようにできます:

import email
import email.Errors
import mailbox

def msgfactory(fp):
    try:
        return email.message_from_file(fp)
    except email.Errors.MessageParseError:
        # Don't return None since that will
        # stop the mailbox iterator
        return ''

mbox = mailbox.UnixMailbox(fp, msgfactory)

一方、メールボックス内には正しい形式の MIME メッセージしか入っていないと分かっているのなら、単に以下のようにします:

import email
import mailbox

mbox = mailbox.UnixMailbox(fp, email.message_from_file)

18.4.5. 例

メールボックス中の面白そうなメッセージのサブジェクトを全て印字する簡単な例:

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