Spam Assassin ( Was: RE: [Mimedefang] Multiplexor stats)

Jeff Heinen jeff.heinen at inherent.com
Fri Jan 4 15:44:23 EST 2002


On Fri, 4 Jan 2002, Mark Roedel wrote:
> Seriously, those are fairly easy to do; it's just my time is a bit
> limited right now.  I'll put them on my TODO list.  Also, if anyone's
> more familiar with SpamAssassin than I am, perhaps you could look at
> improving the glue between m'defang and SA?  It would be nice to get
> more information out of SpamAssassin back into m'defang.

I've actually popped over here from the SA world. I had been working on a
way to roll SA into milter, and this just fit the bill nicely. Extra
information returned and per-user configs are the two things that I wanted
to see also. 

If you want to be risky, you can use the code that I've cooked up, but it is
untested and you'd have to take it at your own risk. I'm not responsible if
it destroys your computer, gives you some rare communicatable disease, or
even knocks up your household pets... its unlikely, but if you are willing
to take that chance it is your decision. ;_) Please only use it in a testing
environment.

Below are two procedures, I've only tested the first, as I didn't have time
to rewrite the filter to test the second (yet). But most, if not all the
data you would be able to get out if it is in the first one. Also, I have
added a trimmed version of my filter_begin which I am using this data.

What I'm looking for now is a way to carry the $report into the top of the
message. I could add it via append_boilerplate, but would the variables I
set in filter_begin ($is_spam and $report) carry to filter_end? Plus, if its
spam, I want the explanation of why I think is spam right at the top.

The other thing I'm looking for is ways to manage per-user differences. For
example, I want to tag all mail, except for those heading to my pager which
I want to deny everything that is close to spam. Custom SA configurations,
or filter scripting are both acceptable I'm just wondering if someone has a
nice generic way that would be easy to adapt as we add more aliases.

As it is, I hope these help people out and if anyone have any questions feel
free to ask. I am actually using some of this code, so if you have any
suggestions I am all ears.

-Jeff



#***********************************************************************
# %PROCEDURE: spam_assassin_check
# %ARGUMENTS:
#  None
# %RETURNS:
#  An array of three elements, 
#	Weight of message ('hits')
#	Number of hits required before SA conciders a message spam
#	Comma separated list of symbolic test names that were triggered
#	A 'report' string, detailing tests that failed and their weights
# %DESCRIPTION:
#  Scans message using SpamAssassin (http://spamassassin.taint.org)
#***********************************************************************
sub spam_assassin_check() {
    open(IN, "<./INPUTMSG") or return 0;

    my $mail = Mail::SpamAssassin::MyMailAudit->new(data=>\*IN);
    my $spamtest =
        Mail::SpamAssassin->new({
            local_tests_only   => 1,
            dont_copy_prefs    => 1,
            userprefs_filename => "/etc/mail/spamassassin.cf"});

    my $status = $spamtest->check($mail);
    close(IN);
	
	my $hits = $status->get_hits;
	my $req = $status->get_required_hits();
	my $names = $status->get_names_of_tests_hit();
	my $report = $status->get_report();
		

	return ($hits, $req, $names, $report);
}

#***********************************************************************
# %PROCEDURE: spam_assassin_status
# %ARGUMENTS:
#  None
# %RETURNS:
#  A SA status object
# %DESCRIPTION:
#  Scans message using SpamAssassin (http://spamassassin.taint.org)
#***********************************************************************
sub spam_assassin_status() {
    open(IN, "<./INPUTMSG") or return 0;

    my $mail = Mail::SpamAssassin::MyMailAudit->new(data=>\*IN);
    my $spamtest =
        Mail::SpamAssassin->new({
            local_tests_only   => 1,
            dont_copy_prefs    => 1,
            userprefs_filename => "/etc/mail/spamassassin.cf"});

    my $status = $spamtest->check($mail);
    close(IN);
	
	return $status;
}

---
And this would be the filter.


sub filter_begin {

        my $hits;
        my $req;
        my $names;
        my $report;

        ($hits,$req,$names, $report) = spam_assassin_check();
        action_add_header("X-Spam-Status", "Yes, hits=$hits required=$req
tests=$names");

# 	You could also bounce and discard at this point, but I'm just
tagging for 
#	the time being and filtering it at the client end. To check for
false positives
#	If I do start dropping, I only do it if the number of hits is >
2*$req. That way
#	There is a nice grey area.

        if ($hits > $req ) {
                $is_spam=1;
                action_add_header("X-Spam-Warning", "SpamAssassin says this
message is SPAM");
                action_add_header("X-Spam-Flag", "YES");
                action_change_header("Subject", "****SPAM**** $Subject");
        } else {
                action_add_header("X-Spam-Flag", "NO");

        }
}

--





More information about the MIMEDefang mailing list