Handle hostnames with upper-case letters
[webmin.git] / sendmail / filter.pl
1 #!/usr/local/bin/perl
2 # filter.pl
3
4 # read sendmail module config
5 $p = -l $0 ? readlink($0) : $0;
6 $p =~ /^(.*)\/[^\/]+$/;
7 if (open(CONF, "$1/config")) {
8         while(<CONF>) {
9                 if (/^(\S+)=(.*)/) {
10                         $config{$1} = $2;
11                         }
12                 }
13         close(CONF);
14         }
15 if (!$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>;
29 while(<STDIN>) {
30         $headers .= $_;
31         s/\r|\n//g;
32         if (/^(\S+):\s+(.*)/) {
33                 $header{lc($1)} = $2;
34                 }
35         elsif (!$_) { last; }
36         }
37 while(<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
51 if (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         }
63 else {
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
69 open(LOG, ">>$ARGV[0].log");
70 foreach $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