1#!/usr/local/bin/perl 2# filter.pl 3 4# read sendmail module config 5$p = -l $0 ? readlink($0) : $0; 6$p =~ /^(.*)\/[^\/]+$/; 7if (open(CONF, "<$1/config")) { 8 while(<CONF>) { 9 if (/^(\S+)=(.*)/) { 10 $config{$1} = $2; 11 } 12 } 13 close(CONF); 14 } 15if (!$config{'sendmail_path'}) { 16 # Make some guesses about sendmail 17 if (-x "/usr/sbin/sendmail") { 18 %config = ( 'sendmail_path' => '/usr/sbin/sendmail' ); 19 } 20 elsif (-x "/usr/lib/sendmail") { 21 %config = ( 'sendmail_path' => '/usr/lib/sendmail' ); 22 } 23 else { 24 die "Failed to find sendmail or config file"; 25 } 26 } 27# read headers and body 28$fromline = <STDIN>; 29while(<STDIN>) { 30 $headers .= $_; 31 s/\r|\n//g; 32 if (/^(\S+):\s+(.*)/) { 33 $header{lc($1)} = $2; 34 } 35 elsif (!$_) { last; } 36 } 37while(<STDIN>) { 38 if ($_ eq ".\n") { 39 # Single line with a . confuses SMTP 40 $body .= ". \n"; 41 } 42 elsif ($_ eq ".\r\n") { 43 $body .= ". \r\n"; 44 } 45 else { 46 $body .= $_; 47 } 48 } 49 50# read the filter file 51if (open(FILTER, "<".$ARGV[0])) { 52 while(<FILTER>) { 53 s/\r|\n//g; 54 if (/^(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) { 55 push(@filter, [ $1, $2, $3, $4 ]); 56 } 57 elsif (/^(\S+)\s+(\S+)$/) { 58 push(@filter, [ $1, $2 ]); 59 } 60 } 61 close(FILTER); 62 } 63else { 64 print STDERR "Filter file $ARGV[0] does not exist!\n"; 65 exit 1; 66 } 67 68# run the filter to find the first matching rule 69open(LOG, ">>$ARGV[0].log"); 70foreach $f (@filter) { 71 local $field = $f->[2] eq 'body' ? $body : $header{$f->[2]}; 72 local $st = 0; 73 if ($f->[0] == 0) { 74 $st = ($field !~ /$f->[3]/i); 75 } 76 elsif ($f->[0] == 1) { 77 $st = ($field =~ /$f->[3]/i); 78 } 79 elsif ($f->[0] == 2) { 80 $st = 1; 81 } 82 if ($st) { 83 # The rule matched! 84 if ($f->[1] =~ /^\//) { 85 # Write to a file 86 open(MAIL, ">>$f->[1]") || die "Failed to open $f->[1] ; $!"; 87 print MAIL $fromline; 88 } 89 else { 90 # Forward to another address 91 open(MAIL, "|$config{'sendmail_path'} ". 92 quotemeta($f->[1])); 93 } 94 print MAIL $headers; 95 print MAIL $body; 96 close(MAIL); 97 $now = localtime(time()); 98 print LOG "[$now] [$header{'from'}] [",join(" ",@$f),"]\n"; 99 last; 100 } 101 } 102 103