以下では, procmail を用いた メール配送に関して記している.
なお, ここでは 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) でのパッケージから提供される コマンド群である.
以下に手順の概要を記す
個別判定が行われる. フォーマットは以下の通り. $SPAM_ADD_PROBAB に 条件に応じた数値 (-1.0 〜 1.0) を, $SPAM_ADD_CHECKER に条件判定 の略称を与える.
#
:0 [フラグ]
* [判定条件]
{
    SPAM_ADD_PROBAB=0.1                # 条件に応じた数値 -1.0 〜 1.0
    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`
}$SPAM_ADD_PROBAB の値を整形して X-Spam-Probability-Plus ヘッダに, $SPAM_ADD_CHECKER の値を整形して X-Spam-Check ヘッダに書き込む.
$SPAM_ADD_PROBAB の値は以下のように整形される. 1.0 以上のものを 1.0 に, 0.0 以下 (マイナスのものも) を 0.0 に, ".3" のように なっているのを "0.3" とするようにしている.
#
: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./'`
}X-Spam-Probability-Plus ヘッダの値から, スパムかどうかの最終判定 を行い, スパムなものは rcvstore で spam フォルダへ移動する. 以下の例では 0.8 〜 1.0 をスパムとして処理している.
# :0: $LOCKFILE * ^X-Spam-Probability-Plus: *(1|0\.[89]) | $RCVSTORE +spam
##################################################
#== 初期設定
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:   |