August, 2013 – Graham Miln

Automating SpamCop

I am not sure how effective SpamCop is. Once upon a time I regularly reported spam to the service. In return, I was occasionally rewarded with administrators saying thanks and putting an end to the source of at least some of the spam.

A guide to typography by Albercht Dürer in Lyon’s printing museum
A guide to typography by Albercht Dürer in Lyon’s printing museum

Spam is no longer the problem it once was. Filters have become better. Multi-layer approaches trap most of the spam. My company in-boxes remain relatively free of junk mail.

This weekend we saw a spike in the amount of spam getting through to the spam mailboxes. Normally I delete mail that reaches these mailboxes. It is rare for valuable e-mail to be misclassified and for that I am grateful. I appreciate the efforts the community has gone to. SpamAssassin and greylisting in particular stand out as worthwhile spam filtering options.

This weekend saw tens of spam e-mails coming in short bursts and I wanted to at least inform someone. With this in mind, I wrote two scripts.

The first script sends e-mails currently selected in Mail.app to SpamCop:

#!/usr/bin/perl

use WWW::Mechanize;

my $applescript =<<END;
set raw to {}
tell application "Mail"
	set msgs to selection
	
	if length of msgs is not 0 then
		--display dialog "Report selected message(s) to Spamcop?"
		--if the button returned of the result is "OK" then
			
			repeat with msg in msgs
				
				set messageSource to source of msg
				set raw to raw & messageSource
				set background color of msg to gray
					
			end repeat
			
		--end if
	end if
end tell
raw
END
my $output = &osascript($applescript);
my @output = split(/, Return-Path/gsm,$output);
my @raw;
foreach my $output (@output) {
	$output = 'Return-Path'.$output if ($output =~ /^: /);
	$output = substr($output,0,49999); # spamcop constraint
	push(@raw,$output);
}

my $spamcop_url = 'https://www.spamcop.net';

my $mech = WWW::Mechanize->new();
$mech->get( $spamcop_url );

$mech->submit_form(
        form_number => 1,
        fields      => {
            username    => 'ENTER YOUR SPAMCOP USER NAME HERE',
            password    => 'ENTER YOUR SPAMCOP PASSWORD HERE',
        }
    );

foreach my $raw (@raw) {
	$mech->get($spamcop_url);
	$mech->submit_form(
			form_name => 'submitspam',
			fields => {
				spam => $raw,
			},
		);
}

if (scalar(@raw) == 1) {
	system("say 'Reported the spam email.'\n");
} else {
	system("say 'Reported ".scalar(@raw)." spam emails.'\n");
}

sub osascript {
	my ($script) = @_;
	my @script = split(/\n/,$script);
	my $script = ' -e \''.join('\' -e \'',@script).'\'';
	my $command = 'osascript' . $script;
	return `$command`;
}

As you might expect, I call this first script using Power Manager as an external script event.

On-demand script in Power Manager
On-demand script in Power Manager

The second script walks the e-mails sent to SpamCop through the reporting process:

#!/usr/bin/perl

use WWW::Mechanize;

my $spamcop_url = 'https://www.spamcop.net';

my $mech = WWW::Mechanize->new();
$mech->get( $spamcop_url );

$mech->submit_form(
        form_number => 1,
        fields      => {
            username    => 'ENTER YOUR SPAMCOP USER NAME HERE',
            password    => 'ENTER YOUR SPAMCOP PASSWORD HERE',
        }
    ) ."\n";

my $stop = 0;
while(not $stop) {

	$mech->follow_link( text => 'Report Now' ) ."\n";

	my $form = $mech->form_name( 'sendreport' );
	if ($form) {
		print "Send Report form found: ".$mech->value('reports')."\n";
		$mech->click_button( 'value' => 'Send Spam Report(s) Now' ) ."\n";
	} else {
		print "No report form button found.\n";
		$stop = 1;
	}
}

There is no magic in these scripts. They use a combination of AppleScript and perl’s wonderful WWW::Mechanize module. Hopefully they will be of use to you.