Hi,

I'm working on using SpamAssassin within a perl mail processing script.
In order to reduce overheads, I'm not loading the mail being processed
into a variable and load new instances of Mail::SpamAssassin every time,
but instead am running spamd and getting the script to check the mails
against it.

But I ran into a problem. I'd rather not rely on spamc and IPC::Open2 to
talk to it from within the script, instead I'd like to write spamc in
Perl. How can I do this? I can't see a way to close the client sending
side, to get spamd to process the mail, while still keeping the client
open to receive the response.

If anyone's got a solution to that I'd be interested to hear it, but in
the mean time I solved the problem by changing spamd to allow the message
to be terminated with a '.', like SMTP and other protocols -- is there
any reason spamd doesn't do this already?

Instead of = (<STDIN>) and the foreach loop, I wrote:

my @msglines;
my $actual_length;
while (<STDIN>) {
    last if /^\.[\r\n]*$/;
    $actual_length += length;
    push (@msglines, $_);
}

Could this be implemeted in the main source? It works with both the old
style and ending with a '.'.

Also, why are the hit values int'd? I'd much prefer them as decimals.
And also, I'd like to be able to get the list of symbols back as well,
along with the score, with a command like SYMBOLS SPAMC/1.x .

Could either of those be implemted too? I've attached a patch to do all
of this, but with the decimals only for < SPAMC/1.3.

- Alan
-- 
Alan Ford * [EMAIL PROTECTED] 
--- spamd.raw   Fri Mar 29 14:39:55 2002
+++ spamd       Fri Mar 29 14:44:44 2002
@@ -226,9 +226,10 @@
        # It might be a CHECK message, meaning that we should just check
        # if it's spam or not, then return the appropriate response.
 
-       elsif (/CHECK SPAMC\/(.*)/)
+       elsif (/(CHECK) SPAMC\/(.*)/ || /(SYMBOLS) SPAMC\/(.*)/)
        {
-           my $version = $1;
+           my $method = $1;
+           my $version = $2;
            my $expected_length;
 
             # Protocol version 1.0 and greater may have "User:" and
@@ -291,10 +292,12 @@
            my $resp = "EX_OK";
 
            # Now read in message
-           my @msglines = (<STDIN>);
+           my @msglines;
            my $actual_length;
-           for (@msglines) {
+           while (<STDIN>) {
+               last if /^\.[\r\n]*$/;
                $actual_length += length;
+               push (@msglines, $_);
            }
            my $mail = Mail::SpamAssassin::NoMailAudit->new (
                                 data => \@msglines,
@@ -309,19 +312,25 @@
 
            # Now use copy-on-writed (hopefully) SA object
            my $status = $spamtest->check($mail);
-           my $msg_score = int($status->get_hits);
-           my $msg_threshold = int($status->get_required_hits);
+           my $msg_score = $status->get_hits;
+           my $msg_threshold = $status->get_required_hits;
            my $was_it_spam;
+           if ($version < 1.3) {
+               $msg_score = int $msg_score;
+               $msg_threshold = int $msg_threshold;
+           }
            if ($status->is_spam)
            {
-               print "SPAMD/1.1 $resphash{$resp} $resp\r\nSpam: True ; $msg_score / 
$msg_threshold\r\n\r\n";
+               print "SPAMD/1.1 $resphash{$resp} $resp\r\nSpam: True ; $msg_score / 
+$msg_threshold\r\n";
                $was_it_spam = 'identified spam';
            }
            else
            {
-               print "SPAMD/1.1 $resphash{$resp} $resp\r\nSpam: False ; $msg_score / 
$msg_threshold\r\n\r\n";
+               print "SPAMD/1.1 $resphash{$resp} $resp\r\nSpam: False ; $msg_score / 
+$msg_threshold\r\n";
                $was_it_spam = 'clean message';
            }
+           print $status->get_names_of_tests_hit, "\r\n" if ($method eq "SYMBOLS");
+           print "\r\n";
            $current_user ||= '(unknown)';
            logmsg "$was_it_spam ($msg_score/$msg_threshold) for $current_user:$> in ".
                sprintf("%3d", time - $start) ." seconds.\n";
@@ -398,10 +407,12 @@
            my $resp = "EX_OK";
 
            # Now read in message
-           my @msglines = (<STDIN>);
+           my @msglines;
            my $actual_length;
-           for (@msglines) {
+           while (<STDIN>) {
+               last if /^\.[\r\n]*$/;
                $actual_length += length;
+               push (@msglines, $_);
            }
            my $mail = Mail::SpamAssassin::NoMailAudit->new (
                                 data => \@msglines,
@@ -434,8 +445,12 @@
            }
            my $was_it_spam;
            if($status->is_spam) { $was_it_spam = 'identified spam'; } else { 
$was_it_spam = 'clean message'; }
-            my $msg_score = int($status->get_hits);
-            my $msg_threshold = int($status->get_required_hits);
+            my $msg_score = $status->get_hits;
+            my $msg_threshold = $status->get_required_hits;
+           if ($version < 1.3) {
+               $msg_score = int $msg_score;
+               $msg_threshold = int $msg_threshold;
+           }
            $current_user ||= '(unknown)';
            logmsg "$was_it_spam ($msg_score/$msg_threshold) for $current_user:$> in ".
                sprintf("%3d", time - $start) ." seconds.\n";

Reply via email to