首页 > 学技术 > 技术网文 > Mail服务器 > 正文

[保留] 利用Procmail如何过滤中文的附件


来源 chinaunix.net 酷勤网整理

我所用RH9+Sendmail+IMAP,想利用Procmail来过滤邮件的附档,可是不知为何就是无法过滤中文名的附件,对英文名即可生效。。。。
/etc/procmailrc的正文如下:
:0 B
* ^Content-Type:.*
* ^.*name=.*\.(ppt|exe|com)
/dev/null

请各位高手帮帮忙!



 reddata 回复于:2004-12-21 08:13:30

等了几天尽没有人理我,只好自已先顶一下啦。


 abel 回复于:2004-12-21 12:13:04

還是老話一句,你自己做了什麼功課....還是做等答案.

email MIME/QP decode
取名為 /etc/parser_subj   (mode 755)

#!/usr/bin/perl
    $sub=join(" ",@ARGV);
    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;
    $subject=~s/\'/\\\'/g;
    $subject=~s/\"/\\\"/g;
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);
}



在 procmail 中加入:

LOGABSTRACT=all
LOGFILE=/tmp/procmail.log
tmp=`formail -I "" | sed -e '/Content-Type/,/^$/!d' | grep "filename=" | sed -e 's/.*filename\=\(.*\)\?.*/\1/g'`
ATTACH=`/etc/parser_subj $tmp`

:0
....這裏你自己去試吧...自己做點功課就會了


去看 /tmp/procmail.log 中的東西,就知道用意了


 reddata 回复于:2004-12-22 20:00:52

老大這幾天我為了這個想盡辦法,就是不如人願,本想利用把其轉碼後進進行過濾,可事後此法行不通,搞到最後造成很多用戶的郵件丟失,明天我再看看你給的代碼。。。不管怎麼樣,我還是得謝謝你的幫助。很多時侯遇到困難,就像迷失了一樣,不知從何下手,所以有你這些指引,我想至少可以少走些彎路,不過我也不會光等著別人,自己的事還得靠自己。。。。。


 abel 回复于:2004-12-22 20:04:35

嗯~
這段 code 或你自己加的東西,放在
$HOME/.procmailrc 較好
等你試出來後再移到 /etc/procmailrc

放在 $HOME/.procmailrc 原因只對該 user 有效
放在 /etc 對全 mail server 皆有效.
因為你不能掌握技巧,從自己先實驗起較好

另外,就是你的問題不明確...上面我也只能 .... 帶過
中文檔名, 然後呢 ?


 reddata 回复于:2004-12-23 08:51:32

今天一大早我就把这段CODE加进去了,可是试了几下不行,也不知哪里出了问题,对了老大你那里有没有关于Procmail方面的资料,虽然在网上找了一点,但看完后没什么价值,还是一头雾水没明白。目前我遇到的问题是无法过滤是中文的附件,对于英文却没有问题。以下是我的MSN也是我的电邮地址,欢迎把我加入:guiweizhao@elegance-group.com


 abel 回复于:2004-12-23 17:58:12

嗯~這個問題我們版上討論就可以了,
沒必要私下交流,因為您的問題也可能是日後其他朋友的參考
所以,請見諒

最後,會建議您,學好英文,才可能學好 sendmail
因為中文的 sendmail 資料真的很少
好好努力把 sendmail 附的 cf/README 看完
procmail* 相關的東西看完,
這樣才能提昇實力,用問的有時都太片面化了,見樹不見林


 reddata 回复于:2004-12-24 16:57:11

你说得极对,这不我从上月开始又在啃英文书了,但是在啃之前,能否先帮我把这个问题给解决了,上述的那个编码是否非要手工输入,直接用COPY到一个新文件可否?昨天我就是利用后者COPY进去的,但是还是不行,后来用base64也没有成功。我在/etc/目录下创建了parser_subj,然后把你上述的正文复制进去,接着就是更改procmailrc的文件,把以下这段CODE追加进去。
LOGABSTRACT=all 
LOGFILE=/tmp/procmail.log 
tmp=`formail -I "" | sed -e '/Content-Type/,/^$/!d' | grep "filename=" | sed -e 's/.*filename\=\(.*\)\?.*/\1/g'` 
ATTACH=`/etc/parser_subj $tmp` 

:0 

重启Sendmail后还是不行!


 abel 回复于:2004-12-24 17:48:09

修改 procmailrc 不用 restart sendmail

:0 然後呢 ?

procmail log 說什麼你有注意看嗎 ?


 abel 回复于:2004-12-24 18:48:25

我只看 man page 或官網後學習的結果:


PATH=$PATH
SHELL=/bin/sh
MAILDIR=/var/spool/mail
VERBOSE=yes
LOGABSTRACT=all
SENDMAIL=/usr/sbin/sendmail
LOGFILE=$HOME/procmail/procmail.log
FILE=`echo $HOME`/procmail/mail_folder/mail-`date +%Y%m%d%H%I%S`-`echo $$`.eml
tmp=`formail >; $FILE; chmod 644 $FILE`
tmp=`formail -zxSubject:`
SUBJ=`/etc/parser_subj "$tmp"| sed -e "s/[\$,\(,\),\',\\]//g"`
FROM=`formail -zxFrom:| sed -e 's/.*<\(.*\)>;.*/\1/g'`
SPAMID=`formail -I ""|grep '/sc?id=' | sed -e 's/.*id=\(.*\)/\1/g'`
PTR=`formail -zxReceived:|grep ^from|sed -e 's/.*\[\(.*\)\.\(.*\)\.\(.*\)\.\(.*\)\].*/\4.\3.\2.\1/g'|head -1`
MYSQL="mysql -h procmail.mydomain.net.tw -u abel -pxxxxxxxx procmail"

# 從網頁取回來的信不再過濾
:0 H
* ^X-resend:
/var/spool/mail/$LOGNAME


# 白名單處理
WHITE_LIST=`echo "SELECT WHITE_NAME FROM WHITE_LIST WHERE USERNAME='$LOGNAME' AND instr('$FROM', WHITE_NAME ) or instr('$SUBJ', WHITE_NAME )"| $MYSQL |  tr '\n' '|' ; echo "aaaaaaaazzzzzzzzzggggggggg"`
:0 H
* $($WHITE_LIST)
$ORGMAIL

# 標?#125;中巳帶有 SPAM
:0 HD
* ^Subject: SPAM.*
{
        :0 fw
        | ( echo "insert into SPAM(MAIL_FROM,RCPT_TO,SUBJ,FILE_NAME,MAIL_TYPE,USERNAME,REASON,PATTEN ) values('$FROM ','$TO ','$SUBJ ','$FILE',1,'$LOGNAME','SPAM','標?#125; SPAM')"    | $MYSQL)

        :0
        /dev/null
}

# 發信不為自己單位但  Message-ID 帶自己
:0 HD
* !^From: .*@mydomain.net.tw.*
* !^Received: .*211\.72\.21[0-1]\..*
* ^Message-Id: .*@mydomain.net.*
{
:0 fw
| echo "insert into SPAM(MAIL_FROM,RCPT_TO,SUBJ,FILE_NAME,MAIL_TYPE,USERNAME,REASON,PATTEN ) values('$FROM ','$TO ','$SUBJ ','$FILE',1,'$LOGNAME','發信軟體','Message-ID 為 mydomain')"    | $MYSQL

:0
/dev/null
}

# spamcop 的檢舉信回函轉存 mysql, 再以程式去 submit form
:0 H
* ^Subject: .*SpamCop has accepted.*
{
        :0 fw
        | ( echo "insert into SPAMCOP_ID(SPAM_ID) values('$SPAMID')" | $MYSQL)

        :0
        /dev/null
}

# 一些大的廣告信商
:0 HD
* (^From:|^Received:|Return-Path:) .*(mailserver.idv.tw|mailserver.com|worldad.net|mailnews.com.tw|rayman.com.cn).*
{
:0 fw
| echo "insert into SPAM(MAIL_FROM,RCPT_TO,SUBJ,FILE_NAME,MAIL_TYPE,USERNAME,REASON,PATTEN ) values('$FROM ','$TO ','$SUBJ ','$FILE',1,'$LOGNAME','發信軟體','mailserver 信商發出')"    | $MYSQL

:0
/dev/null
}


# 收信人為數字型態
:0 HD
* ^To: .*[0-9][0-9].txt.*
{
:0 fw
| echo "insert into SPAM(MAIL_FROM,RCPT_TO,SUBJ,FILE_NAME,MAIL_TYPE,USERNAME,REASON,PATTEN ) values('$FROM ','$TO ','$SUBJ ','$FILE',1,'$LOGNAME','發信軟體','數字型收件者')"    | $MYSQL

:0
/dev/null
}

# From: user@mydomain.net.tw 但不為自己人
:0 HD
* ^From: .*@mydomain.net.tw.*
* !^Received: .*211\.72\.21[0-1]\..*
{
:0 fw
| (username=${FROM%%@*};if [ -d /home/$username ] ; then formail -A "Bogus: No"; else formail -A "Bogus: Yes";  echo "insert into SPAM(MAIL_FROM,RCPT_TO,SUBJ,FILE_NAME,MAIL_TYPE,USERNAME,REASON,PATTEN ) values('$FROM ','$TO ','$SUBJ ','$FILE',1,'$LOGNAME','寄件人不存在','$FROM ')" | $MYSQL ;fi  );

:0 
* ^Bogus: Yes
/dev/null
}


# 主旨過濾,資料存?mysql
:0 HD
* ! ^From: .*@mydomain.net.tw.*
{
patten=`echo "select concat(\"'\",PATTEN,\"'\") from SPAM_PATTEN where USERNAME='$LOGNAME' and instr('$SUBJ',PATTEN)"|$MYSQL | grep -v 'PATTEN'| tr '\n' ','`
patten2=`echo $patten | sed -e "s/'//g"`

        :0 fw
* ? test -n "$patten"
        | ( 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','符合特定字串','$patten2'); update SPAM_PATTEN set CNT=CNT+1 where USERNAME='$LOGNAME' and PATTEN in ($patten ''); " | $MYSQL ;\
)

        :0
        * ^Spam: .*
        /dev/null
}

# RBL 過濾, rbl doamin 存於 mysql
:0 
* ! ^From: .*@(mydomain.net.tw|mydomain.net).*
* ! ^Received: .*159\.226\.*
{
rbl=`for spam in $(echo "select RBL_DOMAIN from SPAM_SOURCE order by SN"| $MYSQL | grep -v 'RBL_DOMAIN'); do  rbl=$(host $PTR.$spam| grep 'has address'); test -n "$rbl" && echo $PTR.$spam && break; done`

        :0 fw
|( test -n "$rbl" && (echo "insert into SPAM(MAIL_FROM,RCPT_TO,SUBJ,FILE_NAME,MAIL_TYPE,USERNAME,REASON,PATTEN ) values('$FROM ','$TO ','$SUBJ ','$FILE',1,'$LOGNAME','來自 RBL IP','$rbl.$spam')" | $MYSQL) && formail -A "Spam: From_RBL $rbl.$spam" )

        :0
        * ^Spam: .*
        /dev/null
}



結果呈現:
http://211.72.210.251/spamcop.html

最近30天:
來自 RBL IP 5061 25.31% 
寄件人不存在 911 4.56% 
符合特定字串 3845 19.23% 
發信軟體 10166 50.84%


 reddata 回复于:2004-12-24 20:00:23

引用:原帖由 "abel" 发表:
修改 procmailrc 不用 restart sendmail

:0 然後呢 ?

============
:0
* ^Content-Type:.*
* name=.*\.(exe|ppt|pps|com|bat|reg|scr)
/dev/null

=============

procmail log 說什麼你有注意看嗎 ?


我在/etc/procmailrc中明明指向/tmp/procmail.log,可是当我进入/tmp一看procmail.log,还是空的,真是怪事。。。

今天一个晚上我都在读你的贴子,受益非浅!让我明白一个道理,凡事得靠自己,不能伸手向别人要东西。。。。。


 abel 回复于:2004-12-27 11:24:14

引用:我在/etc/procmailrc中明明指向/tmp/procmail.log,可是当我进入/tmp一看procmail.log,还是空的,真是怪事。。。 

今天一个晚上我都在读你的贴子,受益非浅!让我明白一个道理,凡事得靠自己,不能伸手向别人要东西。。。。。


procmail.log 一直都是空的嗎? 還是這個版本才是空的...
我想應該是你的語法有錯才會這樣

至於體會,我想最重要的是你自己要懂的克苦力學,
我學 procamil 相關的應用,是努力 K 了一個星期才有的成果,
至於像其他現成的 opensource anti-spam 軟體我也實驗過,
但我們單位現在用我寫的東西可是效果非常好,且補救措施也夠

不管你學什麼,要有一個體認,就是非研究出來不可,英文的東西多看
久了就會習慣了,除非你底子真的很差,那就先學英文較實際

mail 的東西本來在很多層面就有不好理解之處,唯有透過自己做實驗
做研究,久了體會就深了, 我們單位都會提供給我一部機器,讓我做實驗
把實驗好的東西在效到系統中. 常做實驗,多看 "正確" 的文件(manpage
官網), 少看什麼教學或文檔才是最真實的做法


 wanyf 回复于:2004-12-30 16:18:10

很多邮件都是编码的
procmail认不到吧?


 abel 回复于:2004-12-30 16:28:59

請看仔細一點 !!




原文链接:http://bbs.chinaunix.net/viewthread.php?tid=468962
转载请注明作者名及原文出处



收藏本页到: