要約

  • 初期のPOP3では、現在のmaildropを開いた後に付ける番号と、LASTが保持する最高アクセス番号が使われた。どちらも、切断後に同じメッセージを一件ずつ認識する十分な記憶ではなかった。
  • RFC 1725はLASTを削除して任意のUIDLを加え、RFC 1939はUIDを一つのmaildrop内でセッションを越えて持続させた。RFC 2449のCAPAはUIDL対応を広告したが、識別子の品質や保存寿命は別の証拠として残した。

任意機能を使う前に、クライアントはサーバーがその機能を持つか知る必要がある。古いPOP3では、設定で決め打ちするか、コマンドを送って拒否されるかを見るしかない場合があった。機能を発見する操作と、実際の取引を進める操作の区別が弱かったのである。

RFC 2449のCAPAは、この不確実性に一覧を与えた。応答にUIDLがあれば、サーバーは任意のUIDLコマンドを実装していると宣言している。クライアントは本文を取得する前に、その認識手段を使えるか判断できる。

ただし、広告された能力をそのまま大きな保証にしてはいけない。CAPAは「UIDLを話せる」と言うだけで、UIDが世界で一意だとも、メッセージが永久に残るとも、ローカル保存が成功したとも言わない。この境界を理解するには、UIDLが解決した元の問題――セッション番号が切断を越えられないこと――まで戻る必要がある。

現在の番号は、現在のmaildropを操作するために生まれた

RFC 1460が想定したPOP3の利用者は、メール転送システムを常時動かせない小型のワークステーションやパーソナルコンピューターだった。サーバーがメールをmaildropに保持し、クライアントは必要な時に接続して取得し、通常は削除した。

サーバーはmaildropを開いて内容を解析した後、先頭を1、次を2という順番で番号付けする。クライアントはその数字でLISTRETRDELEを指定する。現在の取引にとって、位置は短く明確な参照である。

しかし、ある接続で2番だったメッセージは、その前にあった1番が消えれば次の接続で1番になる。新着や外部削除が集合を変えるたび、同じ数値が指すものは変わり得る。番号は今回の座標であって、二つのmaildrop表示を結ぶ名前ではない。

初期仕様のLASTは、以前の取引でアクセスした最大番号を返した。クライアントはそれより大きい番号を未処理と推測できた。高い番号へのRETRやDELEは境界を進め、RSETはその値をゼロに戻した。

一つの整数は連続した進捗には便利だが、穴を表せない。1番と3番を保存し、2番を保存していない履歴は、最大値3だけでは失われる。二台のクライアントが違う履歴を持つ場合にも一つの境界では足りない。下位のメッセージが消えれば、数字の意味自体も移動する。

RFC 1725の変更一覧は、LASTの削除と任意UIDLの追加を並べた。文書は一方が他方の唯一の原因だとは述べない。それでも設計上は、サーバーが一つの進捗値を抱える方式から、各メッセージに認識用トークンを出し、クライアントが自分の履歴を持つ方式への転換が見える。

UIDLの二列は異なる時間を表した

UIDLにメッセージ番号を付けると、サーバーは現在番号とunique-idの組を返す。引数なしなら、削除マークの付いていない各メッセージについて同じ組を複数行で返す。

現在番号は、この接続で本文を取得したり削除を指定したりするために使う。UIDは、前回の接続でクライアントが記録した項目と今回の行を照合するために使う。二列を一つの恒久IDとして扱うのではなく、短命な操作位置と、より長く続く認識用トークンとして読む必要がある。

RFC 1939では、UIDはサーバーが決める1文字から70文字までの印字可能文字列である。一つのmaildrop内でメッセージを識別し、セッションを越えて持続する。前のセッションがUPDATE状態に入らず終わった場合にも、この持続性は必要である。

この規則は異常切断で効く。クライアントが本文を受信した後、QUITより前に接続を失えば、サーバーは削除マークを実行してはならない。同じメッセージが次回も現れる。その時UIDまで変われば、クライアントは既に保存したメールを新着と判断するか、誤った履歴で破壊的処理を行う可能性がある。

サーバーは、その項目が存在する間、同じmaildropでUIDを再利用すべきでない。再利用すると新しい項目が古い項目のローカル履歴を引き継いで見える。

サーバーがトークンを出し、クライアントが「見た」を定義した

UIDLはサーバー側に端末別の既読状態を作らない。サーバーは範囲の限られたトークンを割り当て、維持する。クライアントが、そのUIDを取得済み、表示済み、保存済み、あるいは削除可能と判断した事実を自分の台帳に残す。

これはPOP3の単純さを守る配分だった。中央のサーバーは各端末のフォルダーやフラグを同期する必要がない。切断していた端末も、UID一覧とローカル台帳を比較してから必要な本文だけ取得できる。

一方で、耐障害性の一部がクライアントへ移る。台帳を失えば、残されたメールを再取得する。サーバー移行で本文を保ったままUIDを再生成すれば、古い内容が一斉に新着に見える。取得完了前に「処理済み」を記録すれば、後の削除で唯一のコピーを失い得る。

したがって、UIDL成功、本文受信完了、ローカル書き込み、DELEマーク、QUITによるUPDATE完了、異常終了は別々の状態である。認識用トークンが返ったことは、利用結果を証明しない。

unique-idは世界的IDでも、一物一値の約束でもなかった

UIDの権限は一つのmaildropに限定される。同じ文字列が別のアカウントや別サーバーにあっても、仕様上の関係はない。メールヘッダーのMessage-IDではなく、送信者、受信者、配送、完全性、真正性の証明にもならない。

さらにRFC 1939は、通常は任意に割り当てたUIDを保存する方法を勧めながら、メッセージからハッシュを計算する方法も許している。その場合、同じmaildropにある二つの同一コピーが同じUIDを持つことを、クライアントは扱えなければならない。

同じUIDの行を一件にまとめると、実在する一コピーを黙って消す可能性がある。照合にはUIDだけでなく、現在の行数と番号も必要になる。「unique」という名称は、すべての物理コピーに別の値を保証してはいない。

狭い範囲は弱点ではなく、誤解を防ぐ設計でもある。POP3が必要としたのは、同じmaildropを再訪したクライアントが過去の項目を認識できることだった。世界共通のメール身分証や内容認証まで引き受ける必要はなかった。

CAPA、UIDL、EXPIREは三つの違う主張だった

CAPAのUIDL行は、コマンド対応を先に確認させる。これは試して失敗する動作を減らし、クライアントが対応経路と非対応経路を明示的に選ぶ助けになる。しかし、広告は導入率の統計でも実装品質の監査でもない。

UIDが存在する間持続することと、メッセージがいつまで保存されるかも別である。RFC 1939は、サーバーに既読メールを残すと大量に蓄積し得ると警告し、サイトの保存方針による削除を認めた。過去にUIDを見たからといって、現在も本文が保管されているとは限らない。

RFC 2449のEXPIRE能力は、最小保存日数、0、またはNEVERを広告できる。それでも個別メッセージの正確な消滅時刻は示せない。到着、最初の一覧表示、RETRなど、どの時点から時計を進めるかがサイトによって異なるためである。

CAPAは能力の存在、UIDLはmaildrop内の認識、EXPIREは保存方針を述べる。三つを分けることで、クライアントは「使える」「同じものだ」「まだある」を別々に検証できる。

番号より長く、保存期間より控えめな識別子

UIDLは完全なメールボックス同期を提供しなかった。フォルダーも、共有既読フラグも、多端末競合の調停もない。代わりに、一時的な番号しか持たない簡単な取得プロトコルへ、再接続に必要な最小限の連続性を加えた。

歴史的に重要なのは、その連続性が越権しなかったことだ。サーバーはトークンを割り当てるが、ユーザーが保存したかは知らない。クライアントは履歴を持つが、メールの保管を命令できない。CAPAは能力を名乗らせるが、品質までは保証しない。

セッション番号は現在を操作する。UIDは切断を越えて過去と照合する。EXPIREは将来の保存限界を示す。この三つの時間を混ぜなかったからこそ、POP3は単純さを保ったまま「サーバーに残す」という利用に対応できた。

出典