アドレスリライティング

アドレスの書き換え定義も sendmail.cf の中のことだが、内容が重くなりそうなのでこうして別ページにした。参考にした TCP/IP Network Administration - Rewriting the Mail Address は、アドレスリライティングこそ ハート・オブ・sendmail.cf だ と言っている。

リライティング ディレクティブの基本書式

Rpattern	transformation	commnet

ご覧のように、アドレスリライティングの命令ひとつは 3つのフィールドから成る。フィールド間はスペースでなくタブで区切られる。おそらく、いずれのフィールドもスペースを含むことが少なからずあるからだろう。各フィールドは下記のような働きをする;

ルールセット

ルールは単独で書くのではなく、ルールセットというまとまりにして構成する。 sendmail.cf の中ででルールセットを定義するには、ここからルールセット n の定義を始めるぞという意味で

Sn

というだけの行を書く (n は数字)。すると、次の行から、また今度別の Sx が現れるまでに書かいたルールは、ルールセット n のメンバとなる。幾つかの番号のルールセットには、あらかじめ決められた特定の守備範囲がある。

ルールセットNo. 用途
3 入力アドレスに対して一番最初に適用されるルールセット。様々な形のメールアドレスを local_part@host.domain という正式な形に整形する。
0 ルールセット3 の次に適用される。ただし処理対象は、メール配送に実際に使われる受信者アドレスだけ。入力アドレスから、メーラー (smtp など)、そのメーラー(配送システム) に応じたホスト部、ユーザ部の、3つの基本情報を生成する。後述 トランスフォーメーション部のメタシンボル$#mailer$@host$:user の説明を参照のこと。
1 メールの送信者アドレスすべてに適用される。
2 メールの受信者アドレスすべてに適用される。
4 メール中のすべてのアドレスに対して適用され、それらを内部形式のアドレスから外部形式のアドレスへと変換する。
5 ローカルアドレスに適用される。ここへ送り込まれるのは sendmailalias 処理を経た後なので、即ち、このルールセットは alias を持たないアドレスにのみ作用する。

n にこれら以外の番号を付けた独自のルールセットを作ることもできる。それらはアドレスリライティングのトランスフォーメーション部で $>n を指定することによってそこへジャンプさせたり(トランスフォーメーションのメタシンボルの項で述べる)、メーラー定義 (Mコマンドで設定) の S 及び R フィールドによってメーラー毎に異なるオプションルールセットを通らせることもできる。

メタシンボル

pattern 部や transformation 部は、前ページで述べたマクロクラス、固定文字列、それに以下に述べるメタシンボルを組み合わせて書くことができる。メタシンボルは、正規表現でいう特殊文字 (制御文字) のようなものだと考えることができる。

なお、これからの説明の中で出てくるトークン (token) とは、入力文字列を区切り境界文字 (operators, operator chars) で分解したパーツのこと。区切り境界文字は、O 動作オプションディレクティブOperatorChars、または予約済みマクロ $o に指定した文字リストで、筆者の見た例では .:%@!^=/[]|+ だった(それがデフォルトかどうかは不明)。入力アドレス中の区切り境界文字それぞれも、ひとつのトークンとしてカウントされる。例えば;

becky@peanut.nuts.com

という入力アドレスは becky, @, peanut, ., nuts, ., com という 7つのトークンに分解されることになる。

pattern 部でのメタシンボルと transformation 部でのメタシンボルとでは、バリエーションや意味が異なる。

パターン部のメタシンボル

メタシンボル 説明
$@ 0個のトークン。入力アドレスがヌル (つまりアドレスが空) であることを検出するために単独で使うというのが、ほとんど唯一の使用法
$* 0個以上のあらゆるトークン
$+ 1個以上のあらゆるトークン
$- きっかり1個のあらゆるトークン
$=X クラス X のいずれかのメンバにマッチするトークン
$~X クラス X のどのメンバともマッチしないトークン
$X マクロ X の値とマッチするトークン

各メタシンボルにマッチしたトークンは、不特定トークン (indefinite tokens) という一種の一時変数に格納される。なぜ不特定なのかといえば、ひとつの不特定トークン$- でマッチさせた時のようにトークンを 1個だけ持つこともあれば、$*$+ などでマッチさせた時のように複数のトークンを含むこともあるから。不特定トークンは、 transformation フィールドで、 PerlAWK の正規表現マッチでの $1\1 に似たやり方で参照できる。

トランスフォーメーション部のメタシンボル

メタシンボル 説明
$n n 番目の不特定トークン(上記参照)。 n は 1 から始まる
$[name$] ホスト名やIPアドレス name を DNS でリゾルブした正式名 (canonical name) と置き換えられる。例えばドメイン example.com$[alpha$] を使った場合、この表現は alpha.example.com に置き換えられる。DNS に登録された alpha.example.com の IP が 192.168.1.1 だとすれば、$[[192.168.1.1]$] はやはり alpha.example.com になる (内側の [] は、リライトルールで IPアドレスを書く時の書式のひとつで、リゾルブするな! という意味)
$>n trans trans (通常の transformation 指定句。例えば `$1 % $2') をルールセット n に送り込みその結果で置き換える
$@trans transformation 部の先頭に $@ を置くと、このルールの処理が終わるとともにアドレスリライティングを終了する。つまりこのルールの結果が即ちアドレスリライティングの最終結果となる。リライティング ディレクティブの基本書式 の項を参照
$:trans transformation 部の先頭に $: を置いた場合、このルールの結果は通常通りルールセットへ再投入されるものの、このルール自体は次のループからはスキップされる
$#mailer$@host$:user ルールセット0 でのみ使用される定型句。mailerM コマンドで定義してあるメーラー種別。例えば入力 david<@mail.example.com> をルール $#smtp$@$2$:$1<@$2>$3 に通すと、メーラー smtp、ホスト mail.example.com、ユーザ david という 3つの基本情報が作られる
$#error$@comment$:msg これもルールセット0 でのみ使用される定型句で、pattern 部にマッチした時のエラーメッセージを生成するために使用される。例えば、
R<@$+> $#error$@5.1.1$: User address required
は、<@example.com> だけのような不十分な入力に対して、"User address required"(ユーザのアドレスは必須だよ) というエラーメッセージを発生する。comment 部はコメントであり処理に影響を与えない
$(map key [$@arg [$@arg]...] [$:default]$) データベース(Kコマンドで定義) map からインデックスキー key に対する値を取得する。引数 arg が指定された場合には、そのDBのプロシージャで arg に応じた処理がなされた結果が出力となる。key に対する結果が得られない場合は何の置き換えも起こらないが、その時 default が指定されていれば default 部に書いた transformation が採用される
${X name$} マクロ X で定義されたNISマップまたはNIS+テーブルで name をリゾルブした結果と置き換えられる

スタティックルート

まず、SMTP の一般論として Static (固定) Route とは何かということを知っておかなくてはならない。通常、MTA がメールを送信/リレーする際には、DNS の MXレコードのルックアップを行い、判明した IPアドレスへ向かってメールを送る。デフォルトリレーを経由して送信する場合にも、MXレコードのルックアップは行われ、レコードが存在しなければ送信/リレーは失敗となる。これがスタティックでないルートである。それに対して、MX検索を行わせないのがスタティックルートだ。

Sendmail のスタティックルート定義は、通常、以下のように書かれている;

STATIC    hoge.cxm    smtp:[gateway.hoge.cxm]
ESTATIC chome.cxm smtp:[mailsv.chome.cxm]
STATIC
第2パラメータに指定したドメインのサブドメインも含める。 Postfix での書き方にたとえれば、
hoge.cxm
.hoge.cxm

ということになる。
ESTATIC
STATIC の反対で、サブドメインは含めない。つまり user@some.chome.cxm という宛先メールアドレスだった場合はこのスタティックルートの対象とはならない。
smtp:[gateway.hoge.cxm]
`smtp' メーラーを使用して gateway.hoge.cxm へ送る。[] は DNS による名前解決 (MXでなく Aレコード検索) を抑止する。