精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>电脑技术>>● FreeBSD>>有待整理的文章-新加的文章都在这里>>[转载]:eps邮件过滤进阶

主题:[转载]:eps邮件过滤进阶
发信人: 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    

[关闭][返回]