Maildir

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

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

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

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

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

* SMTP MTA において、遠隔の電子メールサーバから受信後、別の場所に配送されるのを待つ間。MTAが使う格納領域をスプールと呼ぶことが多い。
* IMAPのメールストアにおいて、電子メールクライアント (MUA) に電子メールを提供するまでの間。
* MUAを使ってユーザーがローカルに電子メールを読む場合、直接通信プロトコルを使って受信したものを表示しているのではなく、一旦ストレージ上に電子メールを格納して、それを読み取っている。
* スパムのフィルタリングなど、電子メールを媒体に一旦格納する場合。

 や関連する標準は電子メールメッセージを複数行のテキストであると定義しており、そのテキストの先頭の数行は厳密な規則に従っている。この考え方はファイルとよく一致する。Maildirは個々のメッセージに1つのファイルを対応させる設計であり、SMTPなどのプロトコルを使ってネットワーク上を転送される電子メールと正確に対応している。MTAも電子メールをシーケンシャルアクセス方式でまとめて（バッチ的に）処理するのが一般的であり、これもメッセージとファイルの対応が適している。

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

## 技術的詳細
電子メールメッセージを配送するプロセスは、その内容を `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のような標準化されたキーワードやユーザー定義フラグが含まれる。

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

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

## Maildirを直接サポートしているソフトウェア
### メールサーバ
*Dovecot - IMAPサーバ
*Courier Mail Server - SMTP/IMAPサーバ。Maildir++フォーマットが生まれた。
*Exim - SMTPサーバ
*Postfix - SMTPサーバ
*qmail - SMTPサーバ。Maildirフォーマットが生まれた。
*XMail - オープンソースでクロスプラットフォーム（*nixとWindows）のSMTP/POP3サーバ
*MeTA1 - SMTPサーバ
*OpenSMTPD - SMTPサーバ

### 配送エージェント
*Procmail
*Maildrop
*Getmail - Fetchmailの代替

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

### メール検索ツール
* Beagle - Maildirや他の様々なフォーマットをインデックス付けする。

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

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

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

また、Windows（特に古いバージョン）ではファイル名更新が不可分操作でないという問題もある。

## 関連項目
*mbox
* Eml形式

## 脚注・出典

## 外部リンク
* manual page for maildir