[ トップページ / メモ書きリスト ]

procmail レシピ


  1. 概要
  2. bsfilter と procmail 自体の条件判定を組み合わせる方法

概要

以下では, procmail を用いた メール配送に関して記している.

なお, ここでは procmail の設定に関する基本的な情報は割愛している. 以下のサイトを参照して欲しい.

bsfilter と procmail 自体の条件判定を組み合わせる方法

この procmailrc では bsfilter を使用し, そのオプションとして --insert-probability を使用することで X-Spam-Probability ヘッダに スパムである確率を 0.0 〜 1.0 で書き出す. さらに その値に個別の条件の判定による値を加算し, その合計値でスパムか どうかを判断している.

bsfilter を利用するに際しては bsfilter / bayesian spam filter / ベイジアン スパム フィルタ を参照した. 自分のメモ書きは bsfilter を mew3.3 で使おう!!!.

個別条件判定に関しては michi さんの procmail メモ を参照した.

メールのフォルダ格納には rcvstore を用いている. 基本的に振り分けるだけなら rcvstore を使う必要は無いので 普通に procmail 標準の書き方でメールを振り分けると良いだろう. (筆者は Mew 3.3 でスパム処理と未読メールの管理 を行っているため, rcvstore を用いているだけである).

依存するコマンド

いろいろごちゃごちゃと (余計に) 凝っているため, 下記のコマンド群が必要である. なお, 動作確認しているのは, Debian GNU/Linux 3.1 (sarge) でのパッケージから提供される コマンド群である.

動作の概要

以下に手順の概要を記す

.procmailrc

##################################################
#== 初期設定
SHELL=/bin/bash
PATH=/bin:/usr/bin:/usr/local/bin
ADDRESS=hogehoge@mailserver.foo.jp
  # ログファイル (ディレクトリを作らなければ生成されない)
LOGFILE=$HOME/.procmail/`date +%Y%m`.log
  # ログを詳細に 詳細: on , 非詳細: off
VERBOSE=off
LOCKFILE=$HOME/.procmail/.lockfile

#=== rcvstore を利用する際の設定
# * rcvstore 形式でメールを格納する際のコマンド (mh-biff などで未読管理
#   を行う際に便利) この場合, メールディレクトリのパスは ~/.mh_profile
#   で管理される. 詳しくは rcvstore(1) および mh_profile(5) を参照.
RCVSTORE=/usr/lib/mh/rcvstore
RCVDEFAULT=+inbox

#=== bsfilter を利用する際の設定
BSFILTER=/usr/bin/bsfilter

#=== メール格納に用いられる変数
# * 上記 rcvstore を用いる場合は無効であるため注意
MAILDIR=$HOME/Mail
DEFAULT=$MAILDIR/inbox/.
# Mail ディレクトリ方式
  # DEFAULT=$MAILDIR/inbox/.
# Maildir/new などの方式
  # DEFAULT=$MAILDIR/inbox/
# Mailbox 方式
  # DEFAULT=$MAILDIR/inbox


##################################################
#== ヘッダを整形
#
#:formail -z の解説
#  ヘッダ名と値のあいだに空白文字を入れる。
#  ヘッダ名だけで中身がないヘッダは削除される。
#  また、-x で値を取り出すときに値の前後の空白文字を省く。
:0 f
|formail -z


##################################################
#== SPAM 対策用の iso-2022-jp のデコード
#
# サブジェクトがエンコードされていたらデコードして制御文字等を削除
# エンコードされていない場合にも備える
#
# from http://www.jaist.ac.jp/~fjt/procmail.html
:0
* ^Subject:\/.*
{
    :0
    * ^Subject:.*iso-2022-jp
    DECODED_SUBJECT=|echo "$MATCH"|nkf -meZ1|sed 's/[[:space:]]//g'
    :0 E
    DECODED_SUBJECT=|echo "$MATCH"|nkf -eZ1|sed 's/[[:space:]]//g'
}

##################################################
#== bsfilter によるスパム確率の判定
#
# http://bsfilter.org/#started
#
# X-Spam-Flag: 、 X-Spam-Probability: ヘッダを追加する.
#
# :$SPAM_PROBAB
#   スパムである確率. bsfilter の判定にプラスして
#   下記の個別条件判定による加算も加える
#
# :$SPAM_CHECKER
#   bsfilter による判定値と他にどのような個別条件判定に
#   ヒットしたかを格納
#
:0 fw: $LOCKFILE
| $BSFILTER --pipe --insert-flag --insert-probability

:0
* ^X-Spam-Probability:\/.*
{
    SPAM_PROBAB=$MATCH
}
:0 E
{
    SPAM_PROBAB=0.0
}

:0
{
    SPAM_PROBAB=`echo "scale=4 ; $SPAM_PROBAB + 0.0" | bc`
    SPAM_CHECKER=`echo bsfilter=$SPAM_PROBAB`
}


##################################################
#== 個別条件によるスパム確率の判定
#
#=== jp ドメイン以外からの HTML メールは撃墜
# 撃墜率:高
# 誤爆率:低
:0 HB
* ! ^From: .*\.jp
* \<html\>
{
    SPAM_ADD_PROBAB=0.1
    SPAM_ADD_CHECKER=html_mail
    SPAM_CHECKER=`echo "$SPAM_CHECKER","$SPAM_ADD_CHECKER=$SPAM_ADD_PROBAB"`
    SPAM_PROBAB=`echo "scale=4 ; $SPAM_PROBAB + $SPAM_ADD_PROBAB" | bc`
}

#=== Subject が [SPAM で始まるものは撃墜
# 撃墜率:中
# 誤爆率:中
#
# 環境によってヘッダに SPAM がつきやすい人は除外
:0
* $DECODED_SUBJECT ?? ^\[SPAM:Low
* ! ^From: .*foo.*
{
    SPAM_ADD_PROBAB=0.1
    SPAM_ADD_CHECKER=spam_subject_low
    SPAM_CHECKER=`echo "$SPAM_CHECKER","$SPAM_ADD_CHECKER=$SPAM_ADD_PROBAB"`
    SPAM_PROBAB=`echo "scale=4 ; $SPAM_PROBAB + $SPAM_ADD_PROBAB" | bc`
}

:0
* $DECODED_SUBJECT ?? ^\[SPAM:Med
{
    SPAM_ADD_PROBAB=0.3
    SPAM_ADD_CHECKER=spam_subject_med
    SPAM_CHECKER=`echo "$SPAM_CHECKER","$SPAM_ADD_CHECKER=$SPAM_ADD_PROBAB"`
    SPAM_PROBAB=`echo "scale=4 ; $SPAM_PROBAB + $SPAM_ADD_PROBAB" | bc`
}

:0
* $DECODED_SUBJECT ?? ^\[SPAM:Hig
{
    SPAM_ADD_PROBAB=0.5
    SPAM_ADD_CHECKER=spam_subject_high
    SPAM_CHECKER=`echo "$SPAM_CHECKER","$SPAM_ADD_CHECKER=$SPAM_ADD_PROBAB"`
    SPAM_PROBAB=`echo "scale=4 ; $SPAM_PROBAB + $SPAM_ADD_PROBAB" | bc`
}


#=== 逆引きできないホストを中継してきたメールは撃墜
# 撃墜率:高
# 誤爆率:低
:0
* ^Received: .*\(unknown \[
{
    SPAM_ADD_PROBAB=0.2
    SPAM_ADD_CHECKER=from_unknown_host
    SPAM_CHECKER=`echo "$SPAM_CHECKER","$SPAM_ADD_CHECKER=$SPAM_ADD_PROBAB"`
    SPAM_PROBAB=`echo "scale=4 ; $SPAM_PROBAB + $SPAM_ADD_PROBAB" | bc`
}


#=== エンドユーザからのメールは撃墜
# 下位ドメインに記号で区切られた数字を含む
:0
* ^Received: from .*\(.*[0-9][^0-9\.][0-9].*\.[^\.]+\.[a-z].*\[
{
    SPAM_ADD_PROBAB=0.2
    SPAM_ADD_CHECKER=from_EndUser_[Type_1]
    SPAM_CHECKER=`echo "$SPAM_CHECKER","$SPAM_ADD_CHECKER=$SPAM_ADD_PROBAB"`
    SPAM_PROBAB=`echo "scale=4 ; $SPAM_PROBAB + $SPAM_ADD_PROBAB" | bc`
}


#=== 数字が5個以上並ぶ
:0
* ^Received: from .*\(.*[0-9][0-9][0-9][0-9][0-9].*\[
{
    SPAM_ADD_PROBAB=0.2
    SPAM_ADD_CHECKER=from_EndUser_[Type_2]
    SPAM_CHECKER=`echo "$SPAM_CHECKER","$SPAM_ADD_CHECKER=$SPAM_ADD_PROBAB"`
    SPAM_PROBAB=`echo "scale=4 ; $SPAM_PROBAB + $SPAM_ADD_PROBAB" | bc`
}


#=== 下位ドメインに数字(IP アドレス)を含む
:0
* ^Received: from .*\(.*\.[0-9][^\.].*\.[^\.]+\.[^\.]+\.[a-z].*\[
{
    SPAM_ADD_PROBAB=0.2
    SPAM_ADD_CHECKER=from_EndUser_[Type_3]
    SPAM_CHECKER=`echo "$SPAM_CHECKER","$SPAM_ADD_CHECKER=$SPAM_ADD_PROBAB"`
    SPAM_PROBAB=`echo "scale=4 ; $SPAM_PROBAB + $SPAM_ADD_PROBAB" | bc`
}


##################################################
#== SPAM_CHECKER と SPAM_PROBAB の整形とヘッダへの追加
#
:0 f
|formail -A "X-Spam-Check: $SPAM_CHECKER"

:0
{
    SPAM_PROBAB=`echo $SPAM_PROBAB | sed 's/^0$/0.0/' | \
            sed 's/^0*//' | \
            sed 's/^[1-9][0-9]*\.[0-9]*/1.0/' | \
            sed 's/^-.*\.[0-9]*/0.0/  ' | \
            sed 's/^\./0./'`
}

:0 f
|formail -A "X-Spam-Probability-Plus: $SPAM_PROBAB"


##################################################
#== X-Spam-Probability-Plus の数値による判定
#
# 現在は 0.8 以上をスパムと判定
#
:0: $LOCKFILE
* ^X-Spam-Probability-Plus: *(1|0\.[89])
| $RCVSTORE +spam


##################################################
#== DEFAULT へ
# これら全てをくぐり抜けたものは, inbox に送る (rcvstore での場合)
# rcvstore を用いない場合は, 何も記述しなければ DEFAULT へ
# 送られる.
:0 w: $LOCKFILE
| $RCVSTORE $RCVDEFAULT

Last Updated: 2005/07/04, Since: 2005/07/04 mailto: morikawa_email