歡迎您光臨本站 註冊首頁

請教:sendmail+mimedefang郵件內容過慮[已經解決]

←手機掃碼閱讀     火星人 @ 2014-03-04 , reply:0

請教:sendmail+mimedefang郵件內容過慮[已經解決]

系統平台:RHEL4.5
軟體:sendmail8.13, mimedefang2.6.3

需求:在本伺服器的用戶向外發送郵件時,在郵件後面附加類似「免遭聲明」之類的聲明。只在本地用戶發送時和本地用戶第一次回復某一主題的時候附加,
         對於已要附加過聲明的郵件,在後面的再回復中不再附加。

我現在的做法是:把要附加的內容存儲在資料庫中。在filter_end中,打開「./INPUTMSG",把經過base64加密的那部分(郵件正文部分)進行decode。
                         然後匹配正文中是否已存在特殊欄位,如果有,則不再附加,反之,則附加。

現在遇到問題是:在解碼./INPUTMSG時,只有在重啟mimedefang服務后第一次能正確解碼,後面再發送其它郵件時,解碼出來的內容都是亂碼了。
                        我在打開"./INPUTMSG"時,拷貝一份到其它目錄下,然後利用filter_end中一樣的解碼過程進行解碼,就能夠得到正常內容,
                        但是在mimedefang過慮過程中解碼得到的卻是亂碼。不知道是什麼原因,下面把部分代碼貼出來,大家幫我看一下:


sub filter_end {
    use DBI;
    use MIME::Base64;
    use Encode qw/from_to/;
    my($entity) = @_;
    my ($dsn)="DBI:mysql:database_name:localhost";
    my ($user_name)="username";
    my ($password)="userpassword";
    foreach $recip(@Recipients){
        $recip=~ /<.*@(.*)>/;
        my $domain_to =$1;
        my $localdomain="local_domain";    #定義特殊domain,對此domain發郵件時不附加
        my $sign="ANNOUNCEMENT:";    #定義特殊標誌,後面匹配到郵件內容中有此字元串時便不在附加
        if($domain_to !~ $localdomain)
        {
            system("/bin/cp ./INPUTMSG /var/spool/MIMEtmp/INPUTMSG"); #拷貝./INPUTMSG到指定目錄,然後可以手動解碼看看實際內容
            my $file="./INPUTMSG";
            my $body;
            my $start=qr/^Content-Transfer-Encoding: base64/;
            my $end=qr/^--(?!----=_NextPart)/;                             #定義截取郵件內容的開始和結束標記,即只要$start和$end中間的內容
            open (FILE,$file) or die "Connot open $!";
            while(<FILE>){
                if((/$start/../$end/) and !/$start/ and !/$end/){
                    $body.=$_;
                    }
                }
            md_syslog('info',"\$body\'s value is : $body");
            close FILE;
            $de_body=decode_base64("$body");
            md_syslog('info',"\$de_body\'s value is : $de_body");
            if ($de_body !~ $sign)
                {
                $dbh=DBI->connect($dsn,$user_name,$password);
                $sth=$dbh->prepare("SELECT * from  comment where active='YES'");
                $sth->execute();
                while(@ary=$sth->fetchrow_array()){
                    ($active,$title,$content)=@ary;
                    }
                from_to($content,"utf8","gb2312");
                append_text_boilerplate($entity,"$sign"."$content", 0);
                append_html_boilerplate($entity,"<br> <hr> <br>"."$sign"."<br><br>"."$content", 0);
                }
        }
    }



另外,這樣做,方法本身可能就有問題,在郵件發送量大的時候,處理延遲問題可能就會很突出,能不能在已經附加過聲明的郵件中插入一個標記,這個標記可以終身跟隨這一主題的郵件,以後只需要檢查郵件中有沒有該標記,然後就可以決定是否附加聲明了?

請各位不吝賜教!謝謝!

[ 本帖最後由 sunrocs 於 2008-10-20 18:30 編輯 ]
《解決方案》

咋沒人幫偶看看呢
《解決方案》

問題已經搞定.

想想前的打開文件,真不是個什麼聰明的方法,現在通過改變郵件的header來實現想要的結果
具體方法:上一封郵件的Message-ID,會現在在回復郵件的References:中,所以我在附加聲明之後,修改郵件的Message-ID,在回復時,檢查References:中是否含
                有我指定的Message-ID,如果有,則說明此主題的郵件已經附加過,則不再附加,也不會再修改Message-ID,反之則附加聲明
實現代碼如下


sub filter_end {
    use DBI;
    use MIME::Base64;
    use Encode qw/from_to/;
    my($entity) = @_;
    my ($dsn)="DBI:mysql:database_name:localhost";
    my ($user_name)="database_user";
    my ($password)="database_passwd";
   
md_syslog('info',"\$recipient\' value is : $recipient"."@Recipients");
    foreach $recip(@Recipients){
        $recip=~ /<.*@(.*)>/;
        my $domain_to =$1;
        my $localdomain="local_domain";
        my $sign='aaaabbbbccccddddeeeeffff13456789';
        if($domain_to !~ $localdomain)
        {
            my $file="./HEADERS";
            open (FILE,$file) or die "Connot open $!";
            while(<FILE>){
                $header.=$_;
                $id=(split(/:/,$_)) if(/References:/);
                }
            md_syslog('info',"\$id\'s value is : $id,,,,,\$sign=$sign");
            md_syslog('info',"\$header\'s value is : $header");
            close FILE;
            if($id !~ $sign)
                {
                action_change_header("Message-ID", "<$sign>");
                $dbh=DBI->connect($dsn,$user_name,$password);
                $sth=$dbh->prepare("SELECT * from  comment where active='YES'");
                $sth->execute();
                while(@ary=$sth->fetchrow_array()){
                    ($active,$title,$content)=@ary;
                    }
                from_to($content,"utf8","gb2312");
                #md_syslog('info',"\$content\' value is : $content");
                append_text_boilerplate($entity,"$content", 0);
                append_html_boilerplate($entity,"<br> <hr> <br>"."$content", 0);
                }
            }
     }



PS:代碼里只是隨便指定了一個$sign,這樣每封每一次發出去的郵件都有相同的Message-ID,容易被認為是垃圾郵件,你可以採取一些簡單的方法,生成不同的Message-ID,方法這裡不再細說

[ 本帖最後由 sunrocs 於 2008-10-21 08:46 編輯 ]
《解決方案》

謝謝分享

解決問題的方法值得學習

[火星人 ] 請教:sendmail+mimedefang郵件內容過慮[已經解決]已經有562次圍觀

http://coctec.com/docs/service/show-post-26892.html