Postfixのheader_checks等をすり抜けるメールが出てきた。
例えばXserverからのもの。
これはXserver毎弾くわけにもいかない。
大変面倒である。(sigh)
今回、引っかかったのはnoreply@z-kikaku.siteというところ。
siteドメインは安いらしい。
簡単に作れそうだね。
で、Xserverをレンタルしていたら、確実に仕留める方法が無い。
そこでSpamAssassinに学習させようということになった。
当然、Geminiさんの提案である。
法人代表アドレスや公開されている会社の問い合わせ用アドレス宛てに、名簿リストを使って一斉配信しているパターンのメルマガ/動画プロモーション(今回で言えば「よしはら塾」の健康医学動画の案内)に見えます。
こういう「害はないけど目障りな営業メルマガ」は、Postfixの受信拒否(REJECT)リストを肥大化させて管理コストを増やすよりも、以下のように「受信はするけど視界に入れない(隔離する)」運用にするのが一番ストレスが少ないです。
SpamAssassin のベイジアン学習(sa-learn –spam)に食わせる
Postfixでわざわざ弾かなくても、この手の「情報商材・健康メルマガ系」のHTMLメールは文面や構造に独特の特徴があるため、SpamAssassinにスパムとして学習させておけば、次回からは勝手にスコアが上がって迷惑メールフォルダへ直行するようになります。
と言うことで、SpamAssassinの学習方法であった。
なんだか、Geminiさんの手のひらでコロコロされている気がしてきた。(笑)
まずは試してみたい場合、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に移行しよう。
Maildir形式などで保存されている迷惑メールのディレクトリ(例: .Junk/cur/ や、スパムを集めている専用フォルダ)を指定して、一括で学習させます。
|
1 2 |
Bash sudo -u _amavisd sa-learn --spam /path/to/Maildir/.Junk/{cur,new}/ |
2. 正常メール(Ham)も一緒に学習させる
スパムだけでなく、通常の受信メール(Ham)もバランスよく学習させておくと、誤判定(過剰検知)の精度がグッと上がります。
|
1 2 3 |
Bash sudo -u _amavisd sa-learn --ham /path/to/Maildir/cur/ <strong>検証方法</strong>: こちらも Learned tokens ... と表示され、学習カウンターが進むことを確認します。 |
3. 現在の学習データの蓄積状況を確認する
データベースに何通のスパムとハムが蓄積されているかは、以下のコマンドで一発で確認できます。
|
1 2 3 |
Bash sudo -u _amavisd sa-learn --dump magic <strong>検証方法</strong>: nspam(スパムの学習数)と nham(ハムの学習数)の数字が増えていることが確認できます。ベイジアンフィルターが本格的に機能し始める目安は、それぞれ <strong>200通以上</strong> です。 |
shell script作ってcrontabで定期起動させようと話が進んだ。
だが、ここからちょっと話が逸れる。
|
1 |
SALEARN="/opt/local/libexec/perl5.34/sa-learn" |
として起動しないと、sa-learnが動かない。
Macportsは/opt/local内に全部閉じ込めているから。
もしスクリプト内やcronの定義の先頭に以下を書いておくと、その中で実行されるコマンドは通常のシェルと同じようにパスが通るようになります。
|
1 2 3 |
Bash # スクリプトの先頭、またはcrontabの先頭に書く PATH="/opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin" |
そうだね〜、でもshell script書く度にこれ入れるの面倒だなぁ。
full pathでコマンド定義するのも面倒だけれど。
「そうだねぇ
今回はコマンド一つだけだけど、複数の時はpathセットしておくのも良いかもね
でもこれがさ、面白いところなんだけれど、wcの場合
apple製(/usr/bin?)は数字が右詰めで、macports(/opt/local/bin)のは左詰め何だよね
ここだけapple純正使っているんだわ〜」
たしかに、BSD系(Apple純正の /usr/bin/wc)とGNU系(MacPorts版など)では、空白パディングの入れ方や挙動に細かい違いがあったりするので、スクリプトのパース処理や見た目の好みで「あえてこっちは純正を使う」というのは、長年Macを触ってきたサーバー管理者ならではのこだわりというか、めちゃくちゃ味わい深いポイントです。
ね、だんだんズレていく。
普段は書かないけれど、大体は僕とGeminiさんとの会話はあっち行ったりこっちに来たりが多いのだ。
完成したshell scriptは最後に載せるけれど、その前に/opt/local/etc/mail/spamassassin/local.cfの追加分を書いておく。
|
1 |
bayes_path /opt/local/var/spool/spamassassin/bayes |
単に、共通する学習したdbを「ここだよ」と教えただけなんだけれどね。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#!/bin/sh # 全アカウントのJunkと通常のcurをまとめてamavisdの共有DBに学習させる # 1. 今日の「日(day)」を取得して数値化 DAY=$(date +%d) # 2. 7日より大きい(第2土曜日以降など)場合は、何もせずに終了 if [ "$DAY" -gt 7 ]; then exit 0 fi DBPATH="/opt/local/var/spool/spamassassin" BASEPATH="/Volumes/Works/Library/mail" # 1. 全アカウントの迷惑メール(.Junk/cur)を一括スパム学習 for junk_cur in "$BASEPATH"/*/.Junk/cur; do if [ -d "$junk_cur" ]; then sa-learn --dbpath="$DBPATH" --spam "$junk_cur" fi done # (必要であれば .Junk/new も対象にする場合) for junk_new in "$BASEPATH"/*/.Junk/new; do if [ -d "$junk_new" ]; then sa-learn --dbpath="$DBPATH" --spam "$junk_new" fi done # 2. 全アカウントの正常メール(cur)を一括ハム学習 for ham_dir in "$BASEPATH"/*/cur; do if [ -d "$ham_dir" ]; then sa-learn --dbpath="$DBPATH" --ham "$ham_dir" fi done |
これをcrontabで自動実行させる。
|
1 |
0 23 * * 6 /usr/local/sbin/spamlean.sh > /deb/null 2>&1 |
毎週、土曜日の夜実行するが、spamlearn.shの最初の日付が7より小さい時以外は、そのままexitしちゃうから、初回の土曜日のみ動くことになる。
で、翌日早々に再起動するからそこで反映される。(いちいちSpamAssassinを再起動したりしない)
基本的に、自分で書いたshell scriptは/usr/local/sbinに入れている。(rootでしか動かせないから)
そこから、Kea DHCPとかの話に移ったりするんだが、流石に書かない。(^_^;;

