]> Sergey Matveev's repositories - public-inbox.git/commitdiff
flesh out MDA and simplify config setup
authorEric Wong <e@80x24.org>
Tue, 1 Apr 2014 23:07:38 +0000 (23:07 +0000)
committerEric Wong <normalperson@yhbt.net>
Sat, 5 Apr 2014 06:55:35 +0000 (06:55 +0000)
We will be reusing the config parsing code for the CGI
script, too.

MANIFEST
lib/PublicInbox/Config.pm
public-inbox-mda
t/fail-bin/spamc [new file with mode: 0755]
t/main-bin/spamc [new file with mode: 0755]
t/mda.t [new file with mode: 0644]

index cddd320eead71fd6d4c1e351b46a9d1724e9bb63..3dba694221e858a2a9b376a55188da6ff1f1aa38 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -1,9 +1,16 @@
 .gitignore
 COPYING
 Documentation/design_notes.txt
+INSTALL
+MANIFEST
 Makefile.PL
 README
+examples/public-inbox-config
+lib/PublicInbox.pm
+lib/PublicInbox/Config.pm
+lib/PublicInbox/Feed.pm
 lib/PublicInbox/Filter.pm
+lib/PublicInbox/View.pm
 public-inbox-mda
 sa_config/Makefile
 sa_config/README
@@ -12,4 +19,11 @@ sa_config/user/.spamassassin/user_prefs
 scripts/dc-dlvr
 scripts/import_gmane_spool
 scripts/report-spam
+t/config.t
+t/fail-bin/spamc
+t/feed.t
 t/filter.t
+t/main-bin/spamc
+t/mda.t
+t/precheck.t
+t/view.t
index d91c28a91ab15e014e9db0e45b38091fe5bb8517..9ba4ad32901f501d011c6a88f531914471d98e09 100644 (file)
@@ -3,12 +3,13 @@
 package PublicInbox::Config;
 use strict;
 use warnings;
+use File::Path::Expand qw/expand_filename/;
 
 # returns key-value pairs of config directives in a hash
 sub new {
        my ($class, $file) = @_;
 
-       local $ENV{GIT_CONFIG} = $file;
+       local $ENV{GIT_CONFIG} = defined $file ? $file : default_file();
 
        my @cfg = `git config -l`;
        $? == 0 or die "git config -l failed: $?\n";
@@ -37,4 +38,11 @@ sub lookup {
        \%rv;
 }
 
+sub default_file {
+       my $f = $ENV{PI_CONFIG};
+       return $f if defined $f;
+       my $pi_dir = $ENV{PI_DIR} || expand_filename('~/.public-inbox/');
+       "$pi_dir/config";
+}
+
 1;
index 291b55748a70fdd306eaa713e621d09a3cee2188..8f63fa7ecba133621dd807955a71947aa66262ba 100755 (executable)
@@ -3,17 +3,37 @@
 # License: AGPLv3 or later (https://www.gnu.org/licenses/agpl-3.0.txt)
 use strict;
 use warnings;
+my $usage = 'public-inbox-mda < rfc2822_message';
+
 use Email::Filter;
 use Email::Address;
-use PublicInbox::Filter;
+use File::Path::Expand qw/expand_filename/;
 use IPC::Run qw(run);
-my $usage = "public-inbox-mda main_repo fail_repo < rfc2822_message";
-my $filter = Email::Filter->new(emergency => "~/emergency.mbox");
-my $main_repo = shift @ARGV or die "Usage: $usage\n";
-my $fail_repo = shift @ARGV or die "Usage: $usage\n";
+use constant MDA => 'ssoma-mda';
+use PublicInbox;
+use PublicInbox::Filter;
+use PublicInbox::Config;
+
+# n.b: hopefully we can setup the failbox 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 $failbox = $ENV{PI_FAILBOX} || '~/public-inbox-fail.mbox';
+$failbox = expand_filename($failbox);
+
+# this reads the message from stdin
+my $filter = Email::Filter->new(emergency => $failbox);
+my $config = PublicInbox::Config->new;
+
+my $recipient = $ENV{RECIPIENT};
+defined $recipient or die "RECIPIENT not defined in ENV\n";
+my $dst = $config->lookup($recipient);
+defined $dst or exit(1);
+my $main_repo = $dst->{mainrepo} or exit(1);
+my $fail_repo = $dst->{failrepo} or exit(1);
+my $filtered; # string dest
 
-my $filtered;
-if (PublicInbox->precheck($filter) && do_spamc($filter->simple, \$filtered)) {
+if (PublicInbox->precheck($filter, $recipient) &&
+    do_spamc($filter->simple, \$filtered)) {
        # update our message with SA headers (in case our filter rejects it)
        my $simple = Email::Simple->new($filtered);
        $filtered = undef;
@@ -23,18 +43,18 @@ if (PublicInbox->precheck($filter) && do_spamc($filter->simple, \$filtered)) {
                # run spamc again on the HTML-free message
                if (do_spamc($simple, \$filtered)) {
                        $filter->simple(Email::Simple->new($filtered));
-                       $filter->pipe("ssoma-mda", $main_repo);
+                       $filter->pipe(MDA, $main_repo);
                } else {
-                       $filter->pipe("ssoma-mda", $fail_repo);
+                       $filter->pipe(MDA, $fail_repo);
                }
        } else {
                # PublicInbox::Filter nuked everything, oops :x
-               $filter->pipe("ssoma-mda", $fail_repo);
+               $filter->pipe(MDA, $fail_repo);
        }
 } else {
        # if SA thinks it's spam or there's an error:
        # don't bother with our own filtering
-       $filter->pipe("ssoma-mda", $fail_repo);
+       $filter->pipe(MDA, $fail_repo);
 }
 die "Email::Filter failed to exit\n";
 
diff --git a/t/fail-bin/spamc b/t/fail-bin/spamc
new file mode 100755 (executable)
index 0000000..209e7dc
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+cat
+exit 1
diff --git a/t/main-bin/spamc b/t/main-bin/spamc
new file mode 100755 (executable)
index 0000000..480d2f8
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+# trivial spamc mock
+exec cat
diff --git a/t/mda.t b/t/mda.t
new file mode 100644 (file)
index 0000000..9f918d3
--- /dev/null
+++ b/t/mda.t
@@ -0,0 +1,83 @@
+# Copyright (C) 2014, Eric Wong <normalperson@yhbt.net> and all contributors
+# License: AGPLv3 or later (https://www.gnu.org/licenses/agpl-3.0.txt)
+use strict;
+use warnings;
+use Test::More;
+use Email::MIME;
+use File::Temp qw/tempdir/;
+use Cwd;
+use IPC::Run qw(run);
+
+my $mda = "blib/script/public-inbox-mda";
+my $tmpdir = tempdir(CLEANUP => 1);
+my $home = "$tmpdir/pi-home";
+my $pi_home = "$home/.public-inbox";
+my $pi_config = "$pi_home/config";
+my $maindir = "$tmpdir/main.git";
+my $faildir = "$tmpdir/fail.git";
+my $main_bin = getcwd()."/t/main-bin";
+my $main_path = "$main_bin:$ENV{PATH}"; # for spamc ham mock
+my $fail_bin = getcwd()."/t/fail-bin";
+my $fail_path = "$fail_bin:$ENV{PATH}"; # for spamc spam mock
+my $addr = 'test-public@example.com';
+my $cfgpfx = "publicinbox.test";
+
+{
+       ok(-x "$main_bin/spamc",
+               "spamc ham mock found (run in top of source tree");
+       ok(-x "$fail_bin/spamc",
+               "spamc mock found (run in top of source tree");
+       ok(-x $mda, "$mda is executable");
+       is(1, mkdir($home, 0755), "setup ~/ for testing");
+       is(1, mkdir($pi_home, 0755), "setup ~/.public-inbox");
+       is(0, system(qw(git init -q --bare), $maindir), "git init (main)");
+       is(0, system(qw(git init -q --bare), $faildir), "git init (fail)");
+
+       my %cfg = (
+               "$cfgpfx.address" => $addr,
+               "$cfgpfx.mainrepo" => $maindir,
+               "$cfgpfx.failrepo" => $faildir,
+       );
+       while (my ($k,$v) = each %cfg) {
+               is(0, system(qw(git config --file), $pi_config, $k, $v),
+                       "setup $k");
+       }
+}
+
+{
+       my $failbox = "$home/fail.mbox";
+       local $ENV{PI_FAILBOX} = $failbox;
+       local $ENV{HOME} = $home;
+       local $ENV{RECIPIENT} = $addr;
+       my $simple = Email::Simple->new(<<EOF);
+From: Me <me\@example.com>
+To: You <you\@example.com>
+Cc: $addr
+Message-Id: <blah\@example.com>
+Subject: hihi
+Date: Thu, 01 Jan 1970 00:00:00 +0000
+
+EOF
+       my $in = $simple->as_string;
+
+       # ensure successful message delivery
+       {
+               local $ENV{PATH} = $main_path;
+               run([$mda], \$in);
+               local $ENV{GIT_DIR} = $maindir;
+               my $rev = `git rev-list HEAD`;
+               like($rev, qr/\A[a-f0-9]{40}/, "good revision committed");
+       }
+
+       # ensure failures work
+       {
+               local $ENV{PATH} = $fail_path;
+               run([$mda], \$in);
+               local $ENV{GIT_DIR} = $faildir;
+               my $rev = `git rev-list HEAD`;
+               like($rev, qr/\A[a-f0-9]{40}/, "bad revision committed");
+       }
+       ok(!-e $failbox, "nothing in PI_FAILBOX");
+}
+
+done_testing();