user/dev discussion of public-inbox itself
 help / color / mirror / code / Atom feed
From: Eric Wong <e@80x24.org>
To: meta@public-inbox.org
Subject: [PATCH 2/3] replyto parameter support
Date: Wed, 14 Jun 2017 00:10:52 +0000	[thread overview]
Message-ID: <20170614001053.12823-3-e@80x24.org> (raw)
In-Reply-To: <20170614001053.12823-1-e@80x24.org>

This allows us to support centralized mailing lists (which suck,
but better than no mailing list at all).
---
 MANIFEST                  |  1 +
 lib/PublicInbox/Config.pm |  2 +-
 lib/PublicInbox/Reply.pm  | 66 +++++++++++++++++++++++++++++++++-------------
 lib/PublicInbox/View.pm   |  5 ++--
 t/reply.t                 | 67 +++++++++++++++++++++++++++++++++++++++++++++++
 t/view.t                  | 12 ---------
 6 files changed, 120 insertions(+), 33 deletions(-)
 create mode 100644 t/reply.t

diff --git a/MANIFEST b/MANIFEST
index 0475cdd..d0b7f2b 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -159,6 +159,7 @@ t/psgi_mount.t
 t/psgi_search.t
 t/psgi_text.t
 t/qspawn.t
+t/reply.t
 t/search-thr-index.t
 t/search.t
 t/spamcheck_spamc.t
diff --git a/lib/PublicInbox/Config.pm b/lib/PublicInbox/Config.pm
index f6275cd..323f8a1 100644
--- a/lib/PublicInbox/Config.pm
+++ b/lib/PublicInbox/Config.pm
@@ -136,7 +136,7 @@ sub _fill {
 
 	foreach my $k (qw(mainrepo address filter url newsgroup
 			infourl watch watchheader httpbackendmax
-			feedmax nntpserver)) {
+			replyto feedmax nntpserver)) {
 		my $v = $self->{"$pfx.$k"};
 		$rv->{$k} = $v if defined $v;
 	}
diff --git a/lib/PublicInbox/Reply.pm b/lib/PublicInbox/Reply.pm
index 73a4df1..5bbe8f4 100644
--- a/lib/PublicInbox/Reply.pm
+++ b/lib/PublicInbox/Reply.pm
@@ -17,36 +17,66 @@ sub squote_maybe ($) {
 	$val;
 }
 
+sub add_addrs {
+	my ($to, $cc, @addrs) = @_;
+	foreach my $address (@addrs) {
+		my $dst = lc($address);
+		$cc->{$dst} ||= $address;
+		$$to ||= $dst;
+	}
+}
+
+my @reply_headers = qw(From To Cc);
+my $reply_headers = join('|', @reply_headers);
+
 sub mailto_arg_link {
-	my ($hdr) = @_;
-	my %cc; # everyone else
-	my $to; # this is the From address
-
-	foreach my $h (qw(From To Cc)) {
-		my $v = $hdr->header($h);
-		defined($v) && ($v ne '') or next;
-		my @addrs = PublicInbox::Address::emails($v);
-		foreach my $address (@addrs) {
-			my $dst = lc($address);
-			$cc{$dst} ||= $address;
-			$to ||= $dst;
+	my ($ibx, $hdr) = @_;
+	my $cc = {}; # everyone else
+	my $to; # this is the From address by default
+
+	foreach my $rt (split(/\s*,\s*/, $ibx->{replyto} || ':all')) {
+		if ($rt eq ':all') {
+			foreach my $h (@reply_headers) {
+				my $v = $hdr->header($h);
+				defined($v) && ($v ne '') or next;
+				my @addrs = PublicInbox::Address::emails($v);
+				add_addrs(\$to, $cc, @addrs);
+			}
+		} elsif ($rt eq ':list') {
+			add_addrs(\$to, $cc, $ibx->{-primary_address});
+		} elsif ($rt =~ /\A(?:$reply_headers)\z/io) {
+			my $v = $hdr->header($rt);
+			if (defined($v) && ($v ne '')) {
+				my @addrs = PublicInbox::Address::emails($v);
+				add_addrs(\$to, $cc, @addrs);
+			}
+		} elsif ($rt =~ /@/) {
+			add_addrs(\$to, $cc, $rt);
+		} else {
+			warn "Unrecognized replyto = '$rt' in config\n";
 		}
 	}
-	my @arg;
 
+	my @arg;
 	my $subj = $hdr->header('Subject') || '';
 	$subj = "Re: $subj" unless $subj =~ /\bRe:/i;
 	my $mid = $hdr->header_raw('Message-ID');
 	push @arg, '--in-reply-to='.squote_maybe(mid_clean($mid));
 	my $irt = mid_escape($mid);
-	delete $cc{$to};
+	delete $cc->{$to};
 	push @arg, "--to=$to";
 	$to = uri_escape_utf8($to);
 	$subj = uri_escape_utf8($subj);
-	my @cc = sort values %cc;
-	push(@arg, map { "--cc=$_" } @cc);
-	my $cc = uri_escape_utf8(join(',', @cc));
-	my $href = "mailto:$to?In-Reply-To=$irt&Cc=${cc}&Subject=$subj";
+	my @cc = sort values %$cc;
+	$cc = '';
+	if (@cc) {
+		push(@arg, map { "--cc=$_" } @cc);
+		$cc = '&Cc=' . uri_escape_utf8(join(',', @cc));
+	}
+
+	# order matters, Subject is the least important header,
+	# so it is last in case it's lost/truncated in a copy+paste
+	my $href = "mailto:$to?In-Reply-To=$irt${cc}&Subject=$subj";
 
 	(\@arg, ascii_html($href));
 }
diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm
index 0d85581..2d81640 100644
--- a/lib/PublicInbox/View.pm
+++ b/lib/PublicInbox/View.pm
@@ -52,12 +52,13 @@ sub msg_reply {
 	 'https://en.wikipedia.org/wiki/Posting_style#Interleaved_style';
 
 	my $info = '';
-	if (my $url = $ctx->{-inbox}->{infourl}) {
+	my $ibx = $ctx->{-inbox};
+	if (my $url = $ibx->{infourl}) {
 		$url = PublicInbox::Hval::prurl($ctx->{env}, $url);
 		$info = qq(\n  List information: <a\nhref="$url">$url</a>\n);
 	}
 
-	my ($arg, $link) = PublicInbox::Reply::mailto_arg_link($hdr);
+	my ($arg, $link) = PublicInbox::Reply::mailto_arg_link($ibx, $hdr);
 	push @$arg, '/path/to/YOUR_REPLY';
 	$arg = ascii_html(join(" \\\n    ", '', @$arg));
 	<<EOF
diff --git a/t/reply.t b/t/reply.t
new file mode 100644
index 0000000..640069c
--- /dev/null
+++ b/t/reply.t
@@ -0,0 +1,67 @@
+# Copyright (C) 2017 all contributors <meta@public-inbox.org>
+# License: AGPL-3+ <https://www.gnu.org/licenses/agpl-3.0.txt>
+use strict;
+use warnings;
+use Test::More;
+use Email::MIME;
+use_ok 'PublicInbox::Reply';
+
+my @q = (
+	'foo@bar', 'foo@bar',
+	'a b', "'a b'",
+	"a'b", "'a'\\''b'",
+);
+
+while (@q) {
+	my $input = shift @q;
+	my $expect = shift @q;
+	my $res = PublicInbox::Reply::squote_maybe($input);
+	is($res, $expect, "quote $input => $res");
+}
+
+my $mime = Email::MIME->new(<<'EOF');
+From: from <from@example.com>
+To: to <to@example.com>
+Cc: cc@example.com
+Message-Id: <blah@example.com>
+Subject: hihi
+
+EOF
+
+my $hdr = $mime->header_obj;
+my $ibx = { -primary_address => 'primary@example.com' };
+
+my ($arg, $link) = PublicInbox::Reply::mailto_arg_link($ibx, $hdr);
+my $exp = [
+    '--in-reply-to=blah@example.com',
+    '--to=from@example.com',
+    '--cc=cc@example.com',
+    '--cc=to@example.com'
+];
+
+is_deeply($arg, $exp, 'default reply is to :all');
+$ibx->{replyto} = ':all';
+($arg, $link) = PublicInbox::Reply::mailto_arg_link($ibx, $hdr);
+is_deeply($arg, $exp, '":all" also works');
+
+$exp = [ '--in-reply-to=blah@example.com', '--to=primary@example.com' ];
+$ibx->{replyto} = ':list';
+($arg, $link) = PublicInbox::Reply::mailto_arg_link($ibx, $hdr);
+is_deeply($arg, $exp, '":list" works for centralized lists');
+
+$exp = [
+	 '--in-reply-to=blah@example.com',
+	 '--to=primary@example.com',
+	 '--cc=cc@example.com',
+	 '--cc=to@example.com'
+];
+$ibx->{replyto} = ':list,Cc,To';
+($arg, $link) = PublicInbox::Reply::mailto_arg_link($ibx, $hdr);
+is_deeply($arg, $exp, '":list,Cc,To" works for kinda centralized lists');
+
+$ibx->{replyto} = 'new@example.com';
+($arg, $link) = PublicInbox::Reply::mailto_arg_link($ibx, $hdr);
+$exp = [ '--in-reply-to=blah@example.com', '--to=new@example.com' ];
+is_deeply($arg, $exp, 'explicit address works, too');
+
+done_testing();
diff --git a/t/view.t b/t/view.t
index abd0001..1f4ed93 100644
--- a/t/view.t
+++ b/t/view.t
@@ -7,18 +7,6 @@ use Email::MIME;
 use Plack::Util;
 use_ok 'PublicInbox::View';
 
-my @q = (
-	'foo@bar', 'foo@bar',
-	'a b', "'a b'",
-	"a'b", "'a'\\''b'",
-);
-while (@q) {
-	my $input = shift @q;
-	my $expect = shift @q;
-	my $res = PublicInbox::Reply::squote_maybe($input);
-	is($res, $expect, "quote $input => $res");
-}
-
 # FIXME: make this test less fragile
 my $ctx = {
 	env => { HTTP_HOST => 'example.com', 'psgi.url_scheme' => 'http' },
-- 
EW


  parent reply	other threads:[~2017-06-14  0:11 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-14  0:10 [PATCH 0/3] support per-inbox "replyto" parameter Eric Wong
2017-06-14  0:10 ` [PATCH 1/3] view: split out reply logic into its own module Eric Wong
2017-06-14  0:10 ` Eric Wong [this message]
2017-06-14  0:10 ` [PATCH 3/3] reply: support Reply-To Eric Wong

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: http://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=20170614001053.12823-3-e@80x24.org \
    --to=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).