melib/threads: prefer local ThreadNode env_hash

When inserting an envelope in a thread and its Message-ID already exists
with an associated envelope, overwrite the association if the previous
associated envelope is from a foreign mailbox and current envelope is
not. This happens when mail from a sent folder has been inserted in eg
your INBOX, but somehow INBOX has a copy of your own message as well.
This can happen when mailing lists that send you copies of your own
posts.

The problem with this was that in IMAP your mailing list copy was unseen
and you could not mark it seen because the thread only knew about your
Sent mailbox copy.
jmap-eventsource
Manos Pitsidianakis 2020-11-30 00:26:13 +02:00
parent 4939a1ad9e
commit 9dd21eea50
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
2 changed files with 28 additions and 14 deletions

View File

@ -137,6 +137,7 @@ impl<'m> Message<'m> {
ThreadNode {
message: Some(self.env_hash()),
parent: None,
other_mailbox: false,
children: vec![],
date: self.date(),
show_subject: true,

View File

@ -338,6 +338,7 @@ impl Thread {
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ThreadNode {
pub message: Option<EnvelopeHash>,
pub other_mailbox: bool,
pub parent: Option<ThreadNodeHash>,
pub children: Vec<ThreadNodeHash>,
pub date: UnixTimestamp,
@ -351,6 +352,7 @@ impl Default for ThreadNode {
ThreadNode {
message: None,
parent: None,
other_mailbox: false,
children: Vec::new(),
date: UnixTimestamp::default(),
show_subject: true,
@ -653,26 +655,36 @@ impl Threads {
env_hash: EnvelopeHash,
other_mailbox: bool,
) -> bool {
{
let envelopes_lck = envelopes.read().unwrap();
let message_id = envelopes_lck[&env_hash].message_id().raw();
if self.message_ids.contains_key(message_id)
&& !self.missing_message_ids.contains(message_id)
{
let thread_hash = self.message_ids[message_id];
let node = self.thread_nodes.entry(thread_hash).or_default();
drop(message_id);
drop(envelopes_lck);
envelopes
.write()
.unwrap()
.get_mut(&env_hash)
.unwrap()
.set_thread(thread_hash);
/* If thread node currently has a message from a foreign mailbox and env_hash is
* from current mailbox we want to update it, otherwise return */
if !(node.other_mailbox && !other_mailbox) {
return false;
}
}
}
let envelopes_lck = envelopes.read().unwrap();
let reply_to_id: Option<ThreadNodeHash> = envelopes_lck[&env_hash]
.in_reply_to()
.map(StrBuild::raw)
.and_then(|r| self.message_ids.get(r).cloned());
let message_id = envelopes_lck[&env_hash].message_id().raw();
if self.message_ids.contains_key(message_id)
&& !self.missing_message_ids.contains(message_id)
{
let thread_hash = self.message_ids[message_id];
drop(envelopes_lck);
envelopes
.write()
.unwrap()
.get_mut(&env_hash)
.unwrap()
.set_thread(thread_hash);
return false;
}
if other_mailbox
&& reply_to_id.is_none()
@ -703,6 +715,7 @@ impl Threads {
if node.parent.is_none() {
node.parent = reply_to_id;
}
node.other_mailbox = other_mailbox;
node.date = envelopes_lck[&env_hash].date();
node.unseen = !envelopes_lck[&env_hash].is_seen();
}