sendmail +mimedefang 给邮件附加负责声明

来源:互联网 发布:有什么办法做淘宝客 编辑:程序博客网 时间:2024/04/30 00:25

最近公司邮件服务器有新的应用,就是在在邮件后面附加类似“免遭声明”之类的声明。只在本地用户发送时和本地用户第一次回复某一主题的时候附加,对于已要附加过声明的邮件,在后面的再回复中不再附加。

搞这个问题搞了一天多了,走了一个大弯路,其实附加声明是很简单的事情,但是判断该主题的邮件是否已经附加过,在这个问题上卡壳了,

原来的思路是:把要附加的内容存储在数据库中。在filter_end中,打开“./INPUTMSG",把经过base64加密的那部分(邮件正文部分)
                           进行decode。 然后匹配正文中是否已存在特殊字段,如果有,则不再附加,反之,则附加。

但是遇到问题:在解码./INPUTMSG时,只有在重启mimedefang服务后第一次能正确解码,后面再发送其它邮件时,
                           解码出来的内容都是乱码了。我在打开"./INPUTMSG"时,拷贝一份到其它目录下,然后利用filter_end中
                            一样的解码过程进行解码,就能够得到正常内容,但是在mimedefang过虑过程中解码得到的却是乱码。
                            不知道是什么原因,部分代码如下:

  1. sub filter_end {
  2.     use DBI;
  3.     use MIME::Base64;
  4.     use Encode qw/from_to/;
  5.     my($entity) = @_;
  6.     my ($dsn)="DBI:mysql:database_name:localhost";
  7.     my ($user_name)="username";
  8.     my ($password)="userpassword";
  9.     foreach $recip(@Recipients){
  10.         $recip=~ /<.*@(.*)>/;
  11.         my $domain_to =$1;
  12.         my $localdomain="local_domain";    #定义特殊domain,对此domain发邮件时不附加
  13.         my $sign="ANNOUNCEMENT:";    #定义特殊标志,后面匹配到邮件内容中有此字符串时便不在附加
  14.         if($domain_to !~ $localdomain)
  15.         {
  16.             system("/bin/cp ./INPUTMSG /var/spool/MIMEtmp/INPUTMSG"); #拷贝./INPUTMSG到指定目录,然后可以手动解码看看实际内容
  17.             my $file="./INPUTMSG";
  18.             my $body;
  19.             my $start=qr/^Content-Transfer-Encoding: base64/;
  20.             my $end=qr/^--(?!----=_NextPart)/;                             #定义截取邮件内容的开始和结束标记,即只要$start和$end中间的内容
  21.             open (FILE,$file) or die "Connot open $!";
  22.             while(<FILE>){
  23.                 if((/$start/../$end/) and !/$start/ and !/$end/){
  24.                     $body.=$_;
  25.                     }
  26.                 }
  27.             md_syslog('info',"/$body/'s value is : $body");
  28.             close FILE;
  29.             $de_body=decode_base64("$body");
  30.             md_syslog('info',"/$de_body/'s value is : $de_body");
  31.             if ($de_body !~ $sign)
  32.                 {
  33.                 $dbh=DBI->connect($dsn,$user_name,$password);
  34.                 $sth=$dbh->prepare("SELECT * from  comment where active='YES'");
  35.                 $sth->execute();
  36.                 while(@ary=$sth->fetchrow_array()){
  37.                     ($active,$title,$content)=@ary;
  38.                     }
  39.                 from_to($content,"utf8","gb2312");
  40.                 append_text_boilerplate($entity,"$sign"."$content"0);
  41.                 append_html_boilerplate($entity,"<br> <hr> <br>"."$sign"."<br><br>"."$content"0);
  42.                 }
  43.         }
  44.     }

 

另外,这样做,方法本身可能就有问题,在邮件发送量大的时候,处理延迟问题可能就会很突出,能不能在已经附加过声明的邮件中插入一个标记,这个标记可以终身跟随这一主题的邮件,以后只需要检查邮件中有没有该标记,然后就可以决定是否附加声明了。

 

后来又去看了一下mimedefang的howto,顺着上面的思路,找到了另种更好的方法:

想想前的打开文件,真不是个什么聪明的方法,现在通过改变邮件的header来实现想要的结果
具体方法:上一封邮件的Message-ID,会现在在回复邮件的References:中,所以我在附加声明之后,修改邮件的Message-ID,在回复时,检查References:中是否含有我指定的Message-ID,如果有,则说明此主题的邮件已经附加过,则不再附加,也不会再修改Message-ID,反之则附加声明
实现代码如下


 
CODE:
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(/:/,$_))[1] 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,{RaiseError => 1});
                $sth=$dbh->prepare("SELECT * from  comment where active='YES'");
                $sth->execute();
                while(@ary=$sth->fetchrow_array()){
                    ($active,$create_date,$title,$content)=@ary;
                    }
                from_to($content,"utf8","gb2312");
                #md_syslog('info',"/$content/' value is : $content");
                append_text_boilerplate($entity,"$sign"."$content", 0);
                append_html_boilerplate($entity,"<br> <hr> <br>"."$content", 0);
                }
            }
     }


PS:代码里只是随便指定了一个$sign,这样每封每一次发出去的邮件都有相同的Message-ID,容易被认为是垃圾邮件,你可以采取一些简单的方法,生成不同的Message-ID,方法这里不再细说

原创粉丝点击