- 论坛徽章:
- 1
|
SpamAssassin的中文垃圾邮件过滤规则集
這一段較少人研究,我給您解釋一下好了:
Mail 的 Subject 或 Body 編碼有三種,
第一種就是原型,什麼都不編碼 "酷!學園"
第二種是 Mime 以 base64 以 6 bit 來編碼,base32 以 5 個 bit ,但Mail 都是用 base64
如: =?big5?B?jjfkdoooo=?= (這一段mime 我是隨意打的)
Ex:
- BIG5 code = Mime Base64
- 104速配快遞 =?big5?B?MTA0s3SwdKfWu7w=?=
- Re:104速配快遞 =?big5?B?UmU6IDEwNLN0sHSn1ru8?=
- 我溜104速配快遞 =?big5?B?p9q3yDEwNLN0sHSn1ru8?=
- Re:我溜104速配快遞 =?big5?B?UmU6IKfat8gxMDSzdLB0p9a7vA==?=
- Fw:我溜104速配快遞 =?big5?B?Rnc6IKfat8gxMDSzdLB0p9a7vA==?=
复制代码
你會發現這幾個的 mime patten 天差地遠...所以 procmailrc 中的 patten 就不是
* ^Subject: 酷!學園 ---->;有90%以上的機會會錯掉
* ^Subject: =?big5?B?jjfkdoooo=?= --->;有75%的機會會錯掉,不過可以取巧,將四種可能都設上
Mime 的編碼在 8bit email subjext 裏面我覺得大概佔到近八成左右,所以要多再注意
第三種稱為 QP (quote-print) , 直接還原 binary code 你有時會看到 =A3=BB...就是了
# 這是還原 encoding 的一段 perl 程式:
- #!/usr/bin/perl
- $sub=$ARGV[0];
- if ($sub=~ /=\?\S+\?\l(\S)\?/) {
- if ($1 =~ /[Qq]/) {
- $sub=decode_qp($sub);
- }
- elsif ($1 =~ /[Bb]/) {
- $sub=decode_base64($sub);
- }
- }
- elsif ($sub=~ /=[a-fA-F0-9][a-fA-F0-9]/) {
- $sub=decode_qp($sub);
- }
- $subject.=$sub;
- print $subject;
- sub decode_qp {
- my($string) = @_;
- @buffer=split(/\?/,$string);
- $string = $buffer[3] if ($buffer[3] ne "");
- $string =~ s/=([\da-fA-F]{2})/pack("C", hex($1))/ge;
- $string =~ /\?=(.*)/;
- $string =~ tr/_/ /;
- $buffer[4]=~s/^=//;
- $buffer[0]=~s/=$//;
- $string="$buffer[0]$string$buffer[4]";
- return($string);
- }
- sub decode_base64 {
- my($string) = @_;
- my($string2);
- @buffer=split(/\?/,$string);
- $string = $buffer[3] if ($buffer[3] ne "");
- $string =~ s/=+$//;
- $string =~ tr|A-Za-z0-9+/| -_|;
- while($string =~ /(.{1,60})/gs) {
- my($string3) = chr(32+length($1)*3/4);
- $string2 .= unpack("u",$string3 . $1 );
- }
- $buffer[4]=~s/^=//;
- $buffer[0]=~s/=$//;
- $string2="$buffer[0]$string2$buffer[4]";
- return($string2);
- }
复制代码
假設就叫 /etc/parser_subj , 並 chmod 755
/etc/parser_subj $SUBJ 就可以取出原來的中文字了
(巳考慮 8bit/Mime/QP 問題,直接用就可以,但這只 for BIG5, GK2323 上面程式自己改就可以了)
存放 SPAM_PATTEN 的 mysql desc:
- +----------+--------------+------+-----+---------+----------------+
- | Field | Type | Null | Key | Default | Extra |
- +----------+--------------+------+-----+---------+----------------+
- | SN | int(20) | | PRI | NULL | auto_increment |
- | USERNAME | varchar(16) | | MUL | | |
- | PATTEN | varchar(128) | | MUL | | |
- | CNT | int(20) | | | 0 | |
- +----------+--------------+------+-----+---------+----------------+
复制代码
所以,針對中文主旨問題,整個 procmail 方案為:
- VERBOSE=on
- LOGFILE=$HOME/procmail/procmail.log
- PATH=/bin:/usr/bin:/usr/local/bin
- LANG=zh_TW.Big5
- LC_ALL=zh_TW.Big5
- SUBJ=`formail -zxSubject: `
- SUBJ=`/etc/parser_subj "${SUBJ}"`
- :0 hD
- * ! ^From: .*mydomain.net.*
- * ! ^Received: .*192\.168\..*
- {
- :0 fh
- | ( patten=`echo "select concat(PATTEN,\" \") from SPAM_PATTEN where USERNAME='$LOGNAME' and instr('$SUBJ',PATTEN)"|$MYSQL | grep -v 'PATTEN'`; \
- if [ ${#patten} -ne 0 ] ; \
- then formail -A "Spam: $patten"; \
- echo "insert into SPAM(MAIL_FROM,RCPT_TO,SUBJ,FILE_NAME,MAIL_TYPE,USERNAME,REASON,PATTEN ) values('$FROM','$TO','$SUBJ','$FILE',1,'$LOGNAME','符合特定字串','$patten')" | $MYSQL; \
- fi; \
- for p in $patten;do \
- echo "update SPAM_PATTEN set CNT=CNT+1 where USERNAME='$LOGNAME' and PATTEN='$p'"|$MYSQL; \
- done);
- :0
- * ^Spam: .*
- /dev/null
- }
复制代码
PS1: 以上皆是 for BIG5 環境來說明
因為我要計數,要存記錄,所以程式為稍長,若只要判斷到就直接導到檔案或 null, 就只要兩行就好了
- :0 hD
- * ! ^From: .*mydomain.net.*
- * ! ^Received: .*192\.168\..*
- * $(echo "select concat(PATTEN,\" \") from SPAM_PATTEN where USE
- RNAME='$LOGNAME' and instr('$SUBJ',PATTEN)"|$MYSQL | grep -v 'PATTEN')
- /var/spool/mail/spam_patten
复制代码
了解原理(Mail Encoding/Format), 及 procmailrc 功能,要做什麼都很簡單,個人覺得
procmail 妙用很多,可以發揮許多 email to program 的功能 |
|