#!/usr/bin/perl -w
# Spamassassin filter for POP3 mail accounts
# Copyright (C) 2003 Nigel Horne, Wharfedale Computers Ltd.
# njh@despammed.com
# 21/11/02: Use DNS to check originating host exists to help stop s
+pam
# 22/11/02: Use MX DNS records.
# 25/11/02: Flush items put in sendmail's queue.
# 2/12/02: Handle e-mail addresses without the realname
# 21/1/03: Added spam blocker
# 22/1/03: Don't forward spam message. Improved spam warning messag
+es
# 24/1/03: Added virus checker.
use strict;
use Net::POP3;
use Net::DNS;
use Mail::SpamAssassin;
my $hostname = 'smsltd.demon.co.uk';
my $server = 'pop3.demon.co.uk';
my $user = 'smsltd';
my $password = 'xyzzy';
my $pop3 = Net::POP3->new($server, Timeout => 60) or
die "Cannot connect to $server: $!";
my $nummessages = $pop3->login($user, $password);
if(!defined $nummessages) {
die "Cannot login to $server: $!";
}
if($nummessages == 0) {
print "Nothing to do\n";
$pop3->quit();
exit 0;
}
print "Retrieving $nummessages messages from $server\n";
my $messages = $pop3->list() or
die "Cannot get list of messages from $server: $!";
my $resolver = Net::DNS::Resolver->new;
sub CATCH_PIPE { };
$SIG{'PIPE'} = "CATCH_PIPE";
MESSAGE: foreach my $msgid (keys %$messages) {
print "Forwarding message $msgid ...";
my $message = $pop3->get($msgid);
defined $message or die "\nCan't retrieve message $msgid: $!";
print "\n";
my $from = "";
my @messageArray = @$message;
foreach (@messageArray) {
if(/^From: (.+)/) {
$from = $1;
if(($from =~ /.*\<.+\@(.+)\>/) ||
($from =~ /.+\@(.+)/)) {
unless(mx($resolver, $1)) {
print "Unknown host $1 in $from, message not forwa
+rded\n";
# You may wish to comment this out
$pop3->delete($msgid);
next MESSAGE;
}
} else {
$from = 'unknown';
}
last;
}
}
if(open(CLAM, "|clamscan --disable-summary -i --mbox -")) {
print CLAM "From $from\n";
foreach (@messageArray) {
print CLAM $_;
}
if(close CLAM != 0) {
if(($from ne "") && open(MAIL, "|/usr/lib/sendmail \"-f$fr
+om\" -t -odq")) {
print MAIL "From MAILER-DAEMON\n";
print MAIL "To: $from\n";
print MAIL "Cc: postmaster\n";
print MAIL "Subject: Virus intercepted\n\n";
print MAIL "A message sent from you contained a virus.
+\n";
print MAIL "It has not been forwarded to the $hostname
+ domain.\n";
close MAIL;
}
print "Not forwarding message containing a virus\n";
# You may wish to comment this out
$pop3->delete($msgid);
next MESSAGE;
}
}
my $ma = Mail::SpamAssassin::NoMailAudit->new(data => \@messageArr
+ay);
# This often gives this error:
# Use of uninitialized value in split at /usr/lib/perl5/5.8.0/F
+ile/Spec/Unix.pm line 216
my $sa = Mail::SpamAssassin->new;
my $status = $sa->check($ma);
if($status->is_spam()) {
$status->rewrite_mail();
# Don't report if the from is forged as us, or if it's a bounc
+e
# of a bounce
my $isbounce = 0;
foreach (@messageArray) {
if(/^From: (.+)\@$hostname(.*)/) {
$isbounce = 1;
last;
}
}
$sa->report_as_spam($ma) unless $isbounce;
print "Not forwarding spam message\n";
# You may wish to comment this out...
$pop3->delete($msgid);
$status->finish();
next MESSAGE;
}
$status->finish();
undef $status;
undef $sa;
undef $ma;
# If we're here it probably isn't spam
if($from eq "") {
$from = 'unknown';
} elsif(open(MAIL, "|/usr/lib/sendmail \"-f$from\" -t -odq")) {
print MAIL "From njh\@despammed.com\n";
print MAIL "To: $from\n";
print MAIL "From: Nigel Horne <njh\@despammed.com>\n";
print MAIL "Subject: Please update your address book\n\n";
print MAIL "This is an automatic message that has been sent\n"
+;
print MAIL "in response to a message sent to $hostname.\n\n";
print MAIL "The domain $hostname is about to disappear.\n";
print MAIL "Please update your address book to point to bandsm
+an.co.uk.\n";
close MAIL;
}
if(open(MAIL, "|/usr/lib/sendmail \"-f$from\" -t")) {
# Send TO field first
foreach (@$message) {
if(/^To: (.+)\@$hostname(.*)/i) {
print MAIL "To: $1$2\n";
print "To: $1$2\n";
last;
} elsif (/^To: (.+)/i) {
print MAIL "To: $1\n";
print "To: $1\n";
last;
} elsif (/^$/) {
# End of headers. No To: found. Must be spam...
print "Not forwarding spam message\n";
$pop3->delete($msgid);
close MAIL;
next MESSAGE;
}
}
my $inhead = 1;
foreach (@$message) {
if($inhead) {
(/^From: (.+)/) && print "From: $1\n";
(/^Subject: (.+)/) && print "Subject: $1\n";
unless (/^To: .+\@$hostname.*/) {
print MAIL $_ || die "Sendmail has disappeared: $!
+\n";
}
$inhead = 0 if(/^$/);
} else {
print MAIL $_ || die "Sendmail has disappeared: $!\n";
}
}
print MAIL "\nForwarded from the pop3 account at $server.";
print MAIL "\nThis service will terminate soon. You *have* bee
+n warned.\n";
if(close MAIL) {
$pop3->delete($msgid);
} else {
warn "e-mail may have failed\n";
# You may wish to comment this out...
$pop3->delete($msgid);
}
}
}
print "Finished\n";
$pop3->quit();
|