procmail用の.forward設定の源流を探る

今日はお絵描きサボりw


先日書いた技術ネタのブログを読む/書く時に気を付ける5箇条まなめはうすさんに補足されて、かなり大量のアクセスが流入してきているようです。ありがとうございます。(元々、1記事あたり20アクセスがせいぜいな当ブログをどうやって補足できたのかが謎ですが。)

まぁ、そのほとんどは一瞥して帰ってしまったようなので、他の記事も見たくなるぐらい、もっと魅せる文章を書けるよう精進しなければいけませんね。

さて、今日はその記事でちらっと触れた procmail でコピペされつづけているっぽい記述について書いてみます。

procmail と .forward の設定

procmail はメールの振り分け配送を行うMDAです。postfixなどのMTAが procmail を local MDA として設定されている場合は良いのですが、そうではない場合、~/.forward などをいじって、procmail に処理が渡されるよう個人別に設定する必要があります。

~/.forward には、単に、 procmail を起動してメールを渡してもらうように設定すれば良いだけなので、最低限の設定は以下のようになります。

|/usr/bin/procmail

なんだこの設定は?

ところが、ちょっとググってみると、上位の方のサイトのいくつかでは、以下のように書くことを薦めています。

"|IFS=' ' && exec /usr/bin/procmail -f- || exit 75 #username"

これには決まって、注意書きとして「全体のダブルクォーテーションは削っちゃだめ」「先頭の | はパイプ記号」「/usr/bin/procmail は自分の環境に合わせて変えてね」「usernameは自分のユーザー名に書き換えて」の4点が続きます。

さて、これを解読してみましょう。

まず全体を括るクォーテートですが、これは確かに必要です。途中にスペースなどを含む記述をしている場合には必要になります。

次に、IFS ですが、これは internal field separator という、シェルで特別に解釈される変数です。この変数は、他の変数が変数展開される際の挙動なんかに影響します。例えばこんなかんじ。(括弧を使ってサブシェルで実行しておかないと、シェルが汚染されるので注意)

$ ( IFS="e"; TEST="test"; echo $TEST test )
t st test

この変数が適切に設定されていないと、古いSystem V ベースのシステムや、一部のシェルで問題があるようです。おそらく、sendmailの古いバージョンで類似な問題があったのでしょう。しかし、他に変数を使っていないので、いま一つ存在意義がわかりません。

exitの存在も謎です。構成としては "(変数設定) && exec || exit" となっているので、exitが実行されるのは変数設定かexecが失敗した時となります。変数設定は失敗することはないので、execの失敗をトラップしてexitするための設定に見えますが、多くのシェルでは exec は、成功しても失敗してもシェル自体が消滅してしまうので、後続のコマンドが実行されることはありません。 つまり、この exit が実行されることはありえません。

最後の #username の記述に至っては、ただのコメントなので、あっても無くても実行の挙動には影響を与えないはずです。ただ、何も無い所からこの記述が突然発生するとも思えないので、元々は何か大事な意味があったのかもしれません。

こたえあわせ

コメントの記述がどこから発生したのかを探っていくうちに、おそらくこれらの記述の源流と思しきものを、procmail の FAQ の中に見付けました。

"|IFS=' '&&p=/usr/local/bin/procmail&&test -f $p&&exec $p -f-||exit 75#whatever"

Procmail FAQ

procmailが存在するかどうかのテストが増えてますが、殆ど同じですね。これなら、変数pを使っているので IFS の意義も十分ありますし、procmailが無かった場合には test が fail して exit に辿り着くのでexitの意義もなくはないです。

また、#でコメントを付けることについても、詳細な理由の記述があります。

11. Why do I have to insert my login name after the '#' in the .forward or .maildelivery file?
Some mailers `optimise' maildelivery and take out duplicates from Cc:, Bcc: and alias lists before delivery. If two or more persons on such a list would have identical .forward files, then the mailer will eliminate all but one. Adding a `#' with your login name following it will make the .forward files unique, and will ensure that the mailer doesn't optimise away some addresses.

Procmail Frequently Asked Questions

つまり、複数ユーザーが、全く同じ .forward の記述を書いていると、「同じ送り先」だと勘違いして、一部の送り先を削除してしまうような、お馬鹿なメール配送デーモンがいたから。というわけですね。コメントを付けて、全ユーザーでユニークにしておけばそれを防げる、と。

まぁ、そういうわけなので、殆どが昔の環境でのworkaroundだったわけですね。しかも、その一部を誰かが適当に削ってしまったがために、意味不明なworkaroundの断片だけが残ってしまった、という経緯なのでしょう。

結局、私はそんな小細工は要らないので、こう記述して使うことにしました。

"|/usr/bin/procmail -f-"

はじめっから、該当のFAQへのリンクを貼っておいてくれれば、調べまわる必要は無かったのになぁ。