X-Git-Url: http://git.jankratochvil.net/?p=PerlMail.git;a=blobdiff_plain;f=perlmail-sendmail;h=900ddede1cb714560ec5df440fba95d25a90d8ce;hp=59ea8b112b0b002843190144e1744c42cbfb51af;hb=32ab14b7e479409a3cd6cad8cf625b22454ae7f5;hpb=08463cf3bb94340b4a4bd08ae16919e96a483b38 diff --git a/perlmail-sendmail b/perlmail-sendmail index 59ea8b1..900dded 100755 --- a/perlmail-sendmail +++ b/perlmail-sendmail @@ -9,19 +9,44 @@ use warnings; 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; +require Mail::Alias; my $sendmail_orig=(-x ($_="/usr/sbin/sendmail-orig") ? $_ : "/usr/sbin/sendmail"); -my $HOME="/home/lace"; +my $HOME="/home/short"; +# Mail-Alias-1.12 defaults to "/etc/mail/aliases" which does not exist on RedHat sendmail-8.12.5-7 +# Mail-Alias-1.12 will clutter $_ ! +my @addr_addon=(Mail::Alias->new("/etc/aliases")->exists("sentout") ? ("sentout") : ()); my $opt_F; +my $is_pgp; sub FromAddress { my($rcpt,$iserror)=@_; + my $phrase=(defined $opt_F ? $opt_F : "Jan Kratochvil"); + { + last if !$is_pgp; + last if $iserror; + local *F; + local $_; + my $filename="$HOME/.gnupg/options"; + open F,$filename or do { warn "Open \"$filename\": $!"; last; }; + local $/="\n"; + my @keys=map((/^\s*default-key\s+(\S+)\s*$/),); + @keys==1 or do { warn "Found ".scalar(@keys)." 'default-key's in your \"$filename\", ignoring"; last; }; + close F or warn "Close \"$filename\": $!"; + my $default_key=$keys[0]; + $default_key=~/^[[:xdigit:]]{8}$/ or do { warn "Invalid 'default-key', ignoring: $default_key"; last; }; + return Mail::Address->new( + $phrase, + 'pgp-'.uc($default_key).'@jankratochvil.net', + ); + } + # !$is_pgp or fallback return Mail::Address->new( - (defined $opt_F ? $opt_F : "Jan Kratochvil"), + $phrase, (!$iserror ? 'rcpt' : 'rcpterr') .'-' .(defined($rcpt->user()) ? $rcpt->user() : "NOUSER") @@ -141,6 +166,8 @@ Getopt::Long::Configure( ); my $opt_b; +my $opt_Q; +my $opt_q; my $opt_t; our $opt_f; #my $opt_F; # declared before &FromAddress already @@ -148,6 +175,8 @@ my $opt_lacemail_dry_run; my @ARGV_save=@ARGV; # for non-bm mode die if !Getopt::Long::GetOptions( "b=s" ,\$opt_b, + "Q:s" ,\$opt_Q, + "q:s" ,\$opt_q, "t" ,\$opt_t, "f=s" ,\$opt_f, "F=s" ,\$opt_F, @@ -158,6 +187,8 @@ if (0 || grep({ File::Basename::basename($0) eq $_; } "newaliases","mailq","smtpd","hoststat","purgestat") # -bm: Deliver mail in the usual way (default). || (defined($opt_b) && $opt_b ne "m") + || defined $opt_q # MD_QUEUERUN + || defined $opt_Q # MD_QUEUERUN ) { @ARGV=@ARGV_save; sendmail_orig_exec(); @@ -167,7 +198,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); +my $head=MIME::Head->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"); @@ -210,18 +241,34 @@ 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 +$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(); ; @@ -232,10 +279,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; } @@ -247,6 +290,7 @@ 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; @@ -259,7 +303,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; }