4 # $URL$ |
4 # $URL$ |
5 use constant USAGE => << '#'; |
5 use constant USAGE => << '#'; |
6 !ME! [options] [-- exim native options] |
6 !ME! [options] [-- exim native options] |
7 |
7 |
8 --[no]log show the log output [!$Cf->log!] |
8 --[no]log show the log output [!$Cf->log!] |
9 --[no]debug show debug debug output [!$Cf->debug!] |
9 --[no]debug show debug output [!$Cf->debug!] |
10 |
10 |
11 --from=s from: [!$Cf->from!] |
11 --from=s from: [!$Cf->from!] |
12 --to=s to: [!$Cf->to!] |
12 --to=s to: [!$Cf->to!] |
13 |
13 |
14 --Helo=s HELO [!$Cf->Helo!] |
14 --Helo=s HELO [!$Cf->Helo!] |
16 --To=s RCPT TO: [!$Cf->To!] |
16 --To=s RCPT TO: [!$Cf->To!] |
17 |
17 |
18 --src=s src ip/name [!$Cf->src!] |
18 --src=s src ip/name [!$Cf->src!] |
19 --dst=s dst ip/name [!$Cf->dst!] |
19 --dst=s dst ip/name [!$Cf->dst!] |
20 |
20 |
|
21 --au user (-oMai) [!$Cf->oMai!] |
|
22 --aa authenticator (-oMaa) [!$Cf->oMaa!] |
|
23 |
21 --exim=s exim binary [!$Cf->exim!] |
24 --exim=s exim binary [!$Cf->exim!] |
22 --config=s exim config file [!$Cf->config!] |
25 --config=s exim config file [!$Cf->config!] |
23 |
26 |
24 --[no]callout [!$Cf->callout!] |
27 --[no]callout [!$Cf->callout!] |
25 |
28 |
26 Environment used: $EXIM [!$ENV{EXIM}!] |
29 Environment used: $EXIM [!$ENV{EXIM}!] |
27 $EXIM_CONF [!$ENV{EXIM_CONF}!] |
30 $EXIM_CONF [!$ENV{EXIM_CONF}!] |
28 |
31 |
48 sub write_exim($@); |
51 sub write_exim($@); |
49 sub addr(@); |
52 sub addr(@); |
50 sub hostname() { chomp (my $h = `hostname -f`); return $h; } |
53 sub hostname() { chomp (my $h = `hostname -f`); return $h; } |
51 |
54 |
52 sub which($) { (map { -x "$_/$_[0]" && "$_/$_[0]" || () } split /:/, $ENV{PATH})[0] } |
55 sub which($) { (map { -x "$_/$_[0]" && "$_/$_[0]" || () } split /:/, $ENV{PATH})[0] } |
53 sub findExim() { which("exim") || which("exim4") } |
56 sub findExim() { $ENV{EXIM} || which("exim") || which("exim4") || undef } |
54 sub guessConfig($) { qx/$_[0] "-bV"/ =~ /^Configuration.*\sis\s+(\S+)/mi and return $1 } |
57 sub guessConfig() { $_ = findExim(); qx/$_ "-bV"/ =~ /^Configuration.*\sis\s+(\S+)/mi and return $1 } |
55 |
58 |
56 use constant ME => basename $0; |
59 use constant ME => basename $0; |
57 use constant HOSTNAME => hostname; |
60 use constant HOSTNAME => hostname; |
58 use constant CONFIG => ( |
61 |
|
62 my $Cf = new AppConfig ( |
59 { CASE => 1 }, |
63 { CASE => 1 }, |
60 |
64 |
61 log => { ARGS => "!", DEFAULT => 1 }, |
65 log => { ARGS => "!", DEFAULT => 1 }, |
62 debug => { ARGS => "!", DEFAULT => 0 }, |
66 debug => { ARGS => "!", DEFAULT => 0 }, |
63 |
67 |
69 To => { ARGS => "=s" }, |
73 To => { ARGS => "=s" }, |
70 |
74 |
71 src => { ARGS => "=s", DEFAULT => "172.20.1.8" }, |
75 src => { ARGS => "=s", DEFAULT => "172.20.1.8" }, |
72 dst => { ARGS => "=s" }, # exim primary_hostname |
76 dst => { ARGS => "=s" }, # exim primary_hostname |
73 |
77 |
74 exim => { ARGS => "=s", DEFAULT => $ENV{EXIM} || findExim }, |
78 au => { ARGS => "=s" }, |
75 config => { ARGS => "=s", DEFAULT => $ENV{EXIM_CONF} || guessConfig(findExim()), |
79 aa => { ARGS => "=s" }, |
76 ALIAS => "C" }, |
80 |
|
81 exim => { ARGS => "=s", DEFAULT => findExim() }, |
|
82 config => { ARGS => "=s", DEFAULT => guessConfig(), ALIAS => "C" }, |
77 |
83 |
78 callout => { ARGS => "!", DEFAULT => 1 }, |
84 callout => { ARGS => "!", DEFAULT => 1 }, |
79 help => { ARGS => "!" }, |
85 help => { ARGS => "!" }, |
80 |
86 |
81 ); |
87 ) or die; |
82 |
88 |
83 |
|
84 |
|
85 my $Cf; |
|
86 $Cf = new AppConfig CONFIG or die; |
|
87 $Cf->exim or die "No exim binary found\n"; |
89 $Cf->exim or die "No exim binary found\n"; |
88 $Cf->dst(addr(exim_option("primary_hostname"))); |
90 $Cf->dst(addr(exim_option("primary_hostname"))); |
89 #$Cf->getopt(qw(pass_through no_ignore_case)) or die $@; |
91 #$Cf->getopt(qw(pass_through no_ignore_case)) or die $@; |
90 $Cf->getopt(qw(no_ignore_case)) or die $@; |
92 $Cf->getopt(qw(no_ignore_case)) or die $@; |
91 |
93 |
94 |
96 |
95 $Cf->Helo(map { (my $x = $_) =~ s/[<>]//g; $x } (split/@/, $Cf->from||"")[1] || HOSTNAME) |
97 $Cf->Helo(map { (my $x = $_) =~ s/[<>]//g; $x } (split/@/, $Cf->from||"")[1] || HOSTNAME) |
96 unless $Cf->Helo; |
98 unless $Cf->Helo; |
97 $Cf->dst(addr(HOSTNAME)) unless $Cf->dst; |
99 $Cf->dst(addr(HOSTNAME)) unless $Cf->dst; |
98 |
100 |
|
101 $Cf->aa("LOGIN") unless $Cf->aa || !$Cf->au; |
|
102 |
99 |
103 |
100 |
104 |
101 MAIN: { |
105 MAIN: { |
102 die "Config file for exim not readable ".$Cf->config.": $!\n" if not -r $Cf->config; |
106 die "Config file for exim not readable ".$Cf->config.": $!\n" if not -r $Cf->config; |
103 |
107 |
|
108 |
104 my ($w, $r); |
109 my ($w, $r); |
105 my @cmd = ($Cf->exim, |
110 my @cmd = ($Cf->exim, |
106 -C => $Cf->config, |
111 -C => $Cf->config, |
107 -oMi => addr($Cf->dst), |
112 -oMi => addr($Cf->dst), |
|
113 ($Cf->au ? (-oMai => $Cf->au) : ()), |
|
114 ($Cf->aa ? (-oMaa => $Cf->aa) : ()), |
108 ($Cf->callout? "-bhc" : "-bh" ) => addr($Cf->src), |
115 ($Cf->callout? "-bhc" : "-bh" ) => addr($Cf->src), |
109 @ARGV); # remaining args are exim native |
116 @ARGV); # remaining args are exim native |
110 |
117 |
111 if ($Cf->help) { |
118 if ($Cf->help) { |
112 ($_ = USAGE) =~ s/!(.*?)!/eval $1||""/egs; |
119 ($_ = USAGE) =~ s/!(.*?)!/eval $1||""/egs; |
117 foreach (qw/from to src dst/) { |
124 foreach (qw/from to src dst/) { |
118 $Cf->get($_) or $@ = join " ", $@, $_; |
125 $Cf->get($_) or $@ = join " ", $@, $_; |
119 } |
126 } |
120 die ME.": Missing values: $@\n" if $@; |
127 die ME.": Missing values: $@\n" if $@; |
121 |
128 |
122 my $s = new IO::Select; |
129 # my $s = new IO::Select; |
123 |
130 |
124 print "**> @cmd\n"; |
131 print "**> @cmd\n"; |
125 |
132 |
126 open3($w, $r, undef, @cmd) or die "Can't run @cmd: $!\n"; |
133 $SIG{PIPE} = sub { exit }; |
|
134 my $pid = open3($w, $r, undef, @cmd) or die "Can't run @cmd: $!\n"; |
127 |
135 |
128 read_exim $r; |
136 read_exim $r; |
129 write_exim $w, "EHLO ".$Cf->Helo."\n"; |
137 write_exim $w, "EHLO ".$Cf->Helo."\n"; |
130 read_exim $r; |
138 read_exim $r; |
131 write_exim $w, "MAIL FROM: ".$Cf->From."\n"; |
139 write_exim $w, "MAIL FROM: ".$Cf->From."\n"; |