X-Git-Url: http://git.jankratochvil.net/?p=PerlMail.git;a=blobdiff_plain;f=perlmail-sendmail;h=f819bccb40b2d599ae2e38766fcaa0aa8a844616;hp=e2ff291ed5bde45d473ecc3c3347fadffc504eed;hb=9d03569bd26dfb0f54f21063445fc9d28ed1c4d3;hpb=4dd3b07cdaef34d607899f7c5fdaa648dbbc798c diff --git a/perlmail-sendmail b/perlmail-sendmail index e2ff291..f819bcc 100755 --- a/perlmail-sendmail +++ b/perlmail-sendmail @@ -7,49 +7,20 @@ $VERSION=do { my @r=(q$Revision$=~/\d+/g); sprintf "%d.".("%03d"x$#r),@r; }; use strict; use warnings; +use File::Basename; +BEGIN { + use lib $ENV{"PERLMAIL_BASEDIR"} || File::Basename::dirname($0); + use PerlMail::Config; + } + require Getopt::Long; use POSIX qw(WIFEXITED WEXITSTATUS WIFSIGNALED WTERMSIG WIFSTOPPED WSTOPSIG); -require Mail::Header; +require MIME::Head; # inherits Mail::Header require Mail::Address; -require File::Basename; -my $sendmail_orig=(-x ($_="/usr/sbin/sendmail-orig") ? $_ : "/usr/sbin/sendmail"); -my $HOME="/home/lace"; -my $opt_F; -sub FromAddress -{ -my($rcpt,$iserror)=@_; - return Mail::Address->new( - (defined $opt_F ? $opt_F : "Jan Kratochvil"), - (!$iserror ? 'rcpt' : 'rcpterr') - .'-' - .(defined($rcpt->user()) ? $rcpt->user() : "NOUSER") - .".AT." - .(defined($rcpt->host()) ? $rcpt->host() : "LOCAL") - .'@jankratochvil.net', - ); -} - -# RedHat sendmail-8.9.3-20/src/conf.c/HdrInfo[]/\Q/* destination fields */\E -# FIXME: Recognize "Resent-$_" headers for -t but when we are in 'resent' mode? -my @h_rcpt=( # case in-sensitive! - "To", - "Cc", - "Bcc", - "Apparently-To", - ); - -# ordering matters; first header found is substituted -# last header is subsituted if no one is found -my @h_from=( - "Resent-From", - "From", - ); - - -# FIXME: modularized unification with 'lacemail-accept' -# BEGIN lacemail-accept +# FIXME: modularized unification with 'perlmail-accept' +# BEGIN perlmail-accept our %muttrc_pending=(); sub muttrc { @@ -118,7 +89,7 @@ my(@headers)=@_; } return wantarray() ? %r : $r{$r[0]}; } -# END lacemail-accept +# END perlmail-accept sub sendmail_show { return "\"$sendmail_orig\" ".join(",",map("\"$_\"",@ARGV)); } @@ -145,8 +116,8 @@ my $opt_Q; my $opt_q; my $opt_t; our $opt_f; -#my $opt_F; # declared before &FromAddress already -my $opt_lacemail_dry_run; +our $opt_F; # from PerlMail::Config; +my $opt_perlmail_dry_run; my @ARGV_save=@ARGV; # for non-bm mode die if !Getopt::Long::GetOptions( "b=s" ,\$opt_b, @@ -155,7 +126,7 @@ die if !Getopt::Long::GetOptions( "t" ,\$opt_t, "f=s" ,\$opt_f, "F=s" ,\$opt_F, - "lacemail-dry-run+",\$opt_lacemail_dry_run, + "perlmail-dry-run+",\$opt_perlmail_dry_run, ); if (0 # RedHat sendmail-8.12.5-7/sendmail/main.c/\QDo a quick prescan of the argument list.\E @@ -173,12 +144,7 @@ if (0 # RedHat sendmail-8.9.3-20/src/main.c/main()/\Qif (FullName != NULL)\E # for $opt_F is implemented by Mail::Address in our &FromAddress -my $head=Mail::Header->new(\*STDIN); -# We may (=will) change the contents and send it multiple times -if (defined(my $msgid=$head->get("Message-ID"))) { - $head->delete("Message-ID"); - $head->replace("X-LaceMail-sendmail-Message-ID",$msgid); - } +my $head=MIME::Head->new(\*STDIN); # options leave in @ARGV, addresses to @addr: my @args=@ARGV; # temporary @ARGV=(); # options @@ -216,18 +182,35 @@ my $from_headername; my $muttrc_From=parseone(scalar muttrc_get("from")); # may get undef()!; parseone() may be redundant $muttrc_From=$muttrc_From->address() if $muttrc_From; $opt_f=undef() if defined($opt_f) && $muttrc_From && lc($opt_f) eq lc($muttrc_From); - my @from_val; for (@h_from) { $from_headername=$_; # leave last item in $from_headername - last if @from_val=$head->get($from_headername); - } - @from_val=map({ ($_->address()); } map({ (Mail::Address->parse($_)); } @from_val)); - $from_headername=undef() if !(1==@from_val && $muttrc_From && lc($from_val[0]) eq lc($muttrc_From)); + next if !(my @from_val=$head->get($from_headername)); + @from_val=map({ ($_->address()); } map({ (Mail::Address->parse($_)); } @from_val)); + $from_headername=undef() if !(1==@from_val && $muttrc_From && lc($from_val[0]) eq lc($muttrc_From)); + last; + } # fallthru with $from_headername remaining set if last headername did not exist # now $from_headername contains the header name to be replaced w/substituted value } +# to be utilized later by &FromAddress +our $is_pgp; # from PerlMail::Config; +$is_pgp=(1 + && do { local $_=$head->mime_attr("Content-Type"); $_ && ~m#^multipart/(?:signed|encrypted)$#; } + && do { local $_=$head->mime_attr("Content-Type.protocol"); $_ && ~m#^application/pgp\b#; } + ); + my $exitcode=0; -my @rcpts=(@addr ? @addr : (undef())); # !defined($rcpt) if we have no recipients +# !defined($rcpt) if we have no recipients +# make the list unique to prevent dupes being normally filtered by sendmail(8) +# one '{' is block-wrapper, another '{' is hash-indirection! +# hash keys are just strings, never refs! +# unify the list as Mail::Address instances +my @rcpts=(!@addr ? (undef()) : values(%{{ map({ + my $obj=$_; + $obj=parseone $obj if !ref $obj; + (!defined $obj ? () : (lc($obj->address())=>$obj)); + } @addr) }})); + my $stdin_body=(@rcpts<=1 ? undef() : do { # store input data only if it will be used multiple times local $/=undef(); ; @@ -238,10 +221,6 @@ for my $rcpt (@rcpts) { if (defined $rcpt) { # !defined($rcpt) if we have no recipients local $_; - if (!ref $rcpt) { - $rcpt=parseone $rcpt; - next if !defined $rcpt; - } $opt_f=FromAddress($rcpt,1)->address() if !defined $opt_f; $head->replace($from_headername,FromAddress($rcpt,0)->format()) if $from_headername; } @@ -253,10 +232,11 @@ for my $rcpt (@rcpts) { # "From/Resent-From" should be handled by our &FromAddress push @ARGV,"-F",$opt_F if defined $opt_F; push @ARGV,$rcpt->address() if defined $rcpt; + push @ARGV,@addr_addon; local $SIG{"PIPE"}=sub { die "Got SIGPIPE from ".sendmail_show(); }; local *SENDMAIL; - if ($opt_lacemail_dry_run) { + if ($opt_perlmail_dry_run) { print sendmail_show()."\n"; *SENDMAIL=\*STDOUT; } @@ -265,7 +245,7 @@ for my $rcpt (@rcpts) { sendmail_orig_exec() if !$pid; # child } $head->print(\*SENDMAIL); - print "\n"; # Mail::Header->print() eats the empty line but it doesn't print it + print SENDMAIL "\n"; # MIME::Head->print() eats the empty line but it doesn't print it if (defined($stdin_body)) { print SENDMAIL $stdin_body; } @@ -276,7 +256,7 @@ for my $rcpt (@rcpts) { } } - next if $opt_lacemail_dry_run; # don't close our STDOUT as it is aliased to *SENDMAIL + next if $opt_perlmail_dry_run; # don't close our STDOUT as it is aliased to *SENDMAIL close SENDMAIL or warn "close(".sendmail_show()."): $?=".join(",", (!WIFEXITED($?) ? () : ("EXITSTATUS(".WEXITSTATUS($?).")")), (!WIFSIGNALED($?) ? () : ("TERMSIG(" .WTERMSIG($?) .")")),