From 052f26f3ada1042afa5acadbecc48b487f4e2d52 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 27 Feb 2016 21:57:57 +0000 Subject: move executables to script/ directory This seems to match more closely with what is expected of Perl packages based on how blib is used. Hopefully makes the top-level source tree less cluttered and things easier-to-find. --- script/public-inbox-mda | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100755 script/public-inbox-mda (limited to 'script/public-inbox-mda') diff --git a/script/public-inbox-mda b/script/public-inbox-mda new file mode 100755 index 00000000..24feeb81 --- /dev/null +++ b/script/public-inbox-mda @@ -0,0 +1,111 @@ +#!/usr/bin/perl -w +# 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 File::Path::Expand qw/expand_filename/; +use IPC::Run qw(run); +use PublicInbox::MDA; +use PublicInbox::Filter; +use PublicInbox::Config; + +# n.b: hopefully we can setup the emergency path without bailing due to +# user error, we really want to setup the emergency destination ASAP +# in case there's bugs in our code or user error. +my $emergency = $ENV{PI_EMERGENCY} || '~/.public-inbox/emergency/'; +$emergency = expand_filename($emergency); + +# this reads the message from stdin +my $filter = Email::Filter->new(emergency => $emergency); +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); # first check +defined $dst or exit(1); +my $main_repo = $dst->{mainrepo} or exit(1); +my $filtered; # string dest + +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 $msg = Email::MIME->new(\$filtered); + $filtered = undef; + $filter->simple($msg); + + 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($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($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; + local $ENV{GIT_COMMITTER_EMAIL} = $recipient; + local $ENV{GIT_COMMITTER_NAME} = $dst->{listname}; + + $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 + +# we depend on "report_safe 0" in /etc/spamassassin/*.cf with --headers +# 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 ($msg, $out) = @_; + eval { + my $orig = $msg->as_string; + run([qw/spamc -E --headers/], \$orig, $out); + }; + + 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; + }; +} -- cgit v1.2.3-24-ge0c7