spamass-milt-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Recipient filtering...


From: Joe Maimon
Subject: Recipient filtering...
Date: Mon, 20 Sep 2004 12:13:04 -0400
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7) Gecko/20040616 Mnenhy/0.6.0.101

Hello all,

I havent been a list member long and have not spent much time searching archives, so forgive me if this is somebody elses old news already.

I recently decided that I did not want to waste spamassassin resources on recipients sendmail had skipped all RBL and other spam check on due to "Spam: FRIEND" checks.(being as most of the spams would have been caught and rejected by the skipped checks)

Since I could not find anyway to have sendmail selectively not launch a milter connection (I did start looking into patching sendmail to use rulesets for milter connections...if anybody is interested) I decided to hack in a filter to spamass-milt.

Attached is my (amatuer) attempts as a patch against 0.2.0 and a patch that will fit into the debian package. Also attached is a bash script that I use as a filter. I probably should have tried this agains cvs....I guess I will check that out next.

Seems to work stable here for a few hours, but is by no means a polished and finished piece of work.

This patch adds command line argument -R which accepts as an argument a program that will be called with a parameter of recpient email adrress, once per recipient.
(Yes i know, not the most resource cheap way)
When the program exits, the exit code of 0 is taken to mean "filtered successfully". If there are no un-filtered recipients, spamass-milter will return to sendmail a SMFIS_ACCEPT at the start of mlfi_header.

Any and all feedback is most welcome.

Joe


Only in spamass-milter-0.2.0-orig/contrib: spamass-milter.spec
diff -ur spamass-milter-0.2.0-orig/spamass-milter.cpp 
spamass-milter-0.2.0/spamass-milter.cpp
--- spamass-milter-0.2.0-orig/spamass-milter.cpp        2003-06-26 
11:10:44.000000000 -0400
+++ spamass-milter-0.2.0/spamass-milter.cpp     2004-09-20 10:42:24.000000000 
-0400
@@ -150,13 +150,15 @@
   };
 
 const char *const debugstrings[] = {
-       "ALL", "FUNC", "POLL", "UORI", "STR", "MISC", "NET", "SPAMC",
+       "ALL", "FUNC", "POLL", "UORI", "STR", "MISC", "NET", "SPAMC", "RCPT",
        NULL
 };
 
 int flag_debug = (1<<D_ALWAYS);
 bool flag_reject = false;
 int reject_score = -1;
+bool flag_rcpt_filter = false;
+char *rcpt_filter = NULL;
 bool dontmodify = false;
 bool flag_sniffuser = false;
 char *defaultuser;
@@ -174,7 +176,7 @@
 main(int argc, char* argv[])
 {
    int c, err = 0;
-   const char *args = "p:fd:mr:u:D:i:b:B:";
+   const char *args = "p:fd:mr:R:u:D:i:b:B:";
    char *sock = NULL;
    bool dofork = false;
 
@@ -207,6 +209,10 @@
                                flag_reject = true;
                                reject_score = atoi(optarg);
                                break;
+                       case 'R':
+                               flag_rcpt_filter = true;
+                               rcpt_filter = optarg;
+                               break;
                        case 'u':
                                flag_sniffuser = true;
                                defaultuser = strdup(optarg);
@@ -259,6 +265,7 @@
       cout << "   -m: don't modify body, Content-type: or Subject:" << endl;
       cout << "   -r nn: reject messages with a score >= nn with an SMTP 
error.\n"
               "          use -1 to reject any messages tagged by SA." << endl;
+      cout << "   -R cmd: filter out recipients with zero exit status."<< endl;
       cout << "   -u defaultuser: pass the recipient's username to spamc.\n"
               "          Uses 'defaultuser' if there are multiple recipients." 
<< endl;
       cout << "   -- spamc args: pass the remaining flags to spamc." << endl;
@@ -576,6 +583,7 @@
        }
        sctx->assassin = NULL;
        sctx->helo = NULL;
+       sctx->rcpts = 0;
        
        /* store a pointer to it with setpriv */
        smfi_setpriv(ctx, sctx);
@@ -718,6 +726,54 @@
        {
                assassin->recipients.push_back( *rcpt ); // XXX verify that 
this worked
        }
+
+       sctx->rcpts++;
+       if(flag_rcpt_filter && rcpt_filter)
+       {
+               int rcpt_filter_result = 0;
+               int size = 0;
+               char *cmd_buffer = NULL;
+               char *tmp_rcpt = NULL;
+               char * queue_id = smfi_getsymval(ctx,"i");
+               
+               debug(D_RCPT,"%s: rcpt_filter",queue_id);
+
+               
+               if((tmp_rcpt = strdup(envrcpt[0])) != NULL)
+               {
+                       tmp_rcpt[strlen(tmp_rcpt)-1] = '\0';
+                       size = strlen(rcpt_filter);
+                       tmp_rcpt++;
+                       size += strlen(tmp_rcpt);
+                       cmd_buffer = (char *) malloc(size+10);
+               }
+               if(cmd_buffer) 
+               {
+                       debug(D_RCPT,"%s: rcpt_filter, malloc succeeded", 
queue_id);
+                       sprintf(cmd_buffer,"%s %s",rcpt_filter, tmp_rcpt );
+                       cmd_buffer[size+2] = '\0';
+                       debug(D_RCPT, "%s: rcpt_filter, filter string <%s>", 
queue_id, cmd_buffer);
+                       
+                       rcpt_filter_result = system(cmd_buffer);
+                       if(!rcpt_filter_result)
+                       {
+                               debug(D_RCPT,"%s: rcpt_filter, removing rcpt", 
queue_id);
+                               sctx->rcpts--;
+                       } else
+                               debug(D_RCPT,"%s: rcpt_filter, leaving rcpt", 
queue_id);
+
+               } else
+                       debug(D_RCPT,"%s: rcp_filter, malloc failed", queue_id);
+
+               if(cmd_buffer)
+                       free(cmd_buffer);
+               if(tmp_rcpt)
+               {
+                       tmp_rcpt--;
+                       free(tmp_rcpt);
+               }
+       
+       }
        return SMFIS_CONTINUE;
 }
 
@@ -740,6 +796,21 @@
   SpamAssassin* assassin = ((struct context *)smfi_getpriv(ctx))->assassin;
   debug(D_FUNC, "mlfi_header: enter");
 
+  {
+       struct context * sctx = (struct context *) smfi_getpriv(ctx);
+       char * queue_id = smfi_getsymval(ctx,"i");
+       if(flag_rcpt_filter && !sctx->rcpts) 
+       {
+               debug(D_RCPT,"%s: rcpt_filter, accepting message without 
processing");
+               mlfi_abort(ctx); // For lack of specific cleanup 
+               debug(D_FUNC, "%s: mlfi_header: rcpt_filter leave", queue_id);
+               return SMFIS_ACCEPT;
+       } else
+               debug(D_RCPT, "%s: rcpt_filter, processing message", queue_id);
+       
+       debug(D_FUNC, "%s: mlfi_header: rcpt_filter leave", queue_id);
+  }
+
   // Check if the SPAMC program has already been run, if not we run it.
   if ( !(assassin->connected) )
      {
diff -ur spamass-milter-0.2.0-orig/spamass-milter.h 
spamass-milter-0.2.0/spamass-milter.h
--- spamass-milter-0.2.0-orig/spamass-milter.h  2003-06-14 15:17:41.000000000 
-0400
+++ spamass-milter-0.2.0/spamass-milter.h       2004-09-20 10:42:33.000000000 
-0400
@@ -63,7 +63,7 @@
 // Debug tokens.
 enum debuglevel 
 {
-       D_ALWAYS, D_FUNC, D_POLL, D_UORI, D_STR, D_MISC, D_NET, D_SPAMC,
+       D_ALWAYS, D_FUNC, D_POLL, D_UORI, D_STR, D_MISC, D_NET, D_SPAMC, D_RCPT,
        D_MAX // must be last
 };
 
@@ -153,6 +153,7 @@
        struct in_addr connect_ip;      // remote IP address
        char *helo;
        SpamAssassin *assassin; // pointer to the SA object if we're processing 
a message
+       int rcpts; // must be positive if we are to do ANY spamassassin 
processing
 };
 
 /* This hack is the only way to call pointers to member functions! */
--- Rcpt-Filter.jm.patch        2004-09-20 10:44:10.000000000 -0400
+++ Rcpt-Filter.jm-Debian.patch 2004-09-20 10:55:20.000000000 -0400
@@ -23,8 +23,8 @@
  main(int argc, char* argv[])
  {
     int c, err = 0;
--   const char *args = "p:fd:mr:u:D:i:b:B:";
-+   const char *args = "p:fd:mr:R:u:D:i:b:B:";
+-   const char *args = "fd:mp:P:r:u:D:i:b:B:";
++   const char *args = "fd:mp:P:r:R:u:D:i:b:B:";
     char *sock = NULL;
     bool dofork = false;
  
Only in spamass-milter-0.2.0-orig/contrib: spamass-milter.spec
diff -ur spamass-milter-0.2.0-orig/spamass-milter.cpp 
spamass-milter-0.2.0/spamass-milter.cpp
--- spamass-milter-0.2.0-orig/spamass-milter.cpp        2003-06-26 
11:10:44.000000000 -0400
+++ spamass-milter-0.2.0/spamass-milter.cpp     2004-09-20 10:42:24.000000000 
-0400
@@ -150,13 +150,15 @@
   };
 
 const char *const debugstrings[] = {
-       "ALL", "FUNC", "POLL", "UORI", "STR", "MISC", "NET", "SPAMC",
+       "ALL", "FUNC", "POLL", "UORI", "STR", "MISC", "NET", "SPAMC", "RCPT",
        NULL
 };
 
 int flag_debug = (1<<D_ALWAYS);
 bool flag_reject = false;
 int reject_score = -1;
+bool flag_rcpt_filter = false;
+char *rcpt_filter = NULL;
 bool dontmodify = false;
 bool flag_sniffuser = false;
 char *defaultuser;
@@ -174,7 +176,7 @@
 main(int argc, char* argv[])
 {
    int c, err = 0;
-   const char *args = "fd:mp:P:r:u:D:i:b:B:";
+   const char *args = "fd:mp:P:r:R:u:D:i:b:B:";
    char *sock = NULL;
    bool dofork = false;
 
@@ -207,6 +209,10 @@
                                flag_reject = true;
                                reject_score = atoi(optarg);
                                break;
+                       case 'R':
+                               flag_rcpt_filter = true;
+                               rcpt_filter = optarg;
+                               break;
                        case 'u':
                                flag_sniffuser = true;
                                defaultuser = strdup(optarg);
@@ -259,6 +265,7 @@
       cout << "   -m: don't modify body, Content-type: or Subject:" << endl;
       cout << "   -r nn: reject messages with a score >= nn with an SMTP 
error.\n"
               "          use -1 to reject any messages tagged by SA." << endl;
+      cout << "   -R cmd: filter out recipients with zero exit status."<< endl;
       cout << "   -u defaultuser: pass the recipient's username to spamc.\n"
               "          Uses 'defaultuser' if there are multiple recipients." 
<< endl;
       cout << "   -- spamc args: pass the remaining flags to spamc." << endl;
@@ -576,6 +583,7 @@
        }
        sctx->assassin = NULL;
        sctx->helo = NULL;
+       sctx->rcpts = 0;
        
        /* store a pointer to it with setpriv */
        smfi_setpriv(ctx, sctx);
@@ -718,6 +726,54 @@
        {
                assassin->recipients.push_back( *rcpt ); // XXX verify that 
this worked
        }
+
+       sctx->rcpts++;
+       if(flag_rcpt_filter && rcpt_filter)
+       {
+               int rcpt_filter_result = 0;
+               int size = 0;
+               char *cmd_buffer = NULL;
+               char *tmp_rcpt = NULL;
+               char * queue_id = smfi_getsymval(ctx,"i");
+               
+               debug(D_RCPT,"%s: rcpt_filter",queue_id);
+
+               
+               if((tmp_rcpt = strdup(envrcpt[0])) != NULL)
+               {
+                       tmp_rcpt[strlen(tmp_rcpt)-1] = '\0';
+                       size = strlen(rcpt_filter);
+                       tmp_rcpt++;
+                       size += strlen(tmp_rcpt);
+                       cmd_buffer = (char *) malloc(size+10);
+               }
+               if(cmd_buffer) 
+               {
+                       debug(D_RCPT,"%s: rcpt_filter, malloc succeeded", 
queue_id);
+                       sprintf(cmd_buffer,"%s %s",rcpt_filter, tmp_rcpt );
+                       cmd_buffer[size+2] = '\0';
+                       debug(D_RCPT, "%s: rcpt_filter, filter string <%s>", 
queue_id, cmd_buffer);
+                       
+                       rcpt_filter_result = system(cmd_buffer);
+                       if(!rcpt_filter_result)
+                       {
+                               debug(D_RCPT,"%s: rcpt_filter, removing rcpt", 
queue_id);
+                               sctx->rcpts--;
+                       } else
+                               debug(D_RCPT,"%s: rcpt_filter, leaving rcpt", 
queue_id);
+
+               } else
+                       debug(D_RCPT,"%s: rcp_filter, malloc failed", queue_id);
+
+               if(cmd_buffer)
+                       free(cmd_buffer);
+               if(tmp_rcpt)
+               {
+                       tmp_rcpt--;
+                       free(tmp_rcpt);
+               }
+       
+       }
        return SMFIS_CONTINUE;
 }
 
@@ -740,6 +796,21 @@
   SpamAssassin* assassin = ((struct context *)smfi_getpriv(ctx))->assassin;
   debug(D_FUNC, "mlfi_header: enter");
 
+  {
+       struct context * sctx = (struct context *) smfi_getpriv(ctx);
+       char * queue_id = smfi_getsymval(ctx,"i");
+       if(flag_rcpt_filter && !sctx->rcpts) 
+       {
+               debug(D_RCPT,"%s: rcpt_filter, accepting message without 
processing");
+               mlfi_abort(ctx); // For lack of specific cleanup 
+               debug(D_FUNC, "%s: mlfi_header: rcpt_filter leave", queue_id);
+               return SMFIS_ACCEPT;
+       } else
+               debug(D_RCPT, "%s: rcpt_filter, processing message", queue_id);
+       
+       debug(D_FUNC, "%s: mlfi_header: rcpt_filter leave", queue_id);
+  }
+
   // Check if the SPAMC program has already been run, if not we run it.
   if ( !(assassin->connected) )
      {
diff -ur spamass-milter-0.2.0-orig/spamass-milter.h 
spamass-milter-0.2.0/spamass-milter.h
--- spamass-milter-0.2.0-orig/spamass-milter.h  2003-06-14 15:17:41.000000000 
-0400
+++ spamass-milter-0.2.0/spamass-milter.h       2004-09-20 10:42:33.000000000 
-0400
@@ -63,7 +63,7 @@
 // Debug tokens.
 enum debuglevel 
 {
-       D_ALWAYS, D_FUNC, D_POLL, D_UORI, D_STR, D_MISC, D_NET, D_SPAMC,
+       D_ALWAYS, D_FUNC, D_POLL, D_UORI, D_STR, D_MISC, D_NET, D_SPAMC, D_RCPT,
        D_MAX // must be last
 };
 
@@ -153,6 +153,7 @@
        struct in_addr connect_ip;      // remote IP address
        char *helo;
        SpamAssassin *assassin; // pointer to the SA object if we're processing 
a message
+       int rcpts; // must be positive if we are to do ANY spamassassin 
processing
 };
 
 /* This hack is the only way to call pointers to member functions! */
#!/bin/bash

EDITMAP="/usr/sbin/editmap"
MAPNAME="/etc/mail/access"
MAPTYPE="hash"


LOCALPART=`echo $1 | cut -d'@' -f1`
RECURPART=`echo $1 | cut -d'@' -f2`

function editmapquery() {

        OUTPUT=`$EDITMAP -q $MAPTYPE $MAPNAME Spam:$1 2> /dev/null | tr 
[[:upper:]] [[:lower:]]`
        if [[ "$?" == "0" && "$OUTPUT" == "friend" ]]; then
                exit 0;
        fi

}

editmapquery $1

while [[ "$RECURPART" != "" && "$RECURPART" != "$OLDPART" ]]; do
        OLDPART=$RECURPART
        editmapquery $RECURPART
        RECURPART=${RECURPART#*.}
done

editmapquery $LOCALPART@
editmapquery 


exit 1;
                        

reply via email to

[Prev in Thread] Current Thread [Next in Thread]