]> Sergey Matveev's repositories - public-inbox.git/commitdiff
Merge branch 'listid'
authorEric Wong <e@80x24.org>
Wed, 16 Oct 2019 00:30:28 +0000 (00:30 +0000)
committerEric Wong <e@80x24.org>
Wed, 16 Oct 2019 00:30:28 +0000 (00:30 +0000)
* listid:
  wwwtext: show listid config directive(s)
  mda, watch: wire up List-ID header support
  config: allow "0" as a valid mainrepo path
  config: avoid unnecessary '||' use
  config: simplify lookup* methods
  config: we always have {-section_order}
  Config.pm: Add support for mailing list information

20 files changed:
Documentation/public-inbox-config.pod
Documentation/public-inbox-mda.pod
lib/PublicInbox/Config.pm
lib/PublicInbox/WatchMaildir.pm
lib/PublicInbox/WwwText.pm
script/public-inbox-mda
t/config.t
t/config_limiter.t
t/mda.t
t/psgi_attach.t
t/psgi_bad_mids.t
t/psgi_mount.t
t/psgi_multipart_not.t
t/psgi_scan_all.t
t/psgi_search.t
t/psgi_text.t
t/psgi_v2.t
t/watch_filter_rubylang.t
t/watch_maildir.t
t/watch_maildir_v2.t

index 8d545f7afa247339653b72ceb13183aa749fc70d..6a9739f71433c85ac8bba39ea8e0a0a11b0de5a0 100644 (file)
@@ -85,6 +85,24 @@ the given header.  Multiple values are not currently supported.
 
 Default: none; only for L<public-inbox-watch(1)> users
 
+=item publicinbox.<name>.listid
+
+The L<rfc2919|https://tools.ietf.org/html/rfc2919> header without
+angle brackets for L<public-inbox-mda(1)> deliveries and
+L<public-inbox-watch(1)>.
+
+For public-inbox-watch users, this is a shortcut for specifying
+C<publicinbox.$NAME.watchheader=List-Id:<foo.example.com>>
+
+For public-inbox-mda users, this may be used to avoid recipient
+matching via C<ORIGINAL_RECIPIENT> environment variable.
+
+This may be specified multiple times for merging multiple mailing
+lists into a single public-inbox, only one C<List-Id> header
+needs to match.
+
+Default: none
+
 =item publicinbox.<name>.nntpmirror
 
 This may be the full NNTP URL of an independently-run mirror.
index 64ec690cc568a3ccc71f085b81c4bef94221b427..921b7a152fb440a27f623f3a2255bec84e39961c 100644 (file)
@@ -25,6 +25,9 @@ L<public-inbox-config(5)/publicinboxmda.spamcheck>
 The original recipient email address, set by the MTA.  Postfix
 sets it by default, untested on other MTAs.
 
+This does not have to be set if relying on C<publicinbox.$NAME.listid>
+directives configured in L<public-inbox-config(5)>.
+
 =item PI_CONFIG
 
 Per-user config file parseable by L<git-config(1)>.
index 4fcb20d24437dee77aeb1bdf6e1ecc6f92c9466d..509de0a0b844784f6d8c05bbc5d1ac741dd4902b 100644 (file)
@@ -20,16 +20,22 @@ sub _array ($) { ref($_[0]) eq 'ARRAY' ? $_[0] : [ $_[0] ] }
 sub new {
        my ($class, $file) = @_;
        $file = default_file() unless defined($file);
-       $file = ref $file ? $file : git_config_dump($file);
-       my $self = bless $file, $class;
-
+       my $self;
+       if (ref($file) eq 'SCALAR') { # used by some tests
+               open my $fh, '<', $file or die;  # PerlIO::scalar
+               $self = config_fh_parse($fh, "\n", '=');
+       } else {
+               $self = git_config_dump($file);
+       }
+       bless $self, $class;
        # caches
-       $self->{-by_addr} ||= {};
-       $self->{-by_name} ||= {};
-       $self->{-by_newsgroup} ||= {};
-       $self->{-no_obfuscate} ||= {};
-       $self->{-limiters} ||= {};
-       $self->{-code_repos} ||= {}; # nick => PublicInbox::Git object
+       $self->{-by_addr} = {};
+       $self->{-by_list_id} = {};
+       $self->{-by_name} = {};
+       $self->{-by_newsgroup} = {};
+       $self->{-no_obfuscate} = {};
+       $self->{-limiters} = {};
+       $self->{-code_repos} = {}; # nick => PublicInbox::Git object
        $self->{-cgitrc_unparsed} = $self->{'publicinbox.cgitrc'};
 
        if (my $no = delete $self->{'publicinbox.noobfuscate'}) {
@@ -57,80 +63,50 @@ sub new {
        $self;
 }
 
+sub _fill_all ($) { each_inbox($_[0], sub {}) }
+
+sub _lookup_fill ($$$) {
+       my ($self, $cache, $key) = @_;
+       $self->{$cache}->{$key} // do {
+               _fill_all($self);
+               $self->{$cache}->{$key};
+       }
+}
+
 sub lookup {
        my ($self, $recipient) = @_;
-       my $addr = lc($recipient);
-       my $ibx = $self->{-by_addr}->{$addr};
-       return $ibx if $ibx;
-
-       my $pfx;
-
-       foreach my $k (keys %$self) {
-               $k =~ m!\A(publicinbox\.[^/]+)\.address\z! or next;
-               my $v = $self->{$k};
-               if (ref($v) eq "ARRAY") {
-                       foreach my $alias (@$v) {
-                               (lc($alias) eq $addr) or next;
-                               $pfx = $1;
-                               last;
-                       }
-               } else {
-                       (lc($v) eq $addr) or next;
-                       $pfx = $1;
-                       last;
-               }
-       }
-       defined $pfx or return;
-       _fill($self, $pfx);
+       _lookup_fill($self, '-by_addr', lc($recipient));
+}
+
+sub lookup_list_id {
+       my ($self, $list_id) = @_;
+       _lookup_fill($self, '-by_list_id', lc($list_id));
 }
 
 sub lookup_name ($$) {
        my ($self, $name) = @_;
-       $self->{-by_name}->{$name} || _fill($self, "publicinbox.$name");
+       $self->{-by_name}->{$name} // _fill($self, "publicinbox.$name");
 }
 
 sub each_inbox {
        my ($self, $cb) = @_;
-       if (my $section_order = $self->{-section_order}) {
-               foreach my $section (@$section_order) {
-                       next if $section !~ m!\Apublicinbox\.([^/]+)\z!;
-                       $self->{"publicinbox.$1.mainrepo"} or next;
-                       my $ibx = lookup_name($self, $1) or next;
-                       $cb->($ibx);
-               }
-       } else {
-               my %seen;
-               foreach my $k (keys %$self) {
-                       $k =~ m!\Apublicinbox\.([^/]+)\.mainrepo\z! or next;
-                       next if $seen{$1};
-                       $seen{$1} = 1;
-                       my $ibx = lookup_name($self, $1) or next;
-                       $cb->($ibx);
-               }
+       # may auto-vivify if config file is non-existent:
+       foreach my $section (@{$self->{-section_order}}) {
+               next if $section !~ m!\Apublicinbox\.([^/]+)\z!;
+               defined($self->{"publicinbox.$1.mainrepo"}) or next;
+               my $ibx = lookup_name($self, $1) or next;
+               $cb->($ibx);
        }
 }
 
 sub lookup_newsgroup {
        my ($self, $ng) = @_;
-       $ng = lc($ng);
-       my $ibx = $self->{-by_newsgroup}->{$ng};
-       return $ibx if $ibx;
-
-       foreach my $k (keys %$self) {
-               $k =~ m!\A(publicinbox\.[^/]+)\.newsgroup\z! or next;
-               my $v = $self->{$k};
-               my $pfx = $1;
-               if ($v eq $ng) {
-                       $ibx = _fill($self, $pfx);
-                       return $ibx;
-               }
-       }
-       undef;
+       _lookup_fill($self, '-by_newsgroup', lc($ng));
 }
 
 sub limiter {
        my ($self, $name) = @_;
-       $self->{-limiters}->{$name} ||= do {
+       $self->{-limiters}->{$name} //= do {
                require PublicInbox::Qspawn;
                my $max = $self->{"publicinboxlimiter.$name.max"} || 1;
                my $limiter = PublicInbox::Qspawn::Limiter->new($max);
@@ -139,7 +115,7 @@ sub limiter {
        };
 }
 
-sub config_dir { $ENV{PI_DIR} || "$ENV{HOME}/.public-inbox" }
+sub config_dir { $ENV{PI_DIR} // "$ENV{HOME}/.public-inbox" }
 
 sub default_file {
        my $f = $ENV{PI_CONFIG};
@@ -147,19 +123,14 @@ sub default_file {
        config_dir() . '/config';
 }
 
-sub git_config_dump {
-       my ($file) = @_;
-       my (%section_seen, @section_order);
-       return {} unless -e $file;
-       my @cmd = (qw/git config -z -l/, "--file=$file");
-       my $cmd = join(' ', @cmd);
-       my $fh = popen_rd(\@cmd) or die "popen_rd failed for $file: $!\n";
+sub config_fh_parse ($$$) {
+       my ($fh, $rs, $fs) = @_;
        my %rv;
-       local $/ = "\0";
+       my (%section_seen, @section_order);
+       local $/ = $rs;
        while (defined(my $line = <$fh>)) {
                chomp $line;
-               my ($k, $v) = split(/\n/, $line, 2);
-
+               my ($k, $v) = split($fs, $line, 2);
                my ($section) = ($k =~ /\A(\S+)\.[^\.]+\z/);
                unless (defined $section_seen{$section}) {
                        $section_seen{$section} = 1;
@@ -177,12 +148,22 @@ sub git_config_dump {
                        $rv{$k} = $v;
                }
        }
-       close $fh or die "failed to close ($cmd) pipe: $?";
        $rv{-section_order} = \@section_order;
 
        \%rv;
 }
 
+sub git_config_dump {
+       my ($file) = @_;
+       return {} unless -e $file;
+       my @cmd = (qw/git config -z -l/, "--file=$file");
+       my $cmd = join(' ', @cmd);
+       my $fh = popen_rd(\@cmd) or die "popen_rd failed for $file: $!\n";
+       my $rv = config_fh_parse($fh, "\0", "\n");
+       close $fh or die "failed to close ($cmd) pipe: $?";
+       $rv;
+}
+
 sub valid_inbox_name ($) {
        my ($name) = @_;
 
@@ -225,8 +206,8 @@ sub cgit_repo_merge ($$$) {
                $self->{-cgit_remove_suffix} and
                        $rel =~ s!/?\.git\z!!;
        }
-       $self->{"coderepo.$rel.dir"} ||= $path;
-       $self->{"coderepo.$rel.cgiturl"} ||= $rel;
+       $self->{"coderepo.$rel.dir"} //= $path;
+       $self->{"coderepo.$rel.cgiturl"} //= $rel;
 }
 
 sub is_git_dir ($) {
@@ -357,7 +338,7 @@ sub _fill_code_repo {
                # cgit supports "/blob/?id=%s", but it's only a plain-text
                # display and requires an unabbreviated id=
                foreach my $t (qw(blob commit tag)) {
-                       $git->{$t.'_url_format'} ||= map {
+                       $git->{$t.'_url_format'} //= map {
                                "$_/$t/?id=%s"
                        } @$cgits;
                }
@@ -398,7 +379,7 @@ sub _fill {
        }
        # TODO: more arrays, we should support multi-value for
        # more things to encourage decentralization
-       foreach my $k (qw(address altid nntpmirror coderepo hide)) {
+       foreach my $k (qw(address altid nntpmirror coderepo hide listid)) {
                if (defined(my $v = $self->{"$pfx.$k"})) {
                        $ibx->{$k} = _array($v);
                }
@@ -421,6 +402,11 @@ sub _fill {
                $self->{-by_addr}->{$lc_addr} = $ibx;
                $self->{-no_obfuscate}->{$lc_addr} = 1;
        }
+       if (my $listids = $ibx->{listid}) {
+               foreach my $list_id (@$listids) {
+                       $self->{-by_list_id}->{$list_id} = $ibx;
+               }
+       }
        if (my $ng = $ibx->{newsgroup}) {
                $self->{-by_newsgroup}->{$ng} = $ibx;
        }
@@ -428,7 +414,7 @@ sub _fill {
        if ($ibx->{obfuscate}) {
                $ibx->{-no_obfuscate} = $self->{-no_obfuscate};
                $ibx->{-no_obfuscate_re} = $self->{-no_obfuscate_re};
-               each_inbox($self, sub {}); # noop to populate -no_obfuscate
+               _fill_all($self); # noop to populate -no_obfuscate
        }
 
        if (my $ibx_code_repos = $ibx->{coderepo}) {
@@ -440,7 +426,7 @@ sub _fill {
                        $valid += valid_inbox_name($_) foreach (@parts);
                        $valid == scalar(@parts) or next;
 
-                       my $repo = $code_repos->{$nick} ||=
+                       my $repo = $code_repos->{$nick} //=
                                                _fill_code_repo($self, $nick);
                        push @$repo_objs, $repo if $repo;
                }
index f63140c8ed32724a20554cb9bbb014cefdfd709b..08b1aab43ad1e8a4f6b06e6def310a4ecfb29eb0 100644 (file)
@@ -59,9 +59,19 @@ sub new {
 
                my $watch = $ibx->{watch} or return;
                if (is_maildir($watch)) {
-                       if (my $wm = $ibx->{watchheader}) {
-                               my ($k, $v) = split(/:/, $wm, 2);
-                               $ibx->{-watchheader} = [ $k, qr/\Q$v\E/ ];
+                       my $watch_hdrs = [];
+                       if (my $wh = $ibx->{watchheader}) {
+                               my ($k, $v) = split(/:/, $wh, 2);
+                               push @$watch_hdrs, [ $k, qr/\Q$v\E/ ];
+                       }
+                       if (my $list_ids = $ibx->{listid}) {
+                               for (@$list_ids) {
+                                       my $re = qr/<[ \t]*\Q$_\E[ \t]*>/;
+                                       push @$watch_hdrs, ['List-Id', $re ];
+                               }
+                       }
+                       if (scalar @$watch_hdrs) {
+                               $ibx->{-watchheaders} = $watch_hdrs;
                        }
                        my $new = "$watch/new";
                        my $cur = "$watch/cur";
@@ -159,10 +169,17 @@ sub _try_path {
                my $mime = _path_to_mime($path) or next;
                my $im = _importer_for($self, $ibx);
 
-               my $wm = $ibx->{-watchheader};
-               if ($wm) {
-                       my $v = $mime->header_obj->header_raw($wm->[0]);
-                       next unless ($v && $v =~ $wm->[1]);
+               # any header match means it's eligible for the inbox:
+               if (my $watch_hdrs = $ibx->{-watchheaders}) {
+                       my $ok;
+                       my $hdr = $mime->header_obj;
+                       for my $wh (@$watch_hdrs) {
+                               my $v = $hdr->header_raw($wh->[0]);
+                               next unless defined($v) && $v =~ $wh->[1];
+                               $ok = 1;
+                               last;
+                       }
+                       next unless $ok;
                }
 
                if (my $scrub = $ibx->filter($im)) {
index 491f7e63da209bceebf1d7c4b15d00a7c8583b30..bcda665c75b9572c029b86b9a829db09e27834fa 100644 (file)
@@ -147,7 +147,7 @@ sub inbox_config ($$$) {
 [publicinbox "$name"]
        mainrepo = /path/to/top-level-inbox
 EOS
-       for my $k (qw(address)) {
+       for my $k (qw(address listid)) {
                defined(my $v = $ibx->{$k}) or next;
                $$txt .= "\t$k = $_\n" for @$v;
        }
index 4e6e04e2174ebd9ab64d815df691c68294bae99f..2655a6c5ed064aad67b97f0c575a3212cde68344 100755 (executable)
@@ -36,10 +36,21 @@ my $config = PublicInbox::Config->new;
 my $key = 'publicinboxmda.spamcheck';
 my $default = 'PublicInbox::Spamcheck::Spamc';
 my $spamc = PublicInbox::Spamcheck::get($config, $key, $default);
+my $dst;
 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 do_exit(67); # EX_NOUSER 5.1.1 user unknown
+if (defined $recipient) {
+       $dst = $config->lookup($recipient); # first check
+}
+if (!defined $dst) {
+       my $list_id = $simple->header('List-Id');
+       if (defined $list_id && $list_id =~ /<[ \t]*(.+)?[ \t]*>/) {
+               $dst = $config->lookup_list_id($1);
+       }
+       if (!defined $dst && !defined $recipient) {
+               die "ORIGINAL_RECIPIENT not defined in ENV\n";
+       }
+       defined $dst or do_exit(67); # EX_NOUSER 5.1.1 user unknown
+}
 $dst->{mainrepo} or do_exit(67);
 $dst = PublicInbox::InboxWritable->new($dst);
 
index a3c74fa2584771f02ffa5c21353471f32df13e66..3b4b12b32c20715ccfa60c6a665b43da9036212a 100644 (file)
@@ -58,30 +58,33 @@ my $tmpdir = tempdir('pi-config-XXXXXX', TMPDIR => 1, CLEANUP => 1);
 {
        my $cfgpfx = "publicinbox.test";
        my @altid = qw(serial:gmane:file=a serial:enamg:file=b);
-       my $config = PublicInbox::Config->new({
-               "$cfgpfx.address" => 'test@example.com',
-               "$cfgpfx.mainrepo" => '/path/to/non/existent',
-               "$cfgpfx.altid" => [ @altid ],
-       });
+       my $config = PublicInbox::Config->new(\<<EOF);
+$cfgpfx.address=test\@example.com
+$cfgpfx.mainrepo=/path/to/non/existent
+$cfgpfx.altid=serial:gmane:file=a
+$cfgpfx.altid=serial:enamg:file=b
+EOF
        my $ibx = $config->lookup_name('test');
        is_deeply($ibx->{altid}, [ @altid ]);
 }
 
 {
        my $pfx = "publicinbox.test";
-       my %h = (
-               "$pfx.address" => 'test@example.com',
-               "$pfx.mainrepo" => '/path/to/non/existent',
-               "publicinbox.nntpserver" => 'news.example.com',
-       );
-       my %tmp = %h;
-       my $cfg = PublicInbox::Config->new(\%tmp);
+       my $str = <<EOF;
+$pfx.address=test\@example.com
+$pfx.mainrepo=/path/to/non/existent
+publicinbox.nntpserver=news.example.com
+EOF
+       my $cfg = PublicInbox::Config->new(\$str);
        my $ibx = $cfg->lookup_name('test');
        is($ibx->{nntpserver}, 'news.example.com', 'global NNTP server');
 
-       delete $h{'publicinbox.nntpserver'};
-       $h{"$pfx.nntpserver"} = 'news.alt.example.com';
-       $cfg = PublicInbox::Config->new(\%h);
+       $str = <<EOF;
+$pfx.address=test\@example.com
+$pfx.mainrepo=/path/to/non/existent
+$pfx.nntpserver=news.alt.example.com
+EOF
+       $cfg = PublicInbox::Config->new(\$str);
        $ibx = $cfg->lookup_name('test');
        is($ibx->{nntpserver}, 'news.alt.example.com','per-inbox NNTP server');
 }
@@ -90,17 +93,15 @@ my $tmpdir = tempdir('pi-config-XXXXXX', TMPDIR => 1, CLEANUP => 1);
 {
        my $pfx = "publicinbox.test";
        my $pfx2 = "publicinbox.foo";
-       my %h = (
-               "$pfx.address" => 'test@example.com',
-               "$pfx.mainrepo" => '/path/to/non/existent',
-               "$pfx2.address" => 'foo@example.com',
-               "$pfx2.mainrepo" => '/path/to/foo',
-               lc("publicinbox.noObfuscate") =>
-                       'public-inbox.org @example.com z@EXAMPLE.com',
-               "$pfx.obfuscate" => 'true', # :<
-       );
-       my %tmp = %h;
-       my $cfg = PublicInbox::Config->new(\%tmp);
+       my $str = <<EOF;
+$pfx.address=test\@example.com
+$pfx.mainrepo=/path/to/non/existent
+$pfx2.address=foo\@example.com
+$pfx2.mainrepo=/path/to/foo
+publicinbox.noobfuscate=public-inbox.org \@example.com z\@EXAMPLE.com
+$pfx.obfuscate=true
+EOF
+       my $cfg = PublicInbox::Config->new(\$str);
        my $ibx = $cfg->lookup_name('test');
        my $re = $ibx->{-no_obfuscate_re};
        like('meta@public-inbox.org', $re,
@@ -174,16 +175,16 @@ for my $s (@valid) {
 {
        my $pfx1 = "publicinbox.test1";
        my $pfx2 = "publicinbox.test2";
-       my $h = {
-               "$pfx1.address" => 'test@example.com',
-               "$pfx1.mainrepo" => '/path/to/non/existent',
-               "$pfx2.address" => 'foo@example.com',
-               "$pfx2.mainrepo" => '/path/to/foo',
-               "$pfx1.coderepo" => 'project',
-               "$pfx2.coderepo" => 'project',
-               "coderepo.project.dir" => '/path/to/project.git',
-       };
-       my $cfg = PublicInbox::Config->new($h);
+       my $str = <<EOF;
+$pfx1.address=test\@example.com
+$pfx1.mainrepo=/path/to/non/existent
+$pfx2.address=foo\@example.com
+$pfx2.mainrepo=/path/to/foo
+$pfx1.coderepo=project
+$pfx2.coderepo=project
+coderepo.project.dir=/path/to/project.git
+EOF
+       my $cfg = PublicInbox::Config->new(\$str);
        my $t1 = $cfg->lookup_name('test1');
        my $t2 = $cfg->lookup_name('test2');
        is($t1->{-repo_objs}->[0], $t2->{-repo_objs}->[0],
index 9fafceaed5106cecc423f8f3613d8026a5331575..c1fffecf8b3c381ae91ee8a60769ff3b6fddadf2 100644 (file)
@@ -6,11 +6,11 @@ use Test::More;
 use PublicInbox::Config;
 my $cfgpfx = "publicinbox.test";
 {
-       my $config = PublicInbox::Config->new({
-               "$cfgpfx.address" => 'test@example.com',
-               "$cfgpfx.mainrepo" => '/path/to/non/existent',
-               "$cfgpfx.httpbackendmax" => 12,
-       });
+       my $config = PublicInbox::Config->new(\<<EOF);
+$cfgpfx.address=test\@example.com
+$cfgpfx.mainrepo=/path/to/non/existent
+$cfgpfx.httpbackendmax=12
+EOF
        my $ibx = $config->lookup_name('test');
        my $git = $ibx->git;
        my $old = "$git";
@@ -24,16 +24,16 @@ my $cfgpfx = "publicinbox.test";
 }
 
 {
-       my $config = PublicInbox::Config->new({
-               'publicinboxlimiter.named.max' => 3,
-               "$cfgpfx.address" => 'test@example.com',
-               "$cfgpfx.mainrepo" => '/path/to/non/existent',
-               "$cfgpfx.httpbackendmax" => 'named',
-       });
+       my $config = PublicInbox::Config->new(\<<EOF);
+publicinboxlimiter.named.max=3
+$cfgpfx.address=test\@example.com
+$cfgpfx.mainrepo=/path/to/non/existent
+$cfgpfx.httpbackendmax=named
+EOF
        my $ibx = $config->lookup_name('test');
        my $git = $ibx->git;
        ok($git, 'got git object');
-       my $old = "$git";
+       my $old = "$git"; # stringify object ref "Git(0xDEADBEEF)"
        my $lim = $git->{-httpbackend_limiter};
        ok($lim, 'Limiter exists');
        is($lim->{max}, 3, 'limiter has expected slots');
diff --git a/t/mda.t b/t/mda.t
index 5621b7d6b4e01d8449894b54ea2959cf1731db5a..3cab590b78f9a9d2728c213706bc229e3ba81aad 100644 (file)
--- a/t/mda.t
+++ b/t/mda.t
@@ -267,6 +267,34 @@ EOF
        }
 }
 
+# List-ID based delivery
+{
+       local $ENV{PI_EMERGENCY} = $faildir;
+       local $ENV{HOME} = $home;
+       local $ENV{ORIGINAL_RECIPIENT} = undef;
+       local $ENV{PATH} = $main_path;
+       my $list_id = 'foo.example.com';
+       my $mid = 'list-id-delivery@example.com';
+       my $simple = Email::Simple->new(<<EOF);
+From: user <user\@example.com>
+To: You <you\@example.com>
+Cc: $addr
+Message-ID: <$mid>
+List-Id: <$list_id>
+Subject: this message will be trained as spam
+Date: Thu, 01 Jan 1970 00:00:00 +0000
+
+EOF
+       system(qw(git config --file), $pi_config, "$cfgpfx.listid", $list_id);
+       $? == 0 or die "failed to set listid $?";
+       my $in = $simple->as_string;
+       IPC::Run::run([$mda], \$in);
+       is($?, 0, 'mda OK with List-Id match');
+       my $path = mid2path($mid);
+       my $msg = `git --git-dir=$maindir cat-file blob HEAD:$path`;
+       like($msg, qr/\Q$list_id\E/, 'delivered message w/ List-ID matches');
+}
+
 done_testing();
 
 sub fail_bad_header {
index 41695e0de961a27398bb16e00c06cd507ff6a13b..f5140f44c308371e4971439833fa6919d8f4f49c 100644 (file)
@@ -21,10 +21,10 @@ use PublicInbox::Config;
 use PublicInbox::WWW;
 use_ok 'PublicInbox::WwwAttach';
 use Plack::Builder;
-my $config = PublicInbox::Config->new({
-       "$cfgpfx.address" => $addr,
-       "$cfgpfx.mainrepo" => $maindir,
-});
+my $config = PublicInbox::Config->new(\<<EOF);
+$cfgpfx.address=$addr
+$cfgpfx.mainrepo=$maindir
+EOF
 is(0, system(qw(git init -q --bare), $maindir), "git init (main)");
 my $git = PublicInbox::Git->new($maindir);
 my $im = PublicInbox::Import->new($git, 'test', $addr);
index c561cc361323b908f9f5d1cb11c04a783d9ec316..95196a3f4b91f18859791090845be414d17ba00e 100644 (file)
@@ -53,11 +53,11 @@ Date: Fri, 02 Oct 1993 00:00:0$i +0000
 }
 $im->done;
 
-my $cfg = {
-       "$cfgpfx.address" => $ibx->{-primary_address},
-       "$cfgpfx.mainrepo" => $mainrepo,
-};
-my $config = PublicInbox::Config->new($cfg);
+my $cfg = <<EOF;
+$cfgpfx.address=$ibx->{-primary_address}
+$cfgpfx.mainrepo=$mainrepo
+EOF
+my $config = PublicInbox::Config->new(\$cfg);
 my $www = PublicInbox::WWW->new($config);
 test_psgi(sub { $www->call(@_) }, sub {
        my ($cb) = @_;
index 8da2bc8937bc140a72de2c1e92a97b04f5fb6bc6..7160896bb6c2f5071f6e7572ba5e643e89a73938 100644 (file)
@@ -21,10 +21,10 @@ use PublicInbox::Config;
 use PublicInbox::WWW;
 use Plack::Builder;
 use Plack::App::URLMap;
-my $config = PublicInbox::Config->new({
-       "$cfgpfx.address" => $addr,
-       "$cfgpfx.mainrepo" => $maindir,
-});
+my $config = PublicInbox::Config->new(\<<EOF);
+$cfgpfx.address=$addr
+$cfgpfx.mainrepo=$maindir
+EOF
 is(0, system(qw(git init -q --bare), $maindir), "git init (main)");
 my $git = PublicInbox::Git->new($maindir);
 my $im = PublicInbox::Import->new($git, 'test', $addr);
index ae248de3c44c64ad51dd60aa6703981b22f51624..2670c47a76f9afae7a5fc6738d168ac4dc27eb4a 100644 (file)
@@ -42,11 +42,11 @@ ok($im->add($mime), 'added broken multipart message');
 $im->done;
 
 my $cfgpfx = "publicinbox.v2test";
-my $cfg = {
-       "$cfgpfx.address" => $ibx->{-primary_address},
-       "$cfgpfx.mainrepo" => $repo,
-};
-my $config = PublicInbox::Config->new($cfg);
+my $cfg = <<EOF;
+$cfgpfx.address=$ibx->{-primary_address}
+$cfgpfx.mainrepo=$repo
+EOF
+my $config = PublicInbox::Config->new(\$cfg);
 my $www = PublicInbox::WWW->new($config);
 
 my ($res, $raw);
index 2f54c8207578303bcc92f06facf880d19a388c4d..2e00b6d843160e43391f2d54b8dc5227f181b42f 100644 (file)
@@ -14,13 +14,15 @@ foreach my $mod (@mods) {
 use_ok 'PublicInbox::V2Writable';
 foreach my $mod (@mods) { use_ok $mod; }
 my $tmp = tempdir('pi-scan_all-XXXXXX', TMPDIR => 1, CLEANUP => 1);
-my $cfg = {};
+my $cfg = '';
 
 foreach my $i (1..2) {
        my $cfgpfx = "publicinbox.test-$i";
-       my $addr = $cfg->{"$cfgpfx.address"} = "test-$i\@example.com";
-       my $mainrepo = $cfg->{"$cfgpfx.mainrepo"} = "$tmp/$i";
-       $cfg->{"$cfgpfx.url"} = "http://example.com/$i";
+       my $addr = "test-$i\@example.com";
+       my $mainrepo = "$tmp/$i";
+       $cfg .= "$cfgpfx.address=$addr\n";
+       $cfg .= "$cfgpfx.mainrepo=$mainrepo\n";
+       $cfg .= "$cfgpfx.url=http://example.com/$i\n";
        my $opt = {
                mainrepo => $mainrepo,
                name => "test-$i",
@@ -45,7 +47,7 @@ EOF
        ok($im->add($mime), "added message to $i");
        $im->done;
 }
-my $config = PublicInbox::Config->new($cfg);
+my $config = PublicInbox::Config->new(\$cfg);
 use_ok 'PublicInbox::WWW';
 my $www = PublicInbox::WWW->new($config);
 
index 0c4bdcd1d75c5558f7f15a303fd9cdd0bac0cb01..ab6892bcfc205aa9ffcdbdc5b595350d456ecf0a 100644 (file)
@@ -45,10 +45,10 @@ $im->done;
 PublicInbox::SearchIdx->new($ibx, 1)->index_sync;
 
 my $cfgpfx = "publicinbox.test";
-my $config = PublicInbox::Config->new({
-       "$cfgpfx.address" => 'git@vger.kernel.org',
-       "$cfgpfx.mainrepo" => $tmpdir,
-});
+my $config = PublicInbox::Config->new(\<<EOF);
+$cfgpfx.address=git\@vger.kernel.org
+$cfgpfx.mainrepo=$tmpdir
+EOF
 my $www = PublicInbox::WWW->new($config);
 test_psgi(sub { $www->call(@_) }, sub {
        my ($cb) = @_;
index bdc1ebfdbce776bb525c2b8dece599051c18d6e8..944a647637ba011140808c19c1de5650833dd1d6 100644 (file)
@@ -21,10 +21,10 @@ use PublicInbox::Config;
 use PublicInbox::WWW;
 use_ok 'PublicInbox::WwwText';
 use Plack::Builder;
-my $config = PublicInbox::Config->new({
-       "$cfgpfx.address" => $addr,
-       "$cfgpfx.mainrepo" => $maindir,
-});
+my $config = PublicInbox::Config->new(\<<EOF);
+$cfgpfx.address=$addr
+$cfgpfx.mainrepo=$maindir
+EOF
 is(0, system(qw(git init -q --bare), $maindir), "git init (main)");
 my $www = PublicInbox::WWW->new($config);
 
index 3003c5d62a7cb1397462cb0b45461eb0f7eee829..e4f7306e1606b3f93abcb33471f5b817d65c72b7 100644 (file)
@@ -54,11 +54,11 @@ $new_mid = $mids->[1];
 $im->done;
 
 my $cfgpfx = "publicinbox.v2test";
-my $cfg = {
-       "$cfgpfx.address" => $ibx->{-primary_address},
-       "$cfgpfx.mainrepo" => $mainrepo,
-};
-my $config = PublicInbox::Config->new($cfg);
+my $cfg = <<EOF;
+$cfgpfx.address=$ibx->{-primary_address}
+$cfgpfx.mainrepo=$mainrepo
+EOF
+my $config = PublicInbox::Config->new(\$cfg);
 my $www = PublicInbox::WWW->new($config);
 my ($res, $raw, @from_);
 test_psgi(sub { $www->call(@_) }, sub {
index da383c15ef4b294cbf5c047395474a8f88e66354..b28d699aa24455a25f22e64b0f5704e72d66d288 100644 (file)
@@ -70,15 +70,15 @@ spam
 EOF
        PublicInbox::Emergency->new($maildir)->prepare(\"$spam");
 
-       my %orig = (
-               "$cfgpfx.address" => $addr,
-               "$cfgpfx.mainrepo" => $mainrepo,
-               "$cfgpfx.watch" => "maildir:$maildir",
-               "$cfgpfx.filter" => 'PublicInbox::Filter::RubyLang',
-               "$cfgpfx.altid" => 'serial:alerts:file=msgmap.sqlite3',
-               "publicinboxwatch.watchspam" => "maildir:$spamdir",
-       );
-       my $config = PublicInbox::Config->new({%orig});
+       my $orig = <<EOF;
+$cfgpfx.address=$addr
+$cfgpfx.mainrepo=$mainrepo
+$cfgpfx.watch=maildir:$maildir
+$cfgpfx.filter=PublicInbox::Filter::RubyLang
+$cfgpfx.altid=serial:alerts:file=msgmap.sqlite3
+publicinboxwatch.watchspam=maildir:$spamdir
+EOF
+       my $config = PublicInbox::Config->new(\$orig);
        my $ibx = $config->lookup_name($v);
        ok($ibx, 'found inbox by name');
 
@@ -108,7 +108,7 @@ EOF
        }
        $w->scan('full');
 
-       $config = PublicInbox::Config->new({%orig});
+       $config = PublicInbox::Config->new(\$orig);
        $ibx = $config->lookup_name($v);
        ($tot, undef) = $ibx->search->reopen->query('b:spam');
        is($tot, 0, 'spam removed');
index d164bf35d35d43fedd2bfc4da05606e8f50398ba..e65ab9a947a339082e4e15dac4410ef601f5154c 100644 (file)
@@ -35,13 +35,13 @@ ok(POSIX::mkfifo("$maildir/cur/fifo", 0777),
        'create FIFO to ensure we do not get stuck on it :P');
 my $sem = PublicInbox::Emergency->new($spamdir); # create dirs
 
-my $config = PublicInbox::Config->new({
-       "$cfgpfx.address" => $addr,
-       "$cfgpfx.mainrepo" => $git_dir,
-       "$cfgpfx.watch" => "maildir:$maildir",
-       "$cfgpfx.filter" => 'PublicInbox::Filter::Vger',
-       "publicinboxlearn.watchspam" => "maildir:$spamdir",
-});
+my $config = PublicInbox::Config->new(\<<EOF);
+$cfgpfx.address=$addr
+$cfgpfx.mainrepo=$git_dir
+$cfgpfx.watch=maildir:$maildir
+$cfgpfx.filter=PublicInbox::Filter::Vger
+publicinboxlearn.watchspam=maildir:$spamdir
+EOF
 
 PublicInbox::WatchMaildir->new($config)->scan('full');
 my $git = PublicInbox::Git->new($git_dir);
index f1d6e740f013c9e83f2efb14ee0f90e90d01ee78..99551ceb7d51191c8dac2cab0482ed50e013bac2 100644 (file)
@@ -40,14 +40,14 @@ ok(POSIX::mkfifo("$maildir/cur/fifo", 0777),
        'create FIFO to ensure we do not get stuck on it :P');
 my $sem = PublicInbox::Emergency->new($spamdir); # create dirs
 
-my %orig = (
-       "$cfgpfx.address" => $addr,
-       "$cfgpfx.mainrepo" => $mainrepo,
-       "$cfgpfx.watch" => "maildir:$maildir",
-       "$cfgpfx.filter" => 'PublicInbox::Filter::Vger',
-       "publicinboxlearn.watchspam" => "maildir:$spamdir"
-);
-my $config = PublicInbox::Config->new({%orig});
+my $orig = <<EOF;
+$cfgpfx.address=$addr
+$cfgpfx.mainrepo=$mainrepo
+$cfgpfx.watch=maildir:$maildir
+$cfgpfx.filter=PublicInbox::Filter::Vger
+publicinboxlearn.watchspam=maildir:$spamdir
+EOF
+my $config = PublicInbox::Config->new(\$orig);
 my $ibx = $config->lookup_name('test');
 ok($ibx, 'found inbox by name');
 my $srch = $ibx->search;
@@ -146,12 +146,12 @@ More majordomo info at  http://vger.kernel.org/majordomo-info.html\n);
        my $v1pfx = "publicinbox.v1";
        my $v1addr = 'v1-public@example.com';
        is(system(qw(git init -q --bare), $v1repo), 0, 'v1 init OK');
-       my $config = PublicInbox::Config->new({
-               %orig,
-               "$v1pfx.address" => $v1addr,
-               "$v1pfx.mainrepo" => $v1repo,
-               "$v1pfx.watch" => "maildir:$maildir",
-       });
+       my $cfg2 = <<EOF;
+$orig$v1pfx.address=$v1addr
+$v1pfx.mainrepo=$v1repo
+$v1pfx.watch=maildir:$maildir
+EOF
+       my $config = PublicInbox::Config->new(\$cfg2);
        my $both = <<EOF;
 From: user\@example.com
 To: $addr, $v1addr
@@ -171,4 +171,35 @@ EOF
        is($both, $$msg, 'got original message back from v2');
 }
 
+{
+       my $want = <<'EOF';
+From: <u@example.com>
+List-Id: <i.want.you.to.want.me>
+Message-ID: <do.want@example.com>
+EOF
+       my $do_not_want = <<'EOF';
+From: <u@example.com>
+List-Id: <do.not.want>
+X-Mailing-List: no@example.com
+Message-ID: <do.not.want@example.com>
+EOF
+       my $cfg = $orig."$cfgpfx.listid=i.want.you.to.want.me\n";
+       PublicInbox::Emergency->new($maildir)->prepare(\$want);
+       PublicInbox::Emergency->new($maildir)->prepare(\$do_not_want);
+       my $config = PublicInbox::Config->new(\$cfg);
+       PublicInbox::WatchMaildir->new($config)->scan('full');
+       $ibx = $config->lookup_name('test');
+       my $num = $ibx->mm->num_for('do.want@example.com');
+       ok(defined $num, 'List-ID matched for watch');
+       $num = $ibx->mm->num_for('do.not.want@example.com');
+       is($num, undef, 'unaccepted List-ID matched for watch');
+
+       $cfg = $orig."$cfgpfx.watchheader=X-Mailing-List:no\@example.com\n";
+       $config = PublicInbox::Config->new(\$cfg);
+       PublicInbox::WatchMaildir->new($config)->scan('full');
+       $ibx = $config->lookup_name('test');
+       $num = $ibx->mm->num_for('do.not.want@example.com');
+       ok(defined $num, 'X-Mailing-List matched');
+}
+
 done_testing;