Maildir

Maildirは、広く使われている電子メール格納フォーマットの一種で、メッセージを追加・移動・削除する際にメッセージの完全性を保証するためにアプリケーションレベルでファイルロックする必要がない。個々のメッセージは個別のファイルとして一意な名前付きで保持されている。全ての操作はファイルシステムの不可分操作を使うので、ファイルシステム側で並行性制御のためのファイルロックを行う。Maildirはディレクトリであり、サブディレクトリとして tmp、new、cur がある。

1. 仕様
-----

Maildirは単純さと保守の容易さが優れており、多数のユーザーを扱う場合にも機能性に優れている。

1.1. Maildir
------------

qmail、djbdns、その他の各種ソフトウェアを開発したダニエル・バーンスタインがMaildirのオリジナルにして唯一の仕様を書いた。その後バーンスタインに追随する動きがなく、Maildirを標準化しようという努力もなされていない。この仕様はバーンスタインのqmail向けに書かれたもので、多くのプログラムに実装するのに十分な汎用性を備えていた。時と共に様々な実装がなされ、数少ない欠点も発見されているdate=2009年9月}}。

1.2. Maildir++
--------------

Courier Mail Server などのソフトウェアを開発した Sam Varshavchik が、サブフォルダとメールクオータをサポートすべくMaildirの拡張フォーマット Maildir++ を作った。Maildir++ ディレクトリ群には、'.'で始まる名前のサブディレクトリがあり、それらもMaildir++のフォルダである。したがってこの拡張はMaildir仕様とは異なるが、MaildirソフトウェアはMaildir++もサポートするものが多い。

2. Maildirが関わる領域
----------------

電子メールは以下のような状況で格納される必要がある。

SMTP MTA において、遠隔の電子メールサーバから受信後、別の場所に配送されるのを待つ間。MTAが使う格納領域をスプールと呼ぶことが多い。
IMAPのメールストアにおいて、電子メールクライアント  に電子メールを提供するまでの間。
MUAを使ってユーザーがローカルに電子メールを読む場合、直接通信プロトコルを使って受信したものを表示しているのではなく、一旦ストレージ上に電子メールを格納して、それを読み取っている。
スパムのフィルタリングなど、電子メールを媒体に一旦格納する場合。RFC 822 や関連する標準は電子メールメッセージを複数行のテキストであると定義しており、そのテキストの先頭の数行は厳密な規則に従っている。この考え方はファイルとよく一致する。Maildirは個々のメッセージに1つのファイルを対応させる設計であり、SMTPなどのプロトコルを使ってネットワーク上を転送される電子メールと正確に対応している。MTAも電子メールをシーケンシャルアクセス方式でまとめて処理するのが一般的であり、これもメッセージとファイルの対応が適している。

ディレクトリにそれぞれ1つのメッセージを含む多数のファイルが置かれているという構造は、電子メールのランダムアクセスが必要とされるような状況では不十分である。このため多くの実装では、検索能力に優れたデータベースを使っている。2007年現在、一般にファイルシステムはデータベースよりもアクセス性能がよいのでdate=2009年9月}}、実装に当たってはインデックス付けの方法、プログラミングの容易さ、性能や効率、既存の技術の再利用、信頼性などを勘案している。最近のメール関連ソフトウェアである Cyrus IMAP server、MH Message Handling System、Dovecot IMAP server、UW IMAP server などは全て相互に非互換なメッセージ毎にファイルを使うフォーマットにインデックス付け手法を組み合わせている。

3. 技術的詳細
--------

電子メールメッセージを配送するプロセスは、その内容を tmp ディレクトリに一意なファイル名のファイルとして書き込む。一意なファイル名を生成する現在のアルゴリズムは、時刻とホスト名といくつかの擬似乱数パラメータを使って一意性を保証している。

配送プロセスは、tmp///unique// にファイルを作り、メッセージを書き込み、それを new///unique// に移動させる。この移動は一般に new へのハードリンクを生成し、その後 tmp からアンリンクするという手順だが、実装によっては単に rename を使っている。電子メールクライアントは tmp を決してみることは無いので、このような手順でMaildirを読んでいるプロセスが部分的に書かれたメッセージを読み取ってしまうという事態を避ける。

電子メールクライアントプロセスが new ディレクトリにメッセージを見つけると、それを cur に移動させる。このときは rename を使う。リンクしてからアンリンクするという前述の方式をここで使うと、メッセージが両方に存在するという事態が生じる可能性がある。そして、中身を読む前にファイル名の末尾に付加情報を追加する。この付加情報は、まずコロンがあり、次に '2' とコンマが1つずつあり、各種フラグが並ぶ。'2' は大まかに言えば、コンマの後の情報のバージョンを意味する。ただし、公式なバージョンとしては '2' しかなく、'1' は実験段階で使われただけである。仕様上定義されているフラグとしては、"P"、"R"、"S"、"T"、"D"、"F" がある。Dovecotでは小文字を26種類のIMAPキーワードに使い、それらには$MDNSentのような標準化されたキーワードやユーザー定義フラグが含まれる。

4. ロックしない操作による問題
----------------

ダニエル・バーンスタインは、たとえNFS上でも、複数のプロセスがロックせずに同時に書き込もうとしても大丈夫なようにMaildirを設計した。大抵の場合、これがうまく機能しているが、バーンスタインはファイルシステムの実装上の制限を考慮していなかった。ディレクトリをプロセスが読み込む場合 readdir を使うが、これは一度に全体を読み込むわけではなく、ディレクトリエントリ毎に読み込む。このため一連の readdir でディレクトリを読み取っている最中に別のプロセスがファイル名の変更を行った場合、タイミングによってはそのファイルのエントリが読み取れないことがある。これは例えば受信メールの一覧を表示させたときにメッセージが消えたように見えることになる。そして、もう一度一覧表示させると、消えたはずのメッセージが再度出現する。このような問題を回避するため、Maildirのトップを独自にロックする方式を採用しているものもある。例えば、DovecotはMaildirに対して独自のロック機構を使っている。

macOSのHFS Plusでは、この問題が起きないように見えるdate=2009年9月}}。Linuxの場合、inotifyでMaildirの変化を監視することで問題を防ぐことができる。例えば、readdirを行った後で、inotifyで新たなファイルが追加されていないかを調べればよいdate=2009年9月}}。

5. Maildirを直接サポートしているソフトウェア
---------------------------

5.1. メールサーバ
-----------

Dovecot - IMAPサーバ
Courier Mail Server - SMTP/IMAPサーバ。Maildir++フォーマットが生まれた。
Exim - SMTPサーバ
Postfix - SMTPサーバ
qmail - SMTPサーバ。Maildirフォーマットが生まれた。
XMail - オープンソースでクロスプラットフォームのSMTP/POP3サーバ
MeTA1 - SMTPサーバ
OpenSMTPD - SMTPサーバ

5.2. 配送エージェント
-------------

Procmail
Maildrop
Getmail - Fetchmailの代替

5.3. メールリーダ
-----------

Evolution - Outlook に似たGNOMEの公式電子メールクライアント
Gnus
KMail - KDEのメールリーダ
Mutt
Wanderlust
Mozilla Thunderbird

5.4. メール検索ツール
-------------

Beagle - Maildirや他の様々なフォーマットをインデックス付けする。

6. 間接的にMaildirをサポートするソフトウェア
---------------------------

これらのソフトウェアの連携方式と通信プロトコルの役割を考慮すると、Maildirをサポートするソフトウェアの範囲はもっと広がる。例えば、次のように考えることができる。

誤解されていることが多いが、Sendmail MTA は単体では電子メール配送フォーマットをサポートしていない。Sendmail には mail.local という独立したプロセスがあって、配送を行っている。mail.local として Procmailを使うことができるので、Sendmail は他のフォーマットと同様にMaildirもサポートしていると言える。
多くのメールリーダーはMaildirはサポートしていないが、IMAPなどのリモートアクセスフォーマットはサポートしている。IMAPメールストアにはMaildirをサポートするものがあるので、IMAPをサポートするメールリーダーはそれを経由してMaildirのフォルダにアクセスできる。
FetchmailはMaildirをサポートしていないが、SMTPサーバやローカルな配送エージェントとやり取りするので、それらを経由することで電子メールをFetchmailからMaildirに配送できる。

7. Windowsのソフトウェア
-----------------

Maildir標準はファイル名にコロンを使うため、Microsoft Windows 上では修正なしで実装できない。Windows上でコロンの代わりに別の文字を使えない技術的理由はないが、仕様が更新されていないため、代替に使用する文字について全体的な合意がなされていないという問題がある。そのため、Windows上のあるプログラムがMaildirファイルを書いても、別のプログラムが読めないという問題が発生する。PythonやPerlで書かれMaildirをサポートしているプログラムがあるし、Cygwinなどを使ってUNIX上のプログラムをWindows上で動かすこともできるが、コロンの代替をどうするかという問題が解決しないと動作が保証できない。

また、Windowsではファイル名更新が不可分操作でないという問題もある。

8. 関連項目
-------

mbox
Eml形式

9. 脚注・出典
--------

10. 外部リンク
---------

[1]