发信人: zenz.hu(真) 
整理人: hackerbay(2002-09-06 16:48:51), 站内信件
 | 
 
 
★原文转载自openbsd版zenz.hu的《eps邮件过滤进阶》★ 好吧,上次我们用eps做了一个很暴力的邮件过滤器,这次我们稍微往前走一点点,把过滤器变得稍微完满一些。
 
 首先,我们通过研究qmail的代码,知道在.qmail文件中,如果调用一个外部程序,返回值是99的话,那么就代表不再进行下一步的邮件处理工作。而通过qmail-inject我们可以发送邮件。
 知道了这些,我们就可以开始进一步把程序处理得更好些了。首先看代码,我们加了一些东西,请自己对比。
 /* myfilter.c */
 #include <stdio.h>
 #include <eps.h>
 #include <qmail.h>
 
 char *exts[]={
   ".vbs",
   ".scr",
   ".exe",
   ".com",
   ".pif",
   ".386",
   ".bat",
   ".sys",
   NULL
 };
 
 
 char *i_headers[]={
   "From",
   NULL
 };
 
 
 // 新加的,用于获取发件人的邮箱
 char *do_address(struct header_t *h)
 {
   struct atom_t *aa = NULL;
   struct address_t *alist = NULL, *a = NULL;
 
   if (!(h->atoms))
      return;
 
   if (!(h->atoms->next))
         return;
 
   alist = eps_address_evaluate(h->data);
 
   if (!alist) {
      printf("%s: no valid addresses\n", h->name);
      return;
   }
 
 
   for (a = alist; a->next; a = a->next) {
       if ((a->next->user == NULL) && (a->next->address))
          printf("  SYNTAX ERROR: [%s]\n", a->next->address);
 
       else {
         if (a->next->name)
            return a->next->address;
         else
            return a->next->address;
       }
   }
 
   eps_address_kill(alist);
 }
 
 
 // 旧的,用于检查附件的扩展名
 int efilter_check_mime(struct mime_t *m)
 {
   int i = 0;
   int p = 0;
 
   if (!(m->filename))
      return 0;
 
   for (i = 0; exts[i]; i++) {
       if (m->filename) {
          p = strstr(m->filename, exts[i]);
          if (p) {
             return 1;
          }
       }
   }
 
   return 0;
 }
 
 
 
 int main(int argc, char *argv[])
 {
   int ret = 0;
   int i;
   char *frm_addr;
   char *l = NULL;
   struct mime_t *m = NULL;
   struct header_t *h = NULL;
   struct eps_t *eps = NULL;
   FILE *qinject = NULL;
 
   if (argc < 2)
     eps = eps_begin(INTERFACE_STDIN, NULL);
   else
     eps = eps_begin(INTERFACE_FILENAME, argv[1]);
 
   if (!eps)
     return 1;
 
   for (h = eps_next_header(eps); h; h = eps_next_header(eps)) {
     if ((h->name) && (h->data)) {
 	for (i=0;i_headers[i]; i++) {
           if (!(strcasecmp(i_headers[i],h->name))) {
 	    frm_addr=do_address(h);
           }
         }
 	eps_header_free(eps);
     }
   }
 
   for (l = eps_next_line(eps, BREAK_STOP); l; l = eps_next_line(eps, BREAK_STOP));
 
   eps_init_mime(eps);
 
   for (m = eps_next_mime(eps); m; m = eps_next_mime(eps)) {
     if (efilter_check_mime(m)){
       printf("rejected");
       ret = 1;
     }
   }
 
   eps_end(eps);
   if (ret) {
     qinject = qmail_inject();
     fprintf(qinject,"From: [email protected]\n");
     fprintf(qinject,"To: %s\n",frm_addr);
     fprintf(qinject,"Subject: email filter warnning!\n");
     fprintf(qinject,"X-mailer: Foxmail 4.1 [cn]\n");
     fprintf(qinject,"Mime-Version: 1.0\n");
     fprintf(qinject,"Content-Type: text/plain;\n      charset=\"GB2312\"\n");
     fprintf(qinject,"Content-Transfer-Encoding: quoted-printable\n\n");
     fprintf(qinject,"您好,您发出的电子邮件因为包含以下被禁止的扩展名附件:\n");
     fprintf(qinject,"*.vbs *.exe *.com *.pif *.scr *.bat *.386 *.sys\n");
     fprintf(qinject,"所以您的邮件被过滤掉了。\n");
     fprintf(qinject,"如果您确实希望包含此类文件到您的邮件当中,那么请先把他们打包。\n");
     fprintf(qinject,"如果您并没有添加此类附件,那么您的电脑可能感染病毒,请杀毒后再发邮件。");
     pclose(qinject);
     return 99;
   }
   return 0;
 }
 
 
 编译程序
 gcc -g -I/usr/include/eps -L/usr/lib -o myfilter myfilter.c -leps
 
 然后把获得的myfilter复制到/var/vpopmail/bin目录中去,属主和组都和vdelivermail一样就可以了。
 修改/var/vpopmail/domains/yourdomain/.qmail-default文件,把
 | /var/vpopmail/bin/vdelivermail '' bounce-no-mailbox
 改为
 | /var/vpopmail/bin/myfilter
 | /var/vpopmail/bin/vdelivermail '' bounce-no-mailbox
 好了,你现在可以试一试这个新的邮件过滤器了。
 
 
  ----
  
 来OpenBSD版看看吧!
 我的QQ:2562293     | 
 
 
 |