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