]> Sergey Matveev's repositories - public-inbox.git/commitdiff
lei: flesh out `forwarded' kw support for Maildir and IMAP
authorEric Wong <e@80x24.org>
Wed, 21 Apr 2021 23:50:52 +0000 (23:50 +0000)
committerEric Wong <e@80x24.org>
Thu, 22 Apr 2021 09:08:39 +0000 (09:08 +0000)
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
lib/PublicInbox/LeiToMail.pm
lib/PublicInbox/NetReader.pm
t/lei-q-kw.t
xt/net_writer-imap.t

index 082176e7dbdda84e17784260baa82df8a333eb8f..ff615d890d30d908128ed158271a43ba16b00893 100644 (file)
@@ -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 {
index 46a82a4bd586d295caa3b021e5fd0be7ddb163cf..0fa0bd9a6a2ef124724b085be5677b5395738ecb 100644 (file)
@@ -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
index 821e5d7fb7c12179ad18a23042503e626b89155c..0ef66fd84cb8bf56cd7737cacd2b059d1b30969b 100644 (file)
@@ -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);
 
index c17411fbe07ce19b7bcc72385547b1e70ad02990..c00a0a43f8e8aa2eaa95986c3fa7e85966d692dc 100644 (file)
@@ -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;
index 11a10e742d68abe13fd1f62541457aa15b9004dc..007de35ea7155eb4e5ce87d4c6596b159ebd4db7 100644 (file)
@@ -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