diff --git a/src/imap/command/authenticated.rs b/src/imap/command/authenticated.rs index 7f6531c..6c2e43b 100644 --- a/src/imap/command/authenticated.rs +++ b/src/imap/command/authenticated.rs @@ -172,10 +172,7 @@ impl<'a> AuthenticatedContext<'a> { } else { "LIST completed" }; - Ok(( - Response::ok(msg)?.with_body(ret), - flow::Transition::None, - )) + Ok((Response::ok(msg)?.with_body(ret), flow::Transition::None)) } async fn status( diff --git a/src/imap/mailbox_view.rs b/src/imap/mailbox_view.rs index f384a79..5debcb9 100644 --- a/src/imap/mailbox_view.rs +++ b/src/imap/mailbox_view.rs @@ -86,41 +86,44 @@ impl MailboxView { let mut data = Vec::::new(); + // Calculate diff between two mailbox states + // See example in IMAP RFC in section on NOOP command: + // we want to produce something like this: + // C: a047 NOOP + // S: * 22 EXPUNGE + // S: * 23 EXISTS + // S: * 14 FETCH (UID 1305 FLAGS (\Seen \Deleted)) + // S: a047 OK Noop completed + // In other words: + // - notify client of expunged mails + // - if new mails arrived, notify client of number of existing mails + // - if flags changed for existing mails, tell client + // (for this last step: if uidvalidity changed, do nothing, + // just notify of new uidvalidity and they will resync) + + // - notify client of expunged mails + let mut n_expunge = 0; + for (i, (_uid, uuid)) in self.known_state.idx_by_uid.iter().enumerate() { + if !new_view.known_state.table.contains_key(uuid) { + data.push(Body::Data(Data::Expunge( + NonZeroU32::try_from((i + 1 - n_expunge) as u32).unwrap(), + ))); + n_expunge += 1; + } + } + + // - if new mails arrived, notify client of number of existing mails + if new_view.known_state.table.len() != self.known_state.table.len() - n_expunge + || new_view.known_state.uidvalidity != self.known_state.uidvalidity + { + data.push(new_view.exists_status()?); + } + if new_view.known_state.uidvalidity != self.known_state.uidvalidity { // TODO: do we want to push less/more info than this? data.push(new_view.uidvalidity_status()?); - data.push(new_view.exists_status()?); data.push(new_view.uidnext_status()?); } else { - // Calculate diff between two mailbox states - // See example in IMAP RFC in section on NOOP command: - // we want to produce something like this: - // C: a047 NOOP - // S: * 22 EXPUNGE - // S: * 23 EXISTS - // S: * 14 FETCH (UID 1305 FLAGS (\Seen \Deleted)) - // S: a047 OK Noop completed - // In other words: - // - notify client of expunged mails - // - if new mails arrived, notify client of number of existing mails - // - if flags changed for existing mails, tell client - - // - notify client of expunged mails - let mut n_expunge = 0; - for (i, (_uid, uuid)) in self.known_state.idx_by_uid.iter().enumerate() { - if !new_view.known_state.table.contains_key(uuid) { - data.push(Body::Data(Data::Expunge( - NonZeroU32::try_from((i + 1 - n_expunge) as u32).unwrap(), - ))); - n_expunge += 1; - } - } - - // - if new mails arrived, notify client of number of existing mails - if new_view.known_state.table.len() != self.known_state.table.len() - n_expunge { - data.push(new_view.exists_status()?); - } - // - if flags changed for existing mails, tell client for (i, (_uid, uuid)) in new_view.known_state.idx_by_uid.iter().enumerate() { let old_mail = self.known_state.table.get(uuid);