X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=public-inbox-mda;h=24feeb81d355a8d4f188a5d7ea4bafa33c66f07a;hb=ac6f7081a484a053ddb60a2f8b6b6487664827ac;hp=6c446749c28cee37e6e8b8482a8a8c6c2c2d0fe5;hpb=1c910ebd5d088b68fd1cec41285ad62641673845;p=public-inbox.git diff --git a/public-inbox-mda b/public-inbox-mda index 6c446749..24feeb81 100755 --- a/public-inbox-mda +++ b/public-inbox-mda @@ -1,14 +1,15 @@ #!/usr/bin/perl -w -# Copyright (C) 2013, Eric Wong and all contributors +# Copyright (C) 2013-2015 all contributors # License: AGPLv3 or later (https://www.gnu.org/licenses/agpl-3.0.txt) +# +# Mail delivery agent for public-inbox, run from your MTA upon mail delivery use strict; use warnings; my $usage = 'public-inbox-mda < rfc2822_message'; use Email::Filter; +use Email::MIME; use Email::Address; -use Encode qw/decode encode/; -use Encode::MIME::Header; use File::Path::Expand qw/expand_filename/; use IPC::Run qw(run); use PublicInbox::MDA; @@ -27,27 +28,43 @@ my $config = PublicInbox::Config->new; my $recipient = $ENV{ORIGINAL_RECIPIENT}; defined $recipient or die "ORIGINAL_RECIPIENT not defined in ENV\n"; -my $dst = $config->lookup($recipient); +my $dst = $config->lookup($recipient); # first check defined $dst or exit(1); my $main_repo = $dst->{mainrepo} or exit(1); my $filtered; # string dest -if (PublicInbox::MDA->precheck($filter, $recipient) && +if (PublicInbox::MDA->precheck($filter, $dst->{address}) && do_spamc($filter->simple, \$filtered)) { # update our message with SA headers (in case our filter rejects it) - my $simple = Email::Simple->new($filtered); + my $msg = Email::MIME->new(\$filtered); $filtered = undef; - $filter->simple($simple); + $filter->simple($msg); - if (PublicInbox::Filter->run($simple)) { + my $filter_arg; + my $fcfg = $dst->{filter}; + if (!defined $fcfg || $filter eq 'reject') { + $filter_arg = $filter; + } elsif ($fcfg eq 'scrub') { + $filter_arg = undef; # the default for legacy versions + } else { + warn "publicinbox.$dst->{listname}.filter=$fcfg invalid\n"; + warn "must be either 'scrub' or 'reject' (the default)\n"; + } + + if (PublicInbox::Filter->run($msg, $filter_arg)) { # run spamc again on the HTML-free message - if (do_spamc($simple, \$filtered)) { - $simple = Email::Simple->new($filtered); - PublicInbox::MDA->set_list_headers($simple, $dst); - $filter->simple($simple); + if (do_spamc($msg, \$filtered)) { + $msg = Email::MIME->new(\$filtered); + PublicInbox::MDA->set_list_headers($msg, $dst); + $filter->simple($msg); my ($name, $email, $date) = - PublicInbox::MDA->author_info($simple); + PublicInbox::MDA->author_info($msg); + + END { + index_sync($main_repo) if ($? == 0); + }; + local $ENV{GIT_AUTHOR_NAME} = $name; local $ENV{GIT_AUTHOR_EMAIL} = $email; local $ENV{GIT_AUTHOR_DATE} = $date; @@ -57,6 +74,14 @@ if (PublicInbox::MDA->precheck($filter, $recipient) && $filter->pipe(PublicInbox::MDA->cmd, $main_repo); } } +} else { + # Ensure emergency spam gets spamassassin headers. + # This makes it easier to prioritize obvious spam from less obvious + if (defined($filtered) && $filtered ne '') { + my $drop = Email::MIME->new(\$filtered); + $filtered = undef; + $filter->simple($drop); + } } exit 0; # goes to emergency @@ -64,11 +89,23 @@ exit 0; # goes to emergency # not using Email::Filter->pipe here since we want the stdout of # the command even on failure (spamc will set $? on error). sub do_spamc { - my ($simple, $out) = @_; + my ($msg, $out) = @_; eval { - my $orig = $simple->as_string; + my $orig = $msg->as_string; run([qw/spamc -E --headers/], \$orig, $out); }; - return ($@ || $? || !defined($$out) || length($$out) == 0) ? 0 : 1; + return ($@ || $? || !defined($$out) || $$out eq '') ? 0 : 1; +} + +sub index_sync { + my ($git_dir) = @_; + + # potentially user-visible, ignore errors: + system('git', "--git-dir=$git_dir", 'update-server-info'); + + eval { + require PublicInbox::SearchIdx; + PublicInbox::SearchIdx->new($git_dir, 2)->index_sync; + }; }