Wednesday, December 28, 2011

spamassassin on your gmail spam folder

I get a lot of spam because I use a catch-all email address for my domain. Legitimate mail has been going into my spam folder, and I have missed it due to the volume. Here's some perl to throw out what SpamAssassin thinks is spam, and to label otherwise.

I have my required_score set to 15 in user_prefs.

#!/usr/bin/env perl

# $Id$
# vim:ts=8 sts=4 sw=4 et ai fdm=marker:

use strict;
use warnings;
use autodie;

use Mail::IMAPClient;
use Mail::SpamAssassin;

$ENV{GMAIL_USER} // die "set GMAIL_USER";
$ENV{GMAIL_PASS} // die "set GMAIL_PASS";

$| = 1;

my $imap = Mail::IMAPClient->new(
    Server           => 'imap.gmail.com',
    User             => $ENV{GMAIL_USER},
    Password         => $ENV{GMAIL_PASS},
    Ssl              => 1,
    Uid              => 1,
    IgnoreSizeErrors => 1,                  # needed for gmail
) or die "login error: $@\n";

$imap->select('[Gmail]/Spam') or die "selecting spam: ", $imap->LastError, "\n";

my $spamtest = Mail::SpamAssassin->new();

my $uid;
for $uid ( $imap->unseen ) {
    my $m;
    my $fh;

    $m = $imap->message_string($uid) // die $imap->LastError;

    my $mail   = $spamtest->parse($m);
    my $status = $spamtest->check($mail);

    print "$uid: scored ", $status->get_score, "/",
      $status->get_required_score, "... ";

    if ( $status->is_spam() ) {

        # save message, and destroy.
        open( $fh, '>', $uid );
        print {$fh} $m;
        close($fh);
        open( $fh, '>', $uid . ".report" );
        print {$fh} $status->get_report();
        close($fh);

        $imap->delete_message($uid) || die $imap->LastError;
        $imap->expunge || die $imap->LastError;
        print "deleted\n";
    }
    else {

        # label it
        my $j = 5;    # interval
        my $k = int( $status->get_score / $j ) * $j;
        $k = 0 if $k < 0;

        my $gmail_label = join( '-',
            'spamass',
            $k,
            $k + $j - 1 );

        $imap->create($gmail_label);    # ignore error
        $imap->copy( $gmail_label, $uid ) || die $imap->LastError;

        print "labelled as $gmail_label\n";
    }

    $status->finish();
    $mail->finish();
}

$spamtest->finish();
$imap->logout;

No comments: