Scrub your mailbox using Spam Assassin

by Richard A. DeVenezia, Back to Home

This script is for anyone having access an 'always on' box wishing to delete spam out their individual email accounts located on one or more mail servers.

Step1: Install Perl

Step 2: Install Spam Assassin

Step 2a: Edit your .spamassassin/user-prefs. Add this line to ensure any mail with an executable attachment is discarded.
score MICROSOFT_EXECUTABLE 10

Step 3: Install this Perl script, I call it scrub.pl. It accepts a few command line options of which most people need be unconcerned. If you make delete_threshold too low you will probably delete the email informing you that you just inherited $1M from Aunt Bertha.

#!/usr/bin/perl -w

use strict;

use Mail::POP3Client;
use Mail::Audit;
use Mail::SpamAssassin;

require "$ENV{HOME}/.mail-accounts";

my @accounts = mail_accounts();
my @range = 0 .. @accounts-1;

my $delete_threshold = 6 ;
my $report_threshold = 6;

my ($argnum, $quiet, $showcleared, $showsummary, $host, $user, $pass, $account, $report_hits, $report_detail);

my $killmsg = -1;
my $showmsg = -1;
my $testmsg = 0;

for (@ARGV) { for ($_) {
    /^-v$/  && do { $quiet=0; last; };
    /^-vv$/ && do { $quiet=0; $showcleared=1; $report_threshold=0; $report_hits=1; last; };
    /^-q$/  && do { $quiet=1; last; };
    /^-vq$/ && do { $quiet=1; $showsummary=0; last; };
    /^-test$/ && do { $testmsg=1; last; };
    /^-s(.*)/ && do { $showmsg = $1; last; };
    /^-kq(.*)/ && do { $killmsg = $1; $quiet = 1; last; };
    /^-k(.*)/ && do { $killmsg = $1; last; };
    /^-h(.*)/ && do { $host = $1; last; };
    /^-u(.*)/ && do { $user = $1; last; };
    /^-p(.*)/ && do { $pass = $1; last; };
    /^-a(.*)/ && do { $account = $1; last; };
    /^-rt(.*)/ && do { $report_threshold = $1; last; };
    /^-dt(.*)/ && do { $delete_threshold = $1; last; };
    /^-hits$/ && do { $report_hits = 1; last; };
    /^-report$/ && do { $report_detail = 1; last; };
    print "\nnot an option: $_";
}}

if (!defined($account) && (($showmsg>0) || ($killmsg>0) )) {
    die "Must specify account if showing or killing\n";
}

@range = $account .. $account if defined($account) ;

$|=1; # disable output buffering

my $inspector = Mail::SpamAssassin->new;
my (@mail,$status,$pail);

for (@accounts[@range]) {
    print "\n".localtime().": $$_{HOST}..." if !$quiet;

    my $deleted = 0;

    my $pop = new Mail::POP3Client (%$_);
    unless ($pop) { warn "Couldn't connect\n"; next; }

    my $count = $pop->Count;
    if ($count < 0) { warn "Authorization failed\n"; next; }

    print "messages: $count" if !$quiet;

    next if $count==0;

    if ($killmsg > 0) { $showmsg = $killmsg; }

    if ($showmsg > 0) {
        @mail = $pop->Retrieve($showmsg);
        $pop->Delete ($showmsg) if $killmsg == $showmsg;
        $pop->Close;

        exit if ($killmsg>0 && $quiet);

        $pail = $inspector->parse (\@mail);
        $status = $inspector->check($pail);

        print "\nFrom: ",$status->get('From');
        print join("", @mail)."\n";

        if ( $report_hits || $report_detail ) {
            print "\nSpam Assassin score: ",$status->get_hits;
            print "\n",$status->get_names_of_tests_hit if $report_hits;
            print "\n",$status->get_report if $report_detail;
            print "\n";
        }
        exit;
    }

    for my $num (reverse 1..$count) {
        @mail = $pop->Retrieve($num);
        $pail =  $inspector->parse (\@mail);
        my $status = $inspector->check($pail);

        if ($status->get_hits() < $delete_threshold) {
            next if $quiet;
            next if $status->get_hits() < $report_threshold;

            print "\n$num, reporting  $delete_threshold > ".$status->get_hits()." >= $report_threshold";
            print "\n",$status->get_names_of_tests_hit if $report_hits;
            print "\n",$status->get_report if $report_detail;

            next;
        }

        if (!$quiet) {
            my $from = $status->get('From');
            $from =~ s/\n//g;
            print "\n$num, deleting ".$status->get_hits()." >= $delete_threshold, ",$from;
            print "\n",$status->get_names_of_tests_hit if $report_hits;
            print "\n",$status->get_report if $report_detail;
        }

        $status->finish();

        $pop->Delete($num) if !$testmsg;
        $deleted++;
    }

    $pop->Close;

    print "\n",
        localtime().": deleted $deleted messages, ".($count-$deleted)." remain" if $deleted;
}

print "\n";

Step 4: Create a mail accounts file for the script (don't let anyone else see this), this is the code included by the statement:
require "$ENV{HOME}/.mail-accounts";

sub mail_accounts {

@accounts = (
{ USER => "username-1", AUTH_MODE => "PASS", PASSWORD => "password-1", HOST => "mail-server-1" },
{ USER => "username-2", AUTH_MODE => "PASS", PASSWORD => "password-2", HOST => "mail-server-2" },
);

return @accounts;

}

1;

Step 5: Use cron to schedule the script to run every 15 minutes

0,15,30,45  *    * * * perl scrub >> /tmp/scrub.log
This page was last updated 5 January 2004.