5 =head1 NAME $RCSfile: maps,v $
7 This script filters mail based on the files nulllist, blacklist and whitelist.
8 Input is an email message. This script extracts the From line and then parses
9 the email address. If the email is from a sender who should be /dev/null'ed
10 (e.g. bounce messages from mail daemons) the message will be discarded. If the
11 sender is on the blacklist then a message is sent back informing the sender that
12 he's been blacklisted. If the sender is on the white list then the email is
13 appended to the mail drop file. Otherwise a message is sent back informing the
14 sender that in order to successfully send email the sender must register for the
15 permission to do so, along with a URL that allows the sender to sign up.
23 Andrew DeFaria <Andrew@DeFaria.com>
31 Fri Nov 29 14:17:21 2002
35 $Date: 2013/06/12 14:05:47 $
42 Usage maps: [-u|ser <username>] [-ve|rbose] [-deb|ug] [-e|xecute]
45 -u|ser <username>: Set context to this username
48 -de|bug: Output debug messages
50 -[no]e|xecute: Set execute mode.
52 # (c) Copyright 2000-2006, Andrew@DeFaria.com, all rights reserved.
61 use File::Temp qw (tempfile);
62 use Net::Domain qw (hostdomain);
64 use lib $FindBin::Bin, '/opt/clearscm/lib';
74 my $userid = $ENV{USER};
76 my $logpath = "$FindBin::Bin/../log";
77 my $logfile = "$logpath/debug.log";
78 my $forwardto = $ENV{MAPS_FORWARDTO} || 'adefaria@gmail.com';
80 # For some reason I'm not parsing messages correctly but it only seems to
81 # happen when the message is piped in from the MTA. This routine will
82 # temporarily save the messages in a file.
85 my $msgfile = tempfile ();
87 # Read STDIN and write it out to the tempfile
92 # Seek to the start of the file (Note if we closed it, it would be deleted)
95 # Return the filehandle
100 my ($sender, $sender_long, $reply_to, $subject, $data) = @_;
102 open SAVED_MSG, '>>', "$logpath/$sender"
103 or die "Unable to open $logpath/$sender - $!\n";
105 print SAVED_MSG "Sender = $sender\n";
106 print SAVED_MSG "Sender long = $sender\n";
107 print SAVED_MSG "reply_to = $reply_to\n";
108 print SAVED_MSG "subject = $subject\n";
109 print SAVED_MSG "data:\n\n";
110 print SAVED_MSG $data;
111 print SAVED_MSG "*** END OF DATA***\n";
114 sub ValidDomainUser ($) {
117 my ($username, $domainname);
119 if ($sender =~ /(.*)\@(.*)/) {
126 return 1 if $domainname ne hostdomain;
128 # Let BICE email come through
129 return 1 if $username eq "bice";
131 my $uid = getpwnam $username;
133 return defined $uid ? 1 : 0;
136 sub ProcessMsgs ($$$) {
137 my ($msgfile, $username, $user_email) = @_;
142 while (!eof *$msgfile) {
143 my ($sender, $sender_long, $reply_to, $subject, $data) = ReadMsg (*$msgfile);
147 #open my $mail, '|', "/usr/lib/sendmail $forwardto"
148 #or die "Unable to open pipe to sendmail - $!";
150 #print $mail "$data\n";
153 #or die "Unable to forward email to $forwardto - $!";
156 my ($onlist, $rule, $sequence, $hit_count);
158 # Algorithm change: We now first check to see if the sender is not found
159 # in the message and skip it if so. Then we handle if we are the sender
160 # and that the from address is formatted properly. Spammers often use
161 # the senders email address (i.e. andrew@defaria.com) as their from address
162 # so we check "Andrew DeFaria <Andrew@DeFaria.com>", which they have never
163 # forged. This catches a lot of spam actually.
165 # Next we check to see if the sender is on our whitelist. If so then we let
166 # them in. This allows us to say whitelist josephrosenberg@hotmail.com while
167 # still nulllisting all of the other hotmail.com spammers.
169 # Next we process blacklisted people as they are also of high priority.
171 # Then we process nulllist people.
173 # Finally, we handle return processing
175 # Special sender handling:
176 if ($sender !~ /.+\@.+/) {
177 verbose "Sender not found in message or invalid";
181 if ($sender eq $user_email and
182 (lc ($sender_long) !~ lc ("\"$username\" <$user_email>") and
183 lc ($sender_long) !~ lc ("$username <$user_email>"))) {
184 verbose "Nulllisting message from sender ($sender_long) pretending to be $user_email";
190 ($onlist, $rule, $sequence, $hit_count) = OnWhitelist $sender;
193 if (ValidDomainUser $sender) {
194 verbose "Whitelisting $sender";
195 Whitelist $sender, $data, $sequence, $hit_count;
197 verbose "Sender from this domain but user not found";
205 ($onlist, $rule, $sequence, $hit_count) = OnBlacklist $sender;
208 verbose "Blacklisting $sender";
209 my @msg = split /\n/, $data;
211 Blacklist $sender, $sequence, $hit_count, @msg;
216 ($onlist, $rule, $sequence, $hit_count) = OnNulllist $sender;
219 verbose "Nulllisting $sender";
220 Nulllist $sender, $sequence, $hit_count;
225 verbose "Returning message from $sender";
226 ReturnMsg $sender, $reply_to, $subject, $data;
232 'user=s' => \$userid,
233 'verbose' => sub { set_verbose },
234 'debug' => sub { set_debug },
235 'execute!' => \$execute,
236 'forwardto=s' => \$forwardto
241 if ($ARGV[0] and $ARGV[0] ne "") {
242 open $msgfile, $ARGV[0];
245 Error "Unable to open file ($ARGV[0]): $!\n";
249 $msgfile = SaveStdin;
252 verbose "Starting MAPS....";
254 my ($username, $user_email) = SetContext $userid
255 or die "$userid is not a registered MAPS user\n";
257 ProcessMsgs $msgfile, $username, $user_email;