exiacl
changeset 11 2fdc6206e792
parent 10 59cd8ce44290
child 12 1f683c5eef8f
equal deleted inserted replaced
10:59cd8ce44290 11:2fdc6206e792
     1 #! /usr/bin/perl
       
     2 # © Heiko Schlittermann
       
     3 # $Id$
       
     4 # $URL$
       
     5 use constant USAGE => << '#'; 
       
     6 !ME! [options] [-- exim native options]
       
     7 
       
     8     --[no]log	show the log output	[!$Cf->log!]
       
     9     --[no]debug	show debug debug output	[!$Cf->debug!]
       
    10 
       
    11     --from=s	from:			[!$Cf->from!]
       
    12     --to=s	to:			[!$Cf->to!]
       
    13 
       
    14     --Helo=s	HELO	   		[!$Cf->Helo!]
       
    15     --From=s	MAIL FROM:		[!$Cf->From!]
       
    16     --To=s	RCPT TO: 		[!$Cf->To!]
       
    17 
       
    18     --src=s	src ip/name		[!$Cf->src!]
       
    19     --dst=s	dst ip/name		[!$Cf->dst!]
       
    20 
       
    21     --exim=s	exim binary		[!$Cf->exim!]
       
    22     --config=s	exim config file	[!$Cf->config!]
       
    23 
       
    24     $Id$
       
    25     $URL$
       
    26 #
       
    27 
       
    28 
       
    29 use strict;
       
    30 use warnings;
       
    31 use AppConfig;
       
    32 use IPC::Open3;
       
    33 use IO::Select;
       
    34 use Socket;
       
    35 use File::Basename;
       
    36 
       
    37 
       
    38 sub exim_option($);
       
    39 sub read_exim($);
       
    40 sub write_exim($@);
       
    41 sub addr(@);
       
    42 sub hostname() { chomp (my $h = `hostname -f`); return $h;  }
       
    43 
       
    44 use constant ME => basename $0;
       
    45 use constant HOSTNAME => hostname;
       
    46 use constant CONFIG => (
       
    47     { CASE => 1 },
       
    48 
       
    49     log	    => { ARGS => "!",  DEFAULT => 1 },
       
    50     debug   => { ARGS => "!",  DEFAULT => 0 },
       
    51 
       
    52     from    => { ARGS => "=s" },
       
    53     to	    => { ARGS => "=s" },
       
    54 
       
    55     Helo    => { ARGS => "=s", ALIAS => "ehlo" },
       
    56     From    => { ARGS => "=s" },
       
    57     To	    => { ARGS => "=s" },
       
    58 
       
    59     src	    => { ARGS => "=s", DEFAULT => "172.20.1.8"  },
       
    60     dst	    => { ARGS => "=s"  },		    # exim primary_hostname
       
    61 
       
    62     exim    => { ARGS => "=s", DEFAULT => $ENV{EXIM} || "exim" },
       
    63     config  => { ARGS => "=s", DEFAULT => $ENV{EXIM_CONF} || "/etc/exim/exim.conf.t" , 
       
    64 		 ALIAS => "C" },
       
    65 
       
    66     help    => { ARGS => "!" },
       
    67 
       
    68 );
       
    69 
       
    70 
       
    71 
       
    72 my $Cf;
       
    73 $Cf = new AppConfig CONFIG or die;
       
    74     $Cf->dst(addr(exim_option("primary_hostname")));
       
    75     $Cf->getopt(qw(pass_through no_ignore_case)) or die $@;
       
    76 
       
    77     $Cf->From($Cf->from)		    unless $Cf->From;
       
    78     $Cf->To($Cf->to)			    unless $Cf->To;
       
    79 
       
    80     $Cf->Helo((split/@/, $Cf->from||"")[1] || HOSTNAME)	    
       
    81 					    unless $Cf->Helo;
       
    82     $Cf->dst(addr(HOSTNAME))		    unless $Cf->dst;
       
    83 
       
    84     $@ = "";
       
    85     foreach (qw/from to src dst/) {
       
    86 	$Cf->get($_) or $@ = join " ", $@, $_;
       
    87     }
       
    88 
       
    89     die ME.": Missing values: $@\n" if $@;
       
    90 
       
    91 
       
    92 MAIN: {
       
    93     die "Config file for exim not readable ".$Cf->config.": $!\n" if not -r $Cf->config;
       
    94 
       
    95     my ($w, $r);
       
    96     my @cmd = ($Cf->exim, 
       
    97 	    -C => $Cf->config, 
       
    98 	    -oMi => addr($Cf->dst),
       
    99 	    -bhc => addr($Cf->src),
       
   100 	    @ARGV);		    # remaining args are exim native
       
   101 
       
   102     if ($Cf->help) {
       
   103 	($_ = USAGE) =~ s/!(.*?)!/eval $1||""/egs;
       
   104 	print; exit;
       
   105     }
       
   106 
       
   107     my $s = new IO::Select;
       
   108 
       
   109     print "**> @cmd\n";
       
   110 
       
   111     open3($w, $r, undef, @cmd) or die "Can't run @cmd: $!\n";
       
   112 
       
   113      read_exim $r;
       
   114     write_exim $w, "EHLO ".$Cf->Helo."\n";
       
   115      read_exim $r;
       
   116     write_exim $w, "MAIL FROM: ".$Cf->From."\n";
       
   117      read_exim $r;
       
   118     write_exim $w, "RCPT TO: ".$Cf->to."\n";
       
   119      read_exim $r;
       
   120     write_exim $w, "DATA\n";
       
   121      read_exim $r;
       
   122     write_exim $w, "From: ".$Cf->from."\n";
       
   123     write_exim $w, "To: ".$Cf->to."\n";
       
   124     write_exim $w, "Subject: Test\n";
       
   125 
       
   126     if (not -t STDIN) {
       
   127 	write_exim $w, "\n";
       
   128 	while (<>) {
       
   129 	    write_exim $w, $_;
       
   130 	}
       
   131     }
       
   132 
       
   133     write_exim $w, "\n.\n";
       
   134      read_exim $r;
       
   135     write_exim $w, "QUIT\n";
       
   136 
       
   137 
       
   138 }
       
   139 
       
   140 sub read_exim($) {
       
   141     my $fh = shift;
       
   142     while (<$fh>) {
       
   143 	/^\d\d\d/ and print("< $_") and next;
       
   144 	/^LOG/ and print and next if $Cf->log;
       
   145 	print and next if $Cf->debug;
       
   146     } continue {
       
   147 	last if /^\d\d\d\s/;
       
   148     }
       
   149     exit if /^5/;
       
   150 }
       
   151 
       
   152 sub write_exim($@) {
       
   153     my $fh = shift;
       
   154     print "> ", @_;
       
   155     print $fh @_;
       
   156 }
       
   157 
       
   158 
       
   159 {
       
   160     my %opts;
       
   161 sub exim_option($) {
       
   162     my $opt = shift;
       
   163     my $exim = $Cf->exim;
       
   164     if (!%opts) {
       
   165 	%opts = map { chomp; /^(.*?)\s*=\s*(.*)/ ? ($1, $2) : (/no_(.*)/ ? ($1, 0) : ($_, 1)) } grep !/^\s*$/, `$exim -bP`;
       
   166     }
       
   167     $opts{$opt}
       
   168 } }
       
   169 
       
   170 
       
   171 sub addr(@) {
       
   172     map { inet_ntoa scalar gethostbyname $_ } @_;
       
   173 }
       
   174 
       
   175 # vim:sts=4 sw=4 aw ai sm: