.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
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
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";
\%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;
# 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;
# 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";
--- /dev/null
+#!/bin/sh
+cat
+exit 1
--- /dev/null
+#!/bin/sh
+# trivial spamc mock
+exec cat
--- /dev/null
+# 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();