#!/usr/bin/perl -w # # program: filter.pl # description: filters email into appropriate folders use diagnostics; use strict; use Mail::Audit; use Mail::SpamAssassin; # # The default mailbox for delivery # my $default = "/var/spool/mail/".getpwuid($>) is also an option. # However, I keep all of my email in ~/mail. Additionally, while I # have a ~/mail/mbox, I route *all* of my email to a specific # folder. my mbox should never contain any email, and only exists # for asthetic reasons. # my $folder = "$ENV{HOME}/mail/"; # #################################################################### # Filter spam first # We knock the spam out of the way immediately. This saves us from # wasting time processing mail which is obviously spam. # # Spam is swept to its own folder, $ENV{HOME}/mail/spam.incoming. # Mail::SpamAssassin will prepend *****SPAM***** to the subject line # of the email. Additionally, it prepends something similar to the # following paragraph to the body of the email (this, as well as # pattern matches, can be modified by editing the # spamassassin.cf file): # # SPAM: -------------------- Start SpamAssassin results ------------- # SPAM: This mail is probably spam. The original message has been altered # SPAM: so you can recognise or block similar unwanted mail in future, using # SPAM: the built-in mail filtering support in your mail reader. # SPAM: # SPAM: Content analysis details: (7.9 hits, 5 required) # SPAM: Hit! (2.1 points) BODY: /http\:\/\/\d+\.\d+\.\d+\.\d+\//is # SPAM: Hit! (2.5 points) BODY: Link to a URL containing "remove" # SPAM: Hit! (3.3 points) BODY: /click here.{0,100}<\/a>/is # SPAM: # SPAM: -------------------- End of SpamAssassin results ------------ #################################################################### # # This statement gets the next email from the queue # # my $item = Mail::SpamAssassin::MyMailAudit->new(); # The above line is the original code. MyMailAudit no # longer exists, so we rely on Mail::Audit to retrieve # the next email from the queue: # my $item = Mail::Audit->new(); # # This statement sets up our handle to SpamAssassin # my $spamtest = Mail::SpamAssassin->new(); # # Now we retrieve the status to determine whether the email is, # in fact, spam # my $status = $spamtest->check ($item); # # If the email is spam, write the email back with the aforementioned # subject and body modifications, then call the spam() subroutine # for processing (see end of script). # if ($status->is_spam ()) { $status->rewrite_mail (); spam("SpamAssassin",$folder); } #################################################################### # Mail::Audint initialization stuff #################################################################### # # If we get here, Spam::Assassin did not identify the email as spam # # Specify the location of our log file. We'll be writing several # status messages here. # open (LOG, ">$ENV{HOME}/syslog/.audit_log"); # # Get relevant fields from the message. These are pretty # self-explanatory. # my $from = $item->from(); my $to = $item->to(); my $cc = $item->cc(); my $subject = $item->subject(); my $body = $item->body(); chomp($from, $to, $cc, $subject); #################################################################### # Note that we just retrieved $body. Although I # don't use it here, this provides the ability to # filter based on the content of the body of the # email. For example: # # if ($body =~ /some_pattern/i) { #do stuff }; #################################################################### # # Start logging. # print LOG ("From: $from\n"); print LOG ("To: $to\n"); print LOG ("Subject: $subject\n"); #################################################################### # End initialization stuff #################################################################### # I know certain people. We all do. They're L-O-S-E-R-S. And, # frankly, I don't enjoy receiving email from them. The following # will identify these email addresses and route them immediately to # my trash folder (via the trash() subroutine). # for (qw(gar079@yahoo.ca badguy@loser.net nasty@whimp.org enemy@hate-u.com)) { if ($from =~ /$_/) { trash("From a loser",$folder); } } # I have some programs that email me from various machines. I want # these email to be immediately routed to ~/mail/home. # if ($from =~ /\@exitwound.org/i) { $item->accept("$folder"."home"); } # Now we come to email lists and people who commonly send me email # (hi Mom!). First, we set up a hash. The key is a pattern to be # matched against the From: line. The content is the folder name # where the mail should be stored. # my %lists = ( "apache" => "apache", "buckaroo" => "buckaroo", "christianhusbands" => "christian", "kde-linux" => "kde", "lawtech" => "lawtech", "debian-user" => "linux", "linux" => "linux", "win4lin" => "linux", "lll\@hotmail" => "Lori", "perlbot" => "perlbot", "dynamite" => "metal", "80s_Rock_Metal" => "metal", "metal" => "metal", "screamsofabel" => "metal", "mavericks" => "MomDad", "hargrojj" => "MomDad", "mutt" => "mutt", "rl2" => "rl2", "focus-linux" => "security", ); # Here, we compare the From: field with each key of the hash and # store the email in the corresponding folder # for my $pattern (keys %lists) { if (($from =~ /$pattern/i) or ($to =~ /$pattern/i) or ($cc =~ /$pattern/i)) { $item->accept("$folder"."$lists{$pattern}"); } } # The following code checks whether the To: or CC: field contains the # phrase "shock." If not, it means that the email is being sent to a # list (which has not been identified in the previous section). # Therefore, if my email address is not in the To: or CC: field, I # assume that it is spam # if ($from !~ /shock/i and $cc !~ /shock/i) { spam("Apparently not to me",$folder); } # If we've made it this far, I'm not sure what it is. Therefore, I # store it in the Bulk folder. # $item->accept("$folder"."Bulk"); # Bye-bye # exit; ################ Subroutines ################ # # This subroutine handles anything identified as spam. It is called # thusly: # # spam("Reason for calling",$folder); # # The subroutine will store the email in the ~/mail/spam.incoming # folder. It will also print a message to the log file identifying: # # (1) The spam subroutine; # (2) The line number which called the spam subroutine; and # (3) The reason for calling (i.e. "Reason for calling"). # sub spam { my ($tag, $reason, $folder) = ("spam", @_); my $line = (caller(1))[2]; print LOG ("$tag [$line]: $reason\n"); $item->accept("$folder"."spam.incoming"); } # # This subroutine handles anything identified as trash. It is called # thusly: # # trash("Reason for calling",$folder); # # (1) The trash subroutine; # (2) The line number which called the trash subroutine; and # (3) The reason for calling (i.e. "Reason for calling"). # sub trash { my ($tag, $reason, %atts) = ("trash", @_); my $line = (caller(1))[2]; print LOG ("$tag [$line]: $reason\n"); $item->accept("$folder"."trash"); }