請教: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 編輯 ]
《解決方案》
謝謝分享
解決問題的方法值得學習