.procmailrc - メール振り分け


.procmailrc は procmail (メール振り分けプログラム) の設定ファイルです。 メール転送ももちろんできます。.forward 単体で使用するよりもこちらを利用したほうが高機能です。 .forward のページを軽く見ておきましょう。

まず procmail.forward から起動しなければいけません。 .forward に以下のように書いておきます。

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

[id] のところには自分のユーザ ID を書いてください(exit 75 #s1080134 のように)。.forward が起動されたら、 このコマンドが実行されることになります。これ以外の文は消しておき、すべて procmail の ほうで処理させましょう。

Table of Contents

サンプル Edit

簡単な例としては、以下のように書きます。

PATH=$HOME/bin:/usr/bin:/bin:/usr/local/bin:/usr/ucb:/usr/bsd
LOGFILE=$HOME/Mail/procmail.log
MAILDIR=$HOME/Mail/
:0
*^From: .*spam.*|^From: .*uzai.*
/dev/null
:0 c
*^Subject: .*lectures.*
lectures/.
:0 c
*!^From: .*keitai@keitai.com.*
! keitai@keitai.com
:0
*^Subject: .*command.*
| command

では、この例を解説していきます。これぐらい理解していれば十分使えると思います。

環境変数設定 Edit

この例では、1行目から3行目で環境変数の設定をしています。

PATH=$HOME/bin:/usr/bin:/bin:/usr/local/bin:/usr/ucb:/usr/bsd

パスを通しています。スクリプト内で指定したディレクトリ以下のコマンドは ディレクトリ名を省略して書くことができるようになります。

LOGFILE=$HOME/Mail/procmail.log

procmail のログファイルの指定です。ログがいらないという人は消してもいいです。が、 あったほうがいいと思います。

MAILDIR=$HOME/Mail/

メールディレクトリの指定です。

レシピの書き方 Edit

procmail では処理の部分をレシピと呼びます。ではレシピの書き方を説明していきます。 基本的なフォーマットは以下のようになります。

:0 [flags] [ : [locallockfile] ]
* <zero or more conditions (one per line)>
<exactly one action line>

1行目の :0 がレシピの始まりを意味します。2行目の condition は * で始まります。正規表現が使えます。 3行目の action には処理を書きます。 処理は,メールの転送,リファイル,コマンド起動 の 3種類あります。 レシピにマッチしなかったメールは通常のメールスプールに追加されます。 通常のメールスプールというのは普通の人なら ${HOME}/Mail/inbox ディレクトリです。 xyoubin が反応するディレクトリです。

リファイル、消去 Edit

例えば上の例の

:0
*^From: .*spam@spam\.com.*|^From: .*uzai.*
/dev/null

spam@spam.com という文字列を含むメールアドレス、 または uzai という文字列を含むメールアドレス から来たメールを /dev/null にリファイル、つまり消去ということをします。

この /dev/null の部分を lectures/. のようにすると、MAIRDIR 以下の lectures/ ディレクトリ以下にメールファイルを移動します。

正規表現の利用 Edit

もう少し詳しく説明します。 ^ は正規表現では、先頭という意味を持ちます。 . は正規表現では任意(すべて)の文字、* は直前の文字の繰り返しという意味をもちます。 つまり .* で任意の文字列ということになります。 また、. は特別な意味をもつので、. という文字そのものにしたいときは \. のように書きます。 実際メールヘッダの From 行はメールアドレスだけでなく、名前が書かれることもあるので メールアドレスを含む。という条件にしたほうがうまくマッチします。 そして、メールのヘッダにその条件

^From: .*spam@spam\.com.*

にマッチする行があれば、真ということになります。

または Edit

:0
*^From: .*spam@spam\.com.*|^From: .*uzai.*
/dev/null

| は "または" という意味です。| の左にスペースをいれるとそのスペースにマッチ しなければならなくなるので、入れないようにしましょう(右側はたぶんOK)。

かつ Edit

また、"かつ" にしたい場合は

:0
*^From: .*spam@spam\.com.*
*^From: .*uzai.*
/dev/null

のように書きます。実際 From の条件を二つ書くことはないでしょうけれども。

否定 Edit

:0 c
*!^From: .*keitai@keitai\.com.*
! keitai@keitai.com

2行目のような ! は否定の意味になります。 つまり、keitai@keitai\.com 以外からきたメールなら次のアクションを行います。

転送 Edit

:0 c
*!^From: .*keitai@keitai\.com.*
! keitai@keitai.com

3行目の ! というアクションは転送を意味します。, で区切れば複数指定が可能です。

c フラグ Edit

:0 c
*^Subject: .*lectures.*
lectures/.

これは Subject に lectures という文字列を含むメールを MAILDIR 以下の lectures/ ディレクトリ にリファイルします。 このレシピで重要なのは :0 c の c です。この c というフラグをつけると メールのコピーを作成します。つまり、マッチしたレシピの処理をされつつ、 コピーが作成され、そのコピーが次のレシピへとわたっていきます。

コマンド実行 Edit

:0
*^Subject: .*command.*
| command

ここで重要なのは3行目の | です。これでコマンドの実行を行えます。 入力はちょうどメールの内容をパイプで渡したような形になります。 通常は、formail コマンドで返信先を編集し、それを sendmail で送信するなどして、 自動返信させたりします。

書き方の応用 Edit

書き方の応用として、

:0
*^Subject: test
{
   :0 c
   *<1000
   ! hoge@hogehoge.or.jp
   :0 c
   test/.
}

のような書き方もあります。

*^Subject: test

にマッチしたメールが {} 内のレシピに渡されます。 ちなみに *<1000 というのはメールの容量が 1000 バイト以下ならばという意味です。 この場合、外側のレシピに c フラグをつけてしまうと、 外でも内でもコピーされてしまい、2つに増えてしまうので注意しましょう。 外側に c を付けないのがコツです。

メールスプール(xyoubin,xbiff) Edit

また、実際メールスプールに渡さないと、xyoubin や xbiff などが反応したないため、 自分は

:0 c
* ^Subject: test|^Subject: jikken
test/.
:0 c
*^Subject: hoge
hoge/.
:0 c
*!^Subject: test
*!^Subject: jikken
*!^Subject: hoge
else/. 

のようにすべてに c フラグをつけてメールスプールに送るようにしています。 マッチしたもの、マッチしなかったものの区別がつかなくなるので、 否定 (!) を使って、マッチしなかったものすべてを else/. に格納しています。 もっと良い方法はないものなのでしょうか?

メールループに注意 Edit

メールがループしないように気をつけてください。 例えば、.procmailrc の記述を変えたらテストメールを送って、ログファイルを確認するとか、 ループしてしまったら、一時的に

% mv ~/.procmailrc ~/.procmailrc.bak

のようにファイル名を変更して処理しないようにするとかしましょう。

参考 Edit

フラグや条件記号などの一覧は、 procmailを利用したメールの自動処理 を見るといいと思います。レシピサンプルも多数あります。 また、自動返信などについては formail について学んでおくといいでしょう。 formail のオプション を見るといいと思います。

spam 避けレシピ(暫定) Edit

spam 避け(あるいはウイルスメール避け)レシピの案を…。

# まともでない Content-Type
:0:
* ^Content-Type:.*(text/html|DEFAULT_CHARSET)
/dev/null
# 何かのワームがつける
:0:
* ^-path:.*
/dev/null
:0
* ^Content-Type:.*multipart/alternative;
{
   # テキストが HTML パートしかない
   :0 B
   * ^Content-Type:.*text/html;
   * ! ^Content-Type:.*text/plain;
   /dev/null

   # 不正な charset
   :0 B
   * ^Content-Type:.*charset="?iso-(1111|2222|3333|4444|5555|6666|7777|8888|9999|0000)
   /dev/null
}

xrea