mirror of
https://git.meli.delivery/meli/meli
synced 2024-11-19 03:25:38 +00:00
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.
This commit is contained in:
parent
76c1c1a213
commit
5f6b4745b8
8
melib/src/backends/imap/cache/sync.rs
vendored
8
melib/src/backends/imap/cache/sync.rs
vendored
@ -658,12 +658,11 @@ impl ImapConnection {
|
||||
|
||||
pub async fn init_mailbox(&mut self, mailbox_hash: MailboxHash) -> Result<SelectResponse> {
|
||||
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];
|
||||
(
|
||||
f.imap_path().to_string(),
|
||||
f.exists.clone(),
|
||||
f.unseen.clone(),
|
||||
f.permissions.clone(),
|
||||
)
|
||||
};
|
||||
@ -705,11 +704,6 @@ impl ImapConnection {
|
||||
mailbox_exists_lck.clear();
|
||||
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 {
|
||||
return Ok(select_response);
|
||||
|
@ -977,7 +977,7 @@ pub struct SelectResponse {
|
||||
pub exists: ImapNum,
|
||||
pub recent: ImapNum,
|
||||
pub flags: (Flag, Vec<String>),
|
||||
pub unseen: MessageSequenceNumber,
|
||||
pub first_unseen: MessageSequenceNumber,
|
||||
pub uidvalidity: UIDVALIDITY,
|
||||
pub uidnext: UID,
|
||||
pub permanentflags: (Flag, Vec<String>),
|
||||
@ -1024,7 +1024,7 @@ pub fn select_response(input: &[u8]) -> Result<SelectResponse> {
|
||||
} else if l.starts_with(b"* FLAGS (") {
|
||||
ret.flags = flags(&l[b"* FLAGS (".len()..l.len() - b")".len()]).map(|(_, v)| v)?;
|
||||
} 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()],
|
||||
))?;
|
||||
} 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,
|
||||
Vec::new()
|
||||
),
|
||||
unseen: 16,
|
||||
first_unseen: 16,
|
||||
uidvalidity: 1554422056,
|
||||
uidnext: 50,
|
||||
permanentflags: (
|
||||
@ -1105,7 +1105,7 @@ fn test_select_response() {
|
||||
Flag::REPLIED | Flag::SEEN | Flag::TRASHED | Flag::DRAFT | Flag::FLAGGED,
|
||||
Vec::new()
|
||||
),
|
||||
unseen: 12,
|
||||
first_unseen: 12,
|
||||
uidvalidity: 3857529045,
|
||||
uidnext: 4392,
|
||||
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,
|
||||
Vec::new()
|
||||
),
|
||||
unseen: 12,
|
||||
first_unseen: 12,
|
||||
uidvalidity: 3857529045,
|
||||
uidnext: 4392,
|
||||
permanentflags: (Flag::SEEN | Flag::TRASHED, vec!["*".into()]),
|
||||
|
@ -246,13 +246,66 @@ pub async fn examine_updates(
|
||||
}
|
||||
if mailbox.is_cold() {
|
||||
/* Mailbox hasn't been loaded yet */
|
||||
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(select_response.unseen);
|
||||
let has_list_status: bool = conn
|
||||
.uid_store
|
||||
.capabilities
|
||||
.lock()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.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);
|
||||
return Ok(());
|
||||
|
Loading…
Reference in New Issue
Block a user