SpamAssassinに学習をさせよう

Postfixのheader_checks等をすり抜けるメールが出てきた。
例えばXserverからのもの。
これはXserver毎弾くわけにもいかない。
大変面倒である。(sigh)

今回、引っかかったのはnoreply@z-kikaku.siteというところ。
siteドメインは安いらしい。
簡単に作れそうだね。
で、Xserverをレンタルしていたら、確実に仕留める方法が無い。

そこでSpamAssassinに学習させようということになった。
当然、Geminiさんの提案である。

まさに「危険なフィッシングではないけれど、頼んでもいないのに送りつけてくる煩わしいDM(特定電子メール法違反すれすれの未承諾広告メール)」の典型ですね。
法人代表アドレスや公開されている会社の問い合わせ用アドレス宛てに、名簿リストを使って一斉配信しているパターンのメルマガ/動画プロモーション(今回で言えば「よしはら塾」の健康医学動画の案内)に見えます。
こういう「害はないけど目障りな営業メルマガ」は、Postfixの受信拒否(REJECT)リストを肥大化させて管理コストを増やすよりも、以下のように「受信はするけど視界に入れない(隔離する)」運用にするのが一番ストレスが少ないです。

SpamAssassin のベイジアン学習(sa-learn –spam)に食わせる
Postfixでわざわざ弾かなくても、この手の「情報商材・健康メルマガ系」のHTMLメールは文面や構造に独特の特徴があるため、SpamAssassinにスパムとして学習させておけば、次回からは勝手にスコアが上がって迷惑メールフォルダへ直行するようになります。

と言うことで、SpamAssassinの学習方法であった。

Apple Mail(Mail.app)の迷惑メール学習も十分賢いですが、サーバー側でPostfix・Dovecot・SpamAssassinを運用しているなら、sa-learn でベイジアンフィルターを育てるのは管理人としてなかなか楽しい作業です。

なんだか、Geminiさんの手のひらでコロコロされている気がしてきた。(笑)

1. 手動(またはcron)で sa-learn を回すシンプル方式
まずは試してみたい場合、Dovecotのメールボックス(Maildir形式)にある「Junk(迷惑メール)」フォルダの中身を直接 sa-learn に食わせるだけで学習できます。

2. Dovecot の imapsieve プラグインで完全自動化する方式(おすすめ)
「Apple Mailで迷惑メールボタンをクリックした瞬間、裏でサーバーが勝手に sa-learn を叩く」ようにすると、メーラーとサーバーの学習が完全に同期して一気に快適になります。

Dovecot 2.2.24以降(現行のMacPorts版Dovecotなら標準搭載)には imapsieve という機能があり、IMAPクライアント(Mail.appやiPhoneのメールなど)でメールを特定のフォルダに移動したイベントをフックしてシェルスクリプトを走らせられます。

受信トレイ → Junk へ移動した時: 自動的に sa-learn –spam を実行

Junk → 受信トレイ へ戻した時(誤判定の救出): 自動的に sa-learn –ham を実行

これを入れておくと、普段通りMail.appやiPhoneで「迷惑メール」に放り込むだけで、サーバー側のSpamAssassinがどんどん賢くなり、他の端末で受信する前段階からスパムスコアを上げて隔離してくれるようになります。

2番目の方法も興味はあるけれど、覚えこませるのに時間がかかりそうだったので、1番目の方法にすることにした。
何故なら迷惑メールのパターンファイルが山のように残っているから。(消していないんだわ)

暫くは同じファイルを何度も食わせて早期学習させてからDovecotに移行しよう。

1. 迷惑メール(Spam)をまとめて学習させる
Maildir形式などで保存されている迷惑メールのディレクトリ(例: .Junk/cur/ や、スパムを集めている専用フォルダ)を指定して、一括で学習させます。

検証方法: 実行後に Learned tokens 1, messages X-Y のようなメッセージが表示されれば成功です。

2. 正常メール(Ham)も一緒に学習させる
スパムだけでなく、通常の受信メール(Ham)もバランスよく学習させておくと、誤判定(過剰検知)の精度がグッと上がります。

3. 現在の学習データの蓄積状況を確認する
データベースに何通のスパムとハムが蓄積されているかは、以下のコマンドで一発で確認できます。

shell script作ってcrontabで定期起動させようと話が進んだ。
だが、ここからちょっと話が逸れる。

として起動しないと、sa-learnが動かない。
Macportsは/opt/local内に全部閉じ込めているから。

crontabやスクリプト内でPATHを通す書き方
もしスクリプト内やcronの定義の先頭に以下を書いておくと、その中で実行されるコマンドは通常のシェルと同じようにパスが通るようになります。

これを入れておけば、わざわざ $SALEARN のようにフルパス変数を作らなくても、単に sa-learn と書くだけで通るようになります。

そうだね〜、でもshell script書く度にこれ入れるの面倒だなぁ。
full pathでコマンド定義するのも面倒だけれど。

「そうだねぇ
今回はコマンド一つだけだけど、複数の時はpathセットしておくのも良いかもね
でもこれがさ、面白いところなんだけれど、wcの場合
apple製(/usr/bin?)は数字が右詰めで、macports(/opt/local/bin)のは左詰め何だよね
ここだけapple純正使っているんだわ〜」

おぉ、なるほど……!wc コマンドの出力フォーマット(右詰めか左詰めか)にそんな違いがあるとは、すごくマニアックで面白い着眼点ですね!

たしかに、BSD系(Apple純正の /usr/bin/wc)とGNU系(MacPorts版など)では、空白パディングの入れ方や挙動に細かい違いがあったりするので、スクリプトのパース処理や見た目の好みで「あえてこっちは純正を使う」というのは、長年Macを触ってきたサーバー管理者ならではのこだわりというか、めちゃくちゃ味わい深いポイントです。

ね、だんだんズレていく。
普段は書かないけれど、大体は僕とGeminiさんとの会話はあっち行ったりこっちに来たりが多いのだ。

完成したshell scriptは最後に載せるけれど、その前に/opt/local/etc/mail/spamassassin/local.cfの追加分を書いておく。

単に、共通する学習したdbを「ここだよ」と教えただけなんだけれどね。

これをcrontabで自動実行させる。

毎週、土曜日の夜実行するが、spamlearn.shの最初の日付が7より小さい時以外は、そのままexitしちゃうから、初回の土曜日のみ動くことになる。
で、翌日早々に再起動するからそこで反映される。(いちいちSpamAssassinを再起動したりしない)

基本的に、自分で書いたshell scriptは/usr/local/sbinに入れている。(rootでしか動かせないから)
そこから、Kea DHCPとかの話に移ったりするんだが、流石に書かない。(^_^;;

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)