X-Git-Url: http://git.jankratochvil.net/?p=PerlMail.git;a=blobdiff_plain;f=perlmail-accept;h=ab934b029067bba6baad8a038ebb7a8aab20ede5;hp=1954c9978257e1b697b5e3a30359aede77897690;hb=d3a5ca9c40b4f139358524dcb9e0641802c46060;hpb=c16c395108059a2e7b4c107f6b222b3803cae34e diff --git a/perlmail-accept b/perlmail-accept index 1954c99..ab934b0 100755 --- a/perlmail-accept +++ b/perlmail-accept @@ -59,7 +59,8 @@ my $SMSmailRcpt=$SMSwebRcpt.'@sms.eurotel.cz'; my $SMScontact=''; our($Message,$Audit,@AuditStored,$store_ignore,$store_ignorenewmail,$store_profile,$DoBell); -our(%audit_profile,@sms_squeezes); # imported +our(%audit_profile,@sms_squeezes,@alternates_host); # imported +my %alternates_host; # from @alternates_host # from RedHat "procmail-3.22-5" # /i should be only $procmailFROM_DAEMON but how it can hurt to /i all? @@ -74,6 +75,7 @@ our $procmailFROM_MAILER=qr'^(((Resent-)?(From|Sender)|X-Envelope-From):|>?From my $opt_mode; my $opt_smstest; # 1 or $smscount my $opt_idle; +my $opt_dry; sub process; @@ -430,10 +432,9 @@ sub smssend { my($ignorenewmail,$smscount,%args)=@_; - my %aliases=muttrc_aliases(); my $text=audit_sms( "subject"=>unmime($Audit->subject()), - "from"=>[ map({ $_=$_->address(); $_="\L$_"; $aliases{$_} || $_; } Mail::Address->parse(unmime($Audit->from()))) ], + "from"=>[ Mail::Address->parse(unmime($Audit->from())) ], "body"=>substr(body_simple(),0,$MaxBodySMS*(1+0.25*$smscount)), %args); my $texthead=""; @@ -479,8 +480,8 @@ sub cut return "" if !defined($_) || /^\s*$/s; s/^\s*//s; s/\s*$//s; - return $_ if length($_)<64; - return substr($_,0,64)."..."; + return $_ if length($_)<128; + return substr($_,0,128)."..."; } our $profile_eval_depth=0; @@ -525,15 +526,16 @@ my($folder,$profile,%args)=@_; $profile=$store_profile if !$profile; my %do=map({ (!/=/ ? ($_=>1) : ($`=>$')); } profile_eval($profile)); - Sys::Syslog::syslog("info","%s%s: %s: %s", + Sys::Syslog::syslog("info","%s%s%s: %s: %s", + (!$opt_dry ? "" : "--dry: "), (!$store_ignore ? "" : "IGNORED[$store_ignore]: "), map({ cut($_); } $folder,address_show(unmime($Audit->from())),unmime($Audit->subject())), ) - if $do{"syslog"}; + if $do{"syslog"} || $opt_dry; $folder=~s/;.*$//s; $folder="$Mail/".$' if $folder=~/^=/; push @AuditStored,$folder if $do{"did"}; - return if $store_ignore; + return if $store_ignore || $opt_dry; $DoBell++ if $do{"bell"}; write_message($folder); smssend_tryall $store_ignorenewmail,$do{"sms"},%args if $do{"sms"}; @@ -558,6 +560,7 @@ sub write_message { my($folder)=@_; + return if $opt_dry; local *F; open F,">>$folder" or do { warn "Append \"$folder\": $!"; return 0; }; { @@ -585,9 +588,11 @@ my($message)=@_; local $Audit=Mail::Audit->new( "emergency"=>"$Mail/emergency", "data"=>[map("$_\n",split("\n",$message))], + "log"=>"$HOME/.lacemail.log", + "loglevel"=>99, ); local @AuditStored=(); - do { smssend $opt_smstest; return; } if $opt_smstest; + do { smssend 0,$opt_smstest; return; } if $opt_smstest; write_message("$Mail/input"); audit(); warn 'Corrupted $_, repaired' if defined($save_)!=defined($_) || (defined($_) && $save_ ne $_); @@ -625,6 +630,7 @@ sub razor2 } # NOTE: returns undef() if !wantarray and the first header is unrecognized +# Returns also hosts sub Received_for { my @r=(); @@ -632,10 +638,35 @@ sub Received_for my($for)=($hdr=~/\bfor\s+\?\b/); return $for if !wantarray(); push @r,$for if $for; + my($from,$fromaddr)=($hdr=~/\bfrom\s+(\S+)\b.*?\[((?:\d{1,3}\.){3}\d{1,3})\]/); + push @r,"$from:$fromaddr" if $from; } return @r; } +# Extended Mail::Audit::MAPS +# $domain,$full,[$timeout] +sub dnsbl +{ +my($domain,$full,$timeout)=@_; + + $timeout||=30; # sec + $Mail::Audit::MAPS::host=$domain; + my @hosts=map({ s/^.*://; "[$_]"; } # strip DNS part + grep({ /^([^:@]*):/ && !$alternates_host{$1}; } (Received_for())) # leave only foreign hosts + ); + splice @hosts,1 if !$full && @hosts; # "&& @hosts" to prevent: WARN: splice() offset past end of array + { + package My::Audit::Faked; + sub received { return @{$_[0]->{"received"}}; } + } + my $self_faked={ + "received"=>[@hosts], + }; + bless $self_faked,"My::Audit::Faked"; + return Mail::Audit::rblcheck($self_faked,$timeout); +} + our %muttrc_pending=(); sub muttrc { @@ -713,12 +744,26 @@ sub muttrc_aliases for my $addrobj (Mail::Address->parse($')) { my $addr=$addrobj->address(); my $ref=\$r{"\L$addr"}; - $$ref=$key if !$$ref; + $$ref=$key if !$$ref; # use always the first occurence to prefer nicks } } return %r; } +# FIXME: Unify +# BEGIN lacemail-sendmail +# return: Mail::Address instance or undef() +sub parseone +{ +my($line)=@_; + + return undef() if !defined $line; + my @r=Mail::Address->parse($line); + warn "Got ".scalar(@r)." addresses while wanting just one; when parsing: $line" if 1!=@r; + return $r[0]; +} +# END lacemail-sendmail + # FIXME: host may get multiple recipients and thus not showing "for <...>" # FIXME: muttrc_get("from") is too strict sub store_muttrc_alternates @@ -729,11 +774,22 @@ my($prefix,$profile)=@_; my $alternatesre=qr/$alternates/si; my $From=muttrc_get("from") or return; my $Fromre=qr/^\Q$From\E$/si; - warn "'From' \"$From\" not matches by 'alternates': $alternatesre" + my $Fromobj=parseone $From or return; + warn "'From' \"$From\" not matched by 'alternates': $alternatesre" if $From!~/$alternates/si; for my $for (reverse Received_for()) { - return if $for=~/$From/si; - next if $for!~/$alternatesre/si; + $for=~s/:.*$//; # strip IP address here + if ($Fromobj->user() ne "prog-mutt") { + next if lc($for) eq lc($From); + } + else { + my $forobj=parseone $for; + if ($forobj && $forobj->host()) { + # it is 'for' our primary address + next if lc($forobj->host()) eq lc($Fromobj->host()); # or 'return'? shouldn't matter + } + } + next if !$alternates_host{lc $for} && $for!~/$alternatesre/si; store "$prefix\L$for",($profile || []); return; } @@ -812,6 +868,7 @@ $Getopt::Long::ignorecase=0; die "GetOptions error" if !Getopt::Long::GetOptions( "inetd" ,sub { $opt_mode=\&inetd; }, "stdin" ,sub { $opt_mode=\&stdin; }, + "dry" ,\$opt_dry, "smstest:s",sub { $opt_mode=\&stdin; $opt_smstest=($_[1] || 1); }, "idle!" ,\$opt_idle, "idletest" ,sub { syslogging_restore(); print((defined($_=useridle()) ? $_ : "")."\n"); exit 0; }, @@ -827,6 +884,7 @@ open AUDIT,$filenameMyAudit or die "open \"$filenameMyAudit\": $!"; local $/=undef(); eval or die "eval \"$filenameMyAudit\": $@"; audit_init(); + %alternates_host=map((lc($_)=>1),@alternates_host); } close AUDIT or warn "close \"$filenameMyAudit\": $!";