要約

  • RFC 5229はset、文字列展開、マッチ変数を導入した。ただしスクリプトがvariables機能を明示的に要求した場合に限られる。
  • その記憶は範囲が限られていた。捕捉値は実際に評価された条件に左右され、実行中のスクリプト内でのみ見え、実装上限を超えれば切り詰められることがある。

フィルターに必要だったのは、小さな記憶であって大きな実行環境ではない

2008年1月の時点で、Sieveには「メールの最終配送時にフィルターを実行する」という役割があった。基本仕様は、有用でありながら意図的に制約された言語として記述されている。変数もループもなく、シェルコマンドも呼び出せない。それは未実装の便利機能の一覧ではない。利用者が書くフィルターからメールサーバーへ何を要求できるのか、その境界を示していた。

RFC 5229はその境界の一部を慎重に広げた。スクリプトはrequire "variables"を宣言し、setで名前付きの文字列を格納できる。その値は別の文字列に埋め込んだり、スクリプトの文字列テストで調べたりできた。ワイルドカード照合が成功すれば、照合全体を${0}、各ワイルドカードに対応する部分を${1}、${2}などとして参照できる。たとえばヘッダーからメーリングリスト名を取り出し、メールボックスのパスに使えば、同じ文字列を規則ごとに書き直さずに済む。

ただし、これは永続的な記憶を与えるものではない。仕様が定める可視範囲は「現在実行中のスクリプト」だ。メールボックス全体で共有する保存領域も、過去のメールを記録する台帳も、利用者間で共有する状態も定義されていない。「変数」という語の響きより、標準化された実体は小さい。スクリプトの実行中だけ、名前と文字列を結び付ける仕組みである。

機能の宣言も安全性の一部だった

機能を使う前に、スクリプトはそれを要求しなければならない。variablesの指定がなければ、文字列の意味が暗黙に変わることはない。拡張可能な言語では、この宣言が重要になる。操作の存在だけでなく、スクリプトとインタープリターの間で「その操作を使う」という合意を明示するからだ。

変数は制御が該当箇所に達したとき、その時点の値で展開される。置換は一度だけだ。未定義の名前は空文字列になり、名前の大文字・小文字は区別されない。この簡潔さは、誤りを目立たなくもする。変数名のタイプミスで値が消えても、欠落を知らせるエラーにならない場合がある。展開後の値に別の${...}が含まれていても、再帰的な二度目の展開は行われない。

追加された加工方法も限られている。ASCIIの大小文字変換、先頭文字の変換、ワイルドカードのエスケープ、文字列長の取得と、stringテストだ。算術演算、ループ、任意コードの実行は含まれない。表現力が増したとはいえ、何でもできるようになったわけではない。少数の文字列を名前で参照し、限定された方法で再利用できるようになったのだ。

捕捉値は、実際に通った条件分岐の産物

マッチ変数では、制御フローが値の由来を決める。RFC 5229はテストを左から順に評価し、真偽が確定すれば残りを実行しないよう求める。たとえばanyof (true, header :matches ...)では、最初の条件で真が確定する。ヘッダーの照合は実行されず、捕捉も生成されない。後の照合が成功すれば、それまでのマッチ一覧は置き換わり得る。一方、失敗した照合から新しい断片は得られない。複雑な規則で${1}を使うなら、どのテストが実際に動いたのかを追う必要がある。

後から追加された照合機能が、捕捉の副作用をすべて引き継ぐわけでもない。RFC 5229の3か月後に出たRFC 5173は、その境界を明記した。variablesが有効なら、本文テストの検索キーにある変数参照は展開される。しかし本文テストのワイルドカード照合は、マッチ変数を設定してはならない。標準は機能同士の組み合わせを認めつつ、表面が似ている処理を同じ挙動にまとめることは避けた。

最低実装要件にも境界が数字で示される。128個以上の変数、32文字以上の名前、4,000文字以上の値、そして${1}から${9}の捕捉をサポートしなければならない。個々の実装の上限を超える値は、可能ならコンパイル時に検出するのが望ましい。実行時にしか分からない場合は切り詰めることが想定され、それをエラー扱いしてはならない。セキュリティ節が、大きく重要なデータ構造を変数に置かないよう注意し、捕捉文字列は差出人が任意に制御し得ると述べるのはそのためだ。

長い草案の履歴は、普及の証拠ではない

Datatrackerの履歴では、個人草案の最初の版は2003年3月にさかのぼる。2004年末からSieveワーキンググループ版が続き、2005年にも複数回の改訂があった。IESGの文書はこの仕様をSieve Mail Filtering Languageワーキンググループの成果と記している。2006年の承認と2008年1月のRFC刊行は別々の記録上の節目だ。日付の並びだけでは時間を要した理由も、実装がどれだけ広がったかも分からない。

Heng Luの「Minimum Initial Specification」は、ここでの分析視角になる。requireは小さな基礎と、スクリプトごとに有効化する将来の機能とを両立させる。「Running-Code Primacy」は、標準化された機能と、ある実装が実際に提供している機能は別だと教える。「Reality Layers」の視点に立てば、スクリプトの宣言、インタープリター内部の値、サーバーの挙動、受信者のメールボックスで起きることを一つの証拠にまとめずに済む。いずれも後年の分析枠組みであり、RFC執筆者の意図を示す史料ではない。

フィルターは、一度の照合で得た値をその場で覚え、少数の名前付き文字列を使い回せるようになった。しかし、それだけでは過去のメールを記憶したことにも、差出人を認証したことにも、メッセージの最終到達先を証明したことにもならない。RFC 5229の歴史的な変化は、Sieveの境界を消すことではなく、明示して使う小さな接合部を実用的にしたことだった。

出典