melib/imap: don't use UNSEEN select response for unseen count
UNSEEN field in SELECT/EXAMINE response is meant to be the message sequence number of the first unseen message, not the count of unseen messages.jmap-eventsource
parent
76c1c1a213
commit
5f6b4745b8
|
@ -658,12 +658,11 @@ impl ImapConnection {
|
||||||
|
|
||||||
pub async fn init_mailbox(&mut self, mailbox_hash: MailboxHash) -> Result<SelectResponse> {
|
pub async fn init_mailbox(&mut self, mailbox_hash: MailboxHash) -> Result<SelectResponse> {
|
||||||
let mut response = Vec::with_capacity(8 * 1024);
|
let mut response = Vec::with_capacity(8 * 1024);
|
||||||
let (mailbox_path, mailbox_exists, unseen, permissions) = {
|
let (mailbox_path, mailbox_exists, permissions) = {
|
||||||
let f = &self.uid_store.mailboxes.lock().await[&mailbox_hash];
|
let f = &self.uid_store.mailboxes.lock().await[&mailbox_hash];
|
||||||
(
|
(
|
||||||
f.imap_path().to_string(),
|
f.imap_path().to_string(),
|
||||||
f.exists.clone(),
|
f.exists.clone(),
|
||||||
f.unseen.clone(),
|
|
||||||
f.permissions.clone(),
|
f.permissions.clone(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
@ -705,11 +704,6 @@ impl ImapConnection {
|
||||||
mailbox_exists_lck.clear();
|
mailbox_exists_lck.clear();
|
||||||
mailbox_exists_lck.set_not_yet_seen(select_response.exists);
|
mailbox_exists_lck.set_not_yet_seen(select_response.exists);
|
||||||
}
|
}
|
||||||
{
|
|
||||||
let mut unseen_lck = unseen.lock().unwrap();
|
|
||||||
unseen_lck.clear();
|
|
||||||
unseen_lck.set_not_yet_seen(select_response.unseen);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if select_response.exists == 0 {
|
if select_response.exists == 0 {
|
||||||
return Ok(select_response);
|
return Ok(select_response);
|
||||||
|
|
|
@ -977,7 +977,7 @@ pub struct SelectResponse {
|
||||||
pub exists: ImapNum,
|
pub exists: ImapNum,
|
||||||
pub recent: ImapNum,
|
pub recent: ImapNum,
|
||||||
pub flags: (Flag, Vec<String>),
|
pub flags: (Flag, Vec<String>),
|
||||||
pub unseen: MessageSequenceNumber,
|
pub first_unseen: MessageSequenceNumber,
|
||||||
pub uidvalidity: UIDVALIDITY,
|
pub uidvalidity: UIDVALIDITY,
|
||||||
pub uidnext: UID,
|
pub uidnext: UID,
|
||||||
pub permanentflags: (Flag, Vec<String>),
|
pub permanentflags: (Flag, Vec<String>),
|
||||||
|
@ -1024,7 +1024,7 @@ pub fn select_response(input: &[u8]) -> Result<SelectResponse> {
|
||||||
} else if l.starts_with(b"* FLAGS (") {
|
} else if l.starts_with(b"* FLAGS (") {
|
||||||
ret.flags = flags(&l[b"* FLAGS (".len()..l.len() - b")".len()]).map(|(_, v)| v)?;
|
ret.flags = flags(&l[b"* FLAGS (".len()..l.len() - b")".len()]).map(|(_, v)| v)?;
|
||||||
} else if l.starts_with(b"* OK [UNSEEN ") {
|
} else if l.starts_with(b"* OK [UNSEEN ") {
|
||||||
ret.unseen = MessageSequenceNumber::from_str(&String::from_utf8_lossy(
|
ret.first_unseen = MessageSequenceNumber::from_str(&String::from_utf8_lossy(
|
||||||
&l[b"* OK [UNSEEN ".len()..l.find(b"]").unwrap()],
|
&l[b"* OK [UNSEEN ".len()..l.find(b"]").unwrap()],
|
||||||
))?;
|
))?;
|
||||||
} else if l.starts_with(b"* OK [UIDVALIDITY ") {
|
} else if l.starts_with(b"* OK [UIDVALIDITY ") {
|
||||||
|
@ -1082,7 +1082,7 @@ fn test_select_response() {
|
||||||
Flag::REPLIED | Flag::SEEN | Flag::TRASHED | Flag::DRAFT | Flag::FLAGGED,
|
Flag::REPLIED | Flag::SEEN | Flag::TRASHED | Flag::DRAFT | Flag::FLAGGED,
|
||||||
Vec::new()
|
Vec::new()
|
||||||
),
|
),
|
||||||
unseen: 16,
|
first_unseen: 16,
|
||||||
uidvalidity: 1554422056,
|
uidvalidity: 1554422056,
|
||||||
uidnext: 50,
|
uidnext: 50,
|
||||||
permanentflags: (
|
permanentflags: (
|
||||||
|
@ -1105,7 +1105,7 @@ fn test_select_response() {
|
||||||
Flag::REPLIED | Flag::SEEN | Flag::TRASHED | Flag::DRAFT | Flag::FLAGGED,
|
Flag::REPLIED | Flag::SEEN | Flag::TRASHED | Flag::DRAFT | Flag::FLAGGED,
|
||||||
Vec::new()
|
Vec::new()
|
||||||
),
|
),
|
||||||
unseen: 12,
|
first_unseen: 12,
|
||||||
uidvalidity: 3857529045,
|
uidvalidity: 3857529045,
|
||||||
uidnext: 4392,
|
uidnext: 4392,
|
||||||
permanentflags: (Flag::SEEN | Flag::TRASHED, vec!["*".into()]),
|
permanentflags: (Flag::SEEN | Flag::TRASHED, vec!["*".into()]),
|
||||||
|
@ -1127,7 +1127,7 @@ fn test_select_response() {
|
||||||
Flag::REPLIED | Flag::SEEN | Flag::TRASHED | Flag::DRAFT | Flag::FLAGGED,
|
Flag::REPLIED | Flag::SEEN | Flag::TRASHED | Flag::DRAFT | Flag::FLAGGED,
|
||||||
Vec::new()
|
Vec::new()
|
||||||
),
|
),
|
||||||
unseen: 12,
|
first_unseen: 12,
|
||||||
uidvalidity: 3857529045,
|
uidvalidity: 3857529045,
|
||||||
uidnext: 4392,
|
uidnext: 4392,
|
||||||
permanentflags: (Flag::SEEN | Flag::TRASHED, vec!["*".into()]),
|
permanentflags: (Flag::SEEN | Flag::TRASHED, vec!["*".into()]),
|
||||||
|
|
|
@ -246,13 +246,66 @@ pub async fn examine_updates(
|
||||||
}
|
}
|
||||||
if mailbox.is_cold() {
|
if mailbox.is_cold() {
|
||||||
/* Mailbox hasn't been loaded yet */
|
/* Mailbox hasn't been loaded yet */
|
||||||
if let Ok(mut exists_lck) = mailbox.exists.lock() {
|
let has_list_status: bool = conn
|
||||||
exists_lck.clear();
|
.uid_store
|
||||||
exists_lck.set_not_yet_seen(select_response.exists);
|
.capabilities
|
||||||
}
|
.lock()
|
||||||
if let Ok(mut unseen_lck) = mailbox.unseen.lock() {
|
.unwrap()
|
||||||
unseen_lck.clear();
|
.iter()
|
||||||
unseen_lck.set_not_yet_seen(select_response.unseen);
|
.any(|cap| cap.eq_ignore_ascii_case(b"LIST-STATUS"));
|
||||||
|
if has_list_status {
|
||||||
|
conn.send_command(
|
||||||
|
format!(
|
||||||
|
"LIST \"{}\" \"\" RETURN (STATUS (MESSAGES UNSEEN))",
|
||||||
|
mailbox.imap_path()
|
||||||
|
)
|
||||||
|
.as_bytes(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
conn.read_response(
|
||||||
|
&mut response,
|
||||||
|
RequiredResponses::LIST_REQUIRED | RequiredResponses::STATUS,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
debug!(
|
||||||
|
"list return status out: {}",
|
||||||
|
String::from_utf8_lossy(&response)
|
||||||
|
);
|
||||||
|
let mut lines = response.split_rn();
|
||||||
|
/* Remove "M__ OK .." line */
|
||||||
|
lines.next_back();
|
||||||
|
for l in lines {
|
||||||
|
if let Ok(status) = protocol_parser::status_response(&l).map(|(_, v)| v) {
|
||||||
|
if Some(mailbox_hash) == status.mailbox {
|
||||||
|
if let Some(total) = status.messages {
|
||||||
|
if let Ok(mut exists_lck) = mailbox.exists.lock() {
|
||||||
|
exists_lck.clear();
|
||||||
|
exists_lck.set_not_yet_seen(total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(total) = status.unseen {
|
||||||
|
if let Ok(mut unseen_lck) = mailbox.unseen.lock() {
|
||||||
|
unseen_lck.clear();
|
||||||
|
unseen_lck.set_not_yet_seen(total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
conn.send_command(b"SEARCH UNSEEN").await?;
|
||||||
|
conn.read_response(&mut response, RequiredResponses::SEARCH)
|
||||||
|
.await?;
|
||||||
|
let unseen_count = protocol_parser::search_results(&response)?.1.len();
|
||||||
|
if let Ok(mut exists_lck) = mailbox.exists.lock() {
|
||||||
|
exists_lck.clear();
|
||||||
|
exists_lck.set_not_yet_seen(select_response.exists);
|
||||||
|
}
|
||||||
|
if let Ok(mut unseen_lck) = mailbox.unseen.lock() {
|
||||||
|
unseen_lck.clear();
|
||||||
|
unseen_lck.set_not_yet_seen(unseen_count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mailbox.set_warm(true);
|
mailbox.set_warm(true);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
Loading…
Reference in New Issue