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 $
41 Usage maps: [-u|ser <username>] [-ve|rbose] [-deb|ug] [-e|xecute]
44 -u|ser <username>: Set context to this username
47 -de|bug: Output debug messages
49 -[no]e|xecute: Set execute mode.
50 -f|ile <file>: File to use as a test message
52 # (c) Copyright 2000-2021, Andrew@DeFaria.com, all rights reserved.
63 use File::Temp qw (tempfile);
64 use Net::Domain qw (hostdomain);
66 use lib "$FindBin::Bin/../lib";
67 use lib "$FindBin::Bin/../../lib";
80 my $userid = $ENV{USER};
84 # For some reason I'm not parsing messages correctly but it only seems to
85 # happen when the message is piped in from the MTA. This routine will
86 # temporarily save the messages in a file.
89 my $msgfile = tempfile ();
91 # Read STDIN and write it out to the tempfile
96 # Seek to the start of the file (Note if we closed it, it would be deleted)
99 # Return the filehandle
103 sub ValidDomainUser($) {
106 my ($username, $domainname);
108 if ($sender =~ /(.*)\@(.*)/) {
115 return 1 if $domainname ne hostdomain;
117 # Let BICE email come through
118 return 1 if $username eq "bice";
120 my $uid = getpwnam $username;
122 return defined $uid ? 1 : 0;
128 return "$rec->{pattern}\@$rec->{domain}:$rec->{sequence}/$rec->{hit_count}";
131 sub ProcessMsgs ($$$) {
132 my ($msgfile, $username, $user_email) = @_;
134 return unless $opts{execute};
136 while (!eof $msgfile) {
137 my %msgInfo = ReadMsg $msgfile;
139 my ($onlist, $rec, $sequence, $hit_count);
141 # Algorithm change: We now first check to see if the sender is not found
142 # in the message and skip it if so. Then we handle if we are the sender
143 # and that the from address is formatted properly. Spammers often use
144 # the senders email address (i.e. andrew@defaria.com) as their from address
145 # so we check "Andrew DeFaria <Andrew@DeFaria.com>", which they have never
146 # forged. This catches a lot of spam actually.
148 # Next we check to see if the sender is on our whitelist. If so then we let
149 # them in. This allows us to say whitelist josephrosenberg@hotmail.com while
150 # still nulllisting all of the other hotmail.com spammers.
152 # Next we process blacklisted people as they are also of high priority.
154 # Then we process nulllist people.
156 # Finally, we handle return processing
158 # Discard any email with an invalid email address
159 next unless Email::Valid->address($msgInfo{sender});
161 if ($msgInfo{sender} eq $user_email and
162 (lc ($msgInfo{sender_long}) !~ lc ("\"$username\" <$user_email>") and
163 lc ($msgInfo{sender_long}) !~ lc ("$username <$user_email>"))) {
164 $log->msg("Nulllisting message from sender ($msgInfo{sender_long}) pretending to be $user_email");
169 # Discard messges coming from andrew@clearscm.com because I don't send from
171 if (lc $msgInfo{to} eq 'andrew@clearscm.com') {
172 $log->msg("Nulllisting message from Andrew\@ClearSCM.com since I don't send from that email address");
178 ($onlist, $rec) = OnWhitelist $msgInfo{sender};
181 if (ValidDomainUser $msgInfo{sender}) {
182 $log->msg("Whitelisting $msgInfo{sender} - Rule: " . formatRule($rec));
184 Whitelist $msgInfo{sender}, $msgInfo{data}, $rec->{sequence}, $rec->{hit_count};
186 $log->msg("Sender ($msgInfo{sender}) from this domain but user not found");
188 Nulllist $msgInfo{sender};
195 ($onlist, $rec) = OnBlacklist $msgInfo{sender};
198 $log->msg("Blacklisting $msgInfo{sender} - Rule: " . formatRule($rec));
202 sender => $msgInfo{sender},
203 sequence => $rec->{sequence},
204 hit_count => $rec->{hit_count},
205 data => $msgInfo{data},
212 ($onlist, $rec) = OnNulllist $msgInfo{sender};
215 $log->msg("Nulllisting $msgInfo{sender} - Rule: " . formatRule($rec));
217 Nulllist $msgInfo{sender}, $rec->{sequence}, $rec->{hit_count};
223 $log->msg("Returning message from $msgInfo{sender}");
227 sender => $msgInfo{sender},
228 reply_to => $msgInfo{reply_to},
229 subject => $msgInfo{subject},
230 data => $msgInfo{data},
245 path => '/var/local/log',
246 timestamped => 'yes',
252 if ($ARGV[0] and $ARGV[0] ne '') {
253 open $msgfile, '<', $ARGV[0];
256 $log->err("Unable to open file ($ARGV[0]): $!");
260 $msgfile = SaveStdin;
264 FindUser(userid => $userid);
268 ProcessMsgs $msgfile, $user->{name}, lc $user->{email};