unofficial mirror of meta@public-inbox.org
 help / color / mirror / Atom feed
From: Eric Wong <e@80x24.org>
To: meta@public-inbox.org
Subject: [PATCH] lei: flesh out `forwarded' kw support for Maildir and IMAP
Date: Wed, 21 Apr 2021 23:50:52 +0000	[thread overview]
Message-ID: <20210421235052.26571-1-e@80x24.org> (raw)

Maildir and IMAP can both handle `forwarded'.  Ensure we don't
lose `forwarded' when reading from stores which do not support
it, but ensure we can set it when reading from IMAP and Maildir
stores.
---
 lib/PublicInbox/LeiSearch.pm | 12 ++++++++++--
 lib/PublicInbox/LeiToMail.pm |  2 +-
 lib/PublicInbox/NetReader.pm |  1 +
 t/lei-q-kw.t                 | 31 +++++++++++++++++++++++++++++++
 xt/net_writer-imap.t         | 14 +++++++++++---
 5 files changed, 54 insertions(+), 6 deletions(-)

diff --git a/lib/PublicInbox/LeiSearch.pm b/lib/PublicInbox/LeiSearch.pm
index 082176e7..ff615d89 100644
--- a/lib/PublicInbox/LeiSearch.pm
+++ b/lib/PublicInbox/LeiSearch.pm
@@ -103,8 +103,16 @@ sub kw_changed {
 	my $xoids = xoids_for($self, $eml) // return;
 	$docids //= [];
 	@$docids = sort { $a <=> $b } values %$xoids;
-	my @cur_kw = msg_keywords($self, $docids->[0]);
-	join("\0", @$new_kw_sorted) eq join("\0", @cur_kw) ? 0 : 1;
+	my $cur_kw = msg_keywords($self, $docids->[0]);
+
+	# RFC 5550 sec 5.9 on the $Forwarded keyword states:
+	# "Once set, the flag SHOULD NOT be cleared"
+	if (exists($cur_kw->{forwarded}) &&
+			!grep(/\Aforwarded\z/, @$new_kw_sorted)) {
+		delete $cur_kw->{forwarded};
+	}
+	$cur_kw = join("\0", sort keys %$cur_kw);
+	join("\0", @$new_kw_sorted) eq $cur_kw ? 0 : 1;
 }
 
 sub all_terms {
diff --git a/lib/PublicInbox/LeiToMail.pm b/lib/PublicInbox/LeiToMail.pm
index 46a82a4b..0fa0bd9a 100644
--- a/lib/PublicInbox/LeiToMail.pm
+++ b/lib/PublicInbox/LeiToMail.pm
@@ -38,7 +38,7 @@ sub _mbox_hdr_buf ($$$) {
 		if (my $ent = $kw2status{$k}) {
 			push @{$hdr{$ent->[0]}}, $ent->[1];
 		} else { # X-Label?
-			warn "TODO: keyword `$k' not supported for mbox\n";
+			warn "# keyword `$k' not supported for mbox\n";
 		}
 	}
 	# Messages are always 'O' (non-\Recent in IMAP), it saves
diff --git a/lib/PublicInbox/NetReader.pm b/lib/PublicInbox/NetReader.pm
index 821e5d7f..0ef66fd8 100644
--- a/lib/PublicInbox/NetReader.pm
+++ b/lib/PublicInbox/NetReader.pm
@@ -8,6 +8,7 @@ use v5.10.1;
 use parent qw(Exporter PublicInbox::IPC);
 use PublicInbox::Eml;
 our %IMAPflags2kw = map {; "\\\u$_" => $_ } qw(seen answered flagged draft);
+$IMAPflags2kw{'$Forwarded'} = 'forwarded';  # RFC 5550
 
 our @EXPORT = qw(uri_section imap_uri nntp_uri);
 
diff --git a/t/lei-q-kw.t b/t/lei-q-kw.t
index c17411fb..c00a0a43 100644
--- a/t/lei-q-kw.t
+++ b/t/lei-q-kw.t
@@ -205,5 +205,36 @@ open $fh, '<', \$lei_out or BAIL_OUT $!;
 PublicInbox::MboxReader->mboxrd($fh, sub { push @another, shift });
 is($another[0]->header('Status'), 'RO', 'seen kw set');
 
+# forwarded
+{
+	local $ENV{DBG} = 1;
+	$o = "$ENV{HOME}/forwarded";
+	lei_ok(qw(q -o), $o, "m:$m");
+	my @p = glob("$o/cur/*");
+	scalar(@p) == 1 or xbail('multiple when 1 expected', \@p);
+	my $passed = $p[0];
+	$passed =~ s/,S\z/,PS/ or xbail "failed to replace $passed";
+	rename($p[0], $passed) or xbail "rename $!";
+	lei_ok(qw(q -o), $o, 'm:bogus', \'clobber maildir');
+	is_deeply([glob("$o/cur/*")], [], 'old results clobbered');
+	lei_ok(qw(q -o), $o, "m:$m");
+	@p = glob("$o/cur/*");
+	scalar(@p) == 1 or xbail('multiple when 1 expected', \@p);
+	like($p[0], qr/,PS/, 'passed (Forwarded) flag kept');
+	lei_ok(qw(q -o), "mboxrd:$o.mboxrd", "m:$m");
+	open $fh, '<', "$o.mboxrd" or xbail $!;
+	my @res;
+	PublicInbox::MboxReader->mboxrd($fh, sub { push @res, shift });
+	scalar(@res) == 1 or xbail('multiple when 1 expected', \@res);
+	is($res[0]->header('Status'), 'RO', 'seen kw set');
+	is($res[0]->header('X-Status'), undef, 'no X-Status');
+
+	lei_ok(qw(q -o), "mboxrd:$o.mboxrd", 'bogus-for-import-before');
+	lei_ok(qw(q -o), $o, "m:$m");
+	@p = glob("$o/cur/*");
+	scalar(@p) == 1 or xbail('multiple when 1 expected', \@p);
+	like($p[0], qr/,PS/, 'passed (Forwarded) flag still kept');
+}
+
 }); # test_lei
 done_testing;
diff --git a/xt/net_writer-imap.t b/xt/net_writer-imap.t
index 11a10e74..007de35e 100644
--- a/xt/net_writer-imap.t
+++ b/xt/net_writer-imap.t
@@ -173,17 +173,18 @@ test_lei(sub {
 	is_deeply([@$res{qw(m kw)}], ['testmessage@example.com', ['seen']],
 		'kw set');
 
+	# prepare messages for watch
 	$mic = $nwr->mic_for_folder($folder_uri);
-	for my $kw (qw(Deleted Seen Answered Draft)) {
+	for my $kw (qw(Deleted Seen Answered Draft forwarded)) {
 		my $buf = <<EOM;
 From: x\@example.com
 Message-ID: <$kw\@test.example.com>
 
 EOM
-		$mic->append_string($folder_uri->mailbox, $buf, "\\$kw")
+		my $f = $kw eq 'forwarded' ? '$Forwarded' : "\\$kw";
+		$mic->append_string($folder_uri->mailbox, $buf, $f)
 			or BAIL_OUT "append $kw $@";
 	}
-	# $mic->expunge or BAIL_OUT "expunge: $@";
 	$mic->disconnect;
 
 	my $inboxdir = "$ENV{HOME}/wtest";
@@ -214,6 +215,13 @@ EOM
 		'-watch ignored \\Deleted');
 	ok(!defined($mm->num_for('Draft@test.example.com')),
 		'-watch ignored \\Draft');
+	ok(defined($mm->num_for('forwarded@test.example.com')),
+		'-watch takes forwarded message');
+	undef $w; # done with watch
+	lei_ok qw(import), $$folder_uri;
+	lei_ok qw(q m:forwarded@test.example.com);
+	is_deeply(json_utf8->decode($lei_out)->[0]->{kw}, ['forwarded'],
+		'forwarded kw imported from IMAP');
 });
 
 undef $cleanup; # remove temporary folder

                 reply	other threads:[~2021-04-21 23:50 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20210421235052.26571-1-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.
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).