メール環境を移行した結果、 spam フィルターを、 Mew がサポートしてるからという理由で使っていた bogofilter から SpamAssassin に移行したのです。が、特性の問題だと思うんだけど、そのままでは SpamAssassin が bogofilter に比べて spam 判定が甘い! ということで俺好みの判定が出来るように頑張ってみました。
まずは spam を学習させないと、ということで調べたら sa-learn というコマンドをウチの環境ではメールサーバー上で使うみたい。こんなこともあろうかと今まで受信してきた spam は残してあるので、それを sa-learn に spam として食わせて、あとは inbox に残ってるメールを ham として食わせればおっけーかな、と試そうとしたら、そもそもサーバー上の Maildir は _dovecot にしか読み書き権限がないので一般ユーザー権限で shell から読み込ませることは出来ないという罠が仕組まれていました。
仕方が無いのであんまりやりたくないんだけど、こんな感じ
sudo -s sa-learn --showdots --spam --nosync /Server/Mail/Data/mail/XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX/.bogofilter/001
これである程度なんとかなるかなー、と思ったら相変わらず SPAM が inbox に配送されてくる。うーん? と思ってログを漁ってみたら
Aug 11 06:01:52 flora org.amavis.amavisd[33945]: bayes: cannot open bayes databases /var/amavis/.spamassassin/bayes_* R/O: tie failed: Permission denied
root で spam/ham を学習させたので、 _amavis に DB の読み書き権限がないので学習させた意味が無いという酷い展開でした…。仕方ないので文句言われた /var/amavis/.spamassassin を _amavis に chown して学習を継続。そしたら一時的にマシになったんだけど、どっかのタイミングで精度が落ちちゃう。んー、と思ったらどっかのタイミングで /var/amavis/.spamassassin の所有者が root に戻っちゃって、上で出ていたのと同じエラーが起きちゃっていたのでした…。どのタイミングで所有者が変わるか分からないけど、こんなの監視してられない。だったら! ということで覚えたての launchd にお任せすべく、こんな plist を書いてみました。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>jp.hyrule.flora.bayes_toks</string>
<key>ProgramArguments</key>
<array>
<string>chown</string>
<string>_amavisd</string>
<string>/var/amavis/.spamassassin/bayes_toks</string>
</array>
<key>WorkingDirectory</key>
<string>/var/amavis</string>
<key>WatchPaths</key>
<array>
<string>/var/amavis/.spamassassin/bayes_toks</string>
</array>
</dict>
</plist>
赤字の部分がキモで、指定したファイルに変化がある度にプログラム(この場合は chown )が動くようです。これを仕掛けて以降 DB の所有者が変わることによるエラーは出なくなった様子。
ちなみに Apple 推奨の spam 学習方法は junkmail と notjunkmail というアカウントを作って、そこに spam や ham を送るというもの、で /private/etc/mail/spamassassin/learn_junk_mail.sh が呼ばれてるみたい。中身を確認したらやっぱり sa-learn を呼んでいるんだけど、
# Has the junk-mail user account been created if [ -d "$JUNK_MAIL_PATH" ] then echo "Learning what is junk mail" find "$JUNK_MAIL_PATH/cur" "$JUNK_MAIL_PATH/new" -type f -print | while read f ile do echo "--- sudo -u _amavisd $SA_LEARN_PATH --dbpath $DB_PATH --spam --no-sync < $file" sudo -u _amavisd $SA_LEARN_PATH --dbpath $DB_PATH --spam --no-sync < "$file" > /dev/null done fi
という具合に sa-learn 自体は _amavis に実行させているので、俺も最初っからこーやるべきだったんでしょう(苦笑)
学習させたから、これでバッチリ、と思ったんだけど、相変わらず spam は SpamAssassin をすり抜けて inbox に配送されてきます。Server Admin.app の迷惑メールの最小スコアは最強に近い 5 に設定しているのになんでー、とすり抜けてみたメールを確認したところ
X-Spam-Status: No, score=4.167 tagged_above=2 required=5 tests=[BAYES_99=3.5, LOTS_OF_MONEY=0.001, SPF_SOFTFAIL=0.665, WEIRD_QUOTING=0.001] autolearn=no
と。
つまりせっかく迷惑メールを学習させて、学習結果からほぼこれは spam ですよ、という結果が出ているのにも関わらず spamassassin は学習結果だけを利用して spam 判定をしていない、のでこんな結果になっていたという。
どーしたもんか、とググったら SpamAssassin – TachTrac に俺が知りたかった設定が載っていたので、この score をパクってみたところ、よーやく spam がすり抜けないよーになったのでした。長かった…