user/dev discussion of public-inbox itself
 help / color / mirror / code / Atom feed
From: Kyle Meyer <kyle@kyleam.com>
To: Eric Wong <e@80x24.org>
Cc: Kyle Meyer <kyle@kyleam.com>, meta@public-inbox.org
Subject: [PATCH v2] watchmaildir: support multiple watchheader values
Date: Sun, 19 Apr 2020 20:13:32 -0400	[thread overview]
Message-ID: <20200420001332.14769-1-kyle@kyleam.com> (raw)
In-Reply-To: <20200412215933.GA63705@dcvr>

The watchheader key supports only a single value.  Supporting multiple
watchheader values was mentioned in discussion [1] of 8d3e3bd8 (doc:
explain publicinbox.<name>.watchheader, 2019-10-09), and it wasn't
clear if there was a need.

One scenario in which matching multiple headers would be convenient is
when someone wants to set up public-inbox archives for some small
projects but does _not_ want to run mailing lists for them, instead
allowing others to follow the project by any of the pull mechanisms.
Using a common underlying address, an address alias for each project
is configured via a third-party email provider, with messages for each
alias being exposed as a separate public-inbox archive.  In this
setup, messages for an inbox cannot be selected by a List-ID header
but can be identified by the inbox's address in either the To or Cc
header.

To support such a use case, update the watchheader handling to
consider multiple values, accepting a message if it matches any value.
While selecting a message based on matching _any_ rather than _all_
values is motivated by the above scenario, it's worth noting that the
"any" behavior is consistent with how multiple listid config values
are handled.

[1] https://public-inbox.org/meta/20191010085118.r3amey4cayazfycb@dcvr/
---

   Changes since v1:

   * Add a test for matching multiple watchheader values.
   * Adjust WwwText::inbox_config to handle watchheader as an array.
   * Condense commit message.

 Documentation/public-inbox-config.pod |  3 +-
 MANIFEST                              |  1 +
 lib/PublicInbox/Config.pm             |  4 +-
 lib/PublicInbox/WatchMaildir.pm       |  8 +--
 lib/PublicInbox/WwwText.pm            |  4 +-
 t/watch_muliple_headers.t             | 76 +++++++++++++++++++++++++++
 6 files changed, 88 insertions(+), 8 deletions(-)
 create mode 100644 t/watch_muliple_headers.t

diff --git a/Documentation/public-inbox-config.pod b/Documentation/public-inbox-config.pod
index 4c9994dc..708a785f 100644
--- a/Documentation/public-inbox-config.pod
+++ b/Documentation/public-inbox-config.pod
@@ -88,7 +88,8 @@ Default: none; only for L<public-inbox-watch(1)> users
 		watchheader = List-Id:<test.example.com>
 
 If specified, L<public-inbox-watch(1)> will only process mail matching
-the given header.  Multiple values are not currently supported.
+the given header.  If specified multiple times, mail will be processed
+if it matches any of the values.
 
 Default: none; only for L<public-inbox-watch(1)> users
 
diff --git a/MANIFEST b/MANIFEST
index 8b724352..bfcf26b4 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -307,6 +307,7 @@ t/view.t
 t/watch_filter_rubylang.t
 t/watch_maildir.t
 t/watch_maildir_v2.t
+t/watch_muliple_headers.t
 t/www_altid.t
 t/www_listing.t
 t/www_static.t
diff --git a/lib/PublicInbox/Config.pm b/lib/PublicInbox/Config.pm
index 917939ca..458f29b2 100644
--- a/lib/PublicInbox/Config.pm
+++ b/lib/PublicInbox/Config.pm
@@ -367,7 +367,7 @@ sub _fill {
 	my $ibx = {};
 
 	foreach my $k (qw(inboxdir filter newsgroup
-			watch watchheader httpbackendmax
+			watch httpbackendmax
 			replyto feedmax nntpserver indexlevel)) {
 		my $v = $self->{"$pfx.$k"};
 		$ibx->{$k} = $v if defined $v;
@@ -388,7 +388,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 listid url
-			infourl)) {
+			infourl watchheader)) {
 		if (defined(my $v = $self->{"$pfx.$k"})) {
 			$ibx->{$k} = _array($v);
 		}
diff --git a/lib/PublicInbox/WatchMaildir.pm b/lib/PublicInbox/WatchMaildir.pm
index bea2ed2a..7b9e8915 100644
--- a/lib/PublicInbox/WatchMaildir.pm
+++ b/lib/PublicInbox/WatchMaildir.pm
@@ -59,9 +59,11 @@ sub new {
 		my $watch = $ibx->{watch} or return;
 		if (is_maildir($watch)) {
 			my $watch_hdrs = [];
-			if (my $wh = $ibx->{watchheader}) {
-				my ($k, $v) = split(/:/, $wh, 2);
-				push @$watch_hdrs, [ $k, qr/\Q$v\E/ ];
+			if (my $whs = $ibx->{watchheader}) {
+				for (@$whs) {
+					my ($k, $v) = split(/:/, $_, 2);
+					push @$watch_hdrs, [ $k, qr/\Q$v\E/ ];
+				}
 			}
 			if (my $list_ids = $ibx->{listid}) {
 				for (@$list_ids) {
diff --git a/lib/PublicInbox/WwwText.pm b/lib/PublicInbox/WwwText.pm
index 2008ba09..b23a415e 100644
--- a/lib/PublicInbox/WwwText.pm
+++ b/lib/PublicInbox/WwwText.pm
@@ -151,7 +151,7 @@ sub inbox_config ($$$) {
 	url = https://example.com/$name/
 	url = http://example.onion/$name/
 EOS
-	for my $k (qw(address listid infourl)) {
+	for my $k (qw(address listid infourl watchheader)) {
 		defined(my $v = $ibx->{$k}) or next;
 		$$txt .= "\t$k = $_\n" for @$v;
 	}
@@ -171,7 +171,7 @@ EOF
 		}
 	}
 
-	for my $k (qw(filter newsgroup obfuscate replyto watchheader)) {
+	for my $k (qw(filter newsgroup obfuscate replyto)) {
 		defined(my $v = $ibx->{$k}) or next;
 		$$txt .= "\t$k = $v\n";
 	}
diff --git a/t/watch_muliple_headers.t b/t/watch_muliple_headers.t
new file mode 100644
index 00000000..8ea4b306
--- /dev/null
+++ b/t/watch_muliple_headers.t
@@ -0,0 +1,76 @@
+# Copyright (C) 2020 all contributors <meta@public-inbox.org>
+# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
+use strict;
+use Test::More;
+use PublicInbox::Config;
+use PublicInbox::TestCommon;
+require_git(2.6);
+require_mods(qw(Search::Xapian DBD::SQLite Filesys::Notify::Simple));
+my ($tmpdir, $for_destroy) = tmpdir();
+my $inboxdir = "$tmpdir/v2";
+my $maildir = "$tmpdir/md";
+use_ok 'PublicInbox::WatchMaildir';
+use_ok 'PublicInbox::Emergency';
+my $cfgpfx = "publicinbox.test";
+my $addr = 'test-public@example.com';
+my @cmd = ('-init', '-V2', 'test', $inboxdir,
+	'http://example.com/list', $addr);
+local $ENV{PI_CONFIG} = "$tmpdir/pi_config";
+ok(run_script(\@cmd), 'public-inbox init OK');
+
+my $msg_to = <<EOF;
+From: user\@a.com
+To: $addr
+Subject: address is in to
+Message-Id: <to\@a.com>
+Date: Sat, 18 Apr 2020 00:00:00 +0000
+
+content1
+EOF
+
+my $msg_cc = <<EOF;
+From: user1\@a.com
+To: user2\@a.com
+Cc: $addr
+Subject: address is in cc
+Message-Id: <cc\@a.com>
+Date: Sat, 18 Apr 2020 00:01:00 +0000
+
+content2
+EOF
+
+my $msg_none = <<EOF;
+From: user1\@a.com
+To: user2\@a.com
+Cc: user3\@a.com
+Subject: address is not in to or cc
+Message-Id: <none\@a.com>
+Date: Sat, 18 Apr 2020 00:02:00 +0000
+
+content3
+EOF
+
+PublicInbox::Emergency->new($maildir)->prepare(\$msg_to);
+PublicInbox::Emergency->new($maildir)->prepare(\$msg_cc);
+PublicInbox::Emergency->new($maildir)->prepare(\$msg_none);
+
+my $cfg = <<EOF;
+$cfgpfx.address=$addr
+$cfgpfx.inboxdir=$inboxdir
+$cfgpfx.watch=maildir:$maildir
+$cfgpfx.watchheader=To:$addr
+$cfgpfx.watchheader=Cc:$addr
+EOF
+my $config = PublicInbox::Config->new(\$cfg);
+PublicInbox::WatchMaildir->new($config)->scan('full');
+my $ibx = $config->lookup_name('test');
+ok($ibx, 'found inbox by name');
+
+my $num = $ibx->mm->num_for('to@a.com');
+ok(defined $num, 'Matched for address in To:');
+my $num = $ibx->mm->num_for('cc@a.com');
+ok(defined $num, 'Matched for address in Cc:');
+$num = $ibx->mm->num_for('none@a.com');
+is($num, undef, 'No match without address in To: or Cc:');
+
+done_testing;

base-commit: b3f81ce0c71d5d4eca347f259b5ae69660a2cb13
-- 
2.26.0


  reply	other threads:[~2020-04-20  0:13 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-12  4:44 [RFC PATCH] watchmaildir: support multiple watchheader values Kyle Meyer
2020-04-12 21:59 ` Eric Wong
2020-04-20  0:13   ` Kyle Meyer [this message]
2020-04-20  0:45     ` [PATCH v2] " Eric Wong
2020-04-20  1:13       ` Kyle Meyer
2020-04-20  1:32         ` Eric Wong
2020-04-20  7:05           ` [PATCH] doc: HACKING: add a bit about faster testing Eric Wong
2020-04-20 13:26             ` Kyle Meyer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://public-inbox.org/README

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200420001332.14769-1-kyle@kyleam.com \
    --to=kyle@kyleam.com \
    --cc=e@80x24.org \
    --cc=meta@public-inbox.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/public-inbox.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).