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 {
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
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);
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;
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";
'-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