diff --git a/crates/imap/src/core/message.rs b/crates/imap/src/core/message.rs index 0721ba74..dfefa896 100644 --- a/crates/imap/src/core/message.rs +++ b/crates/imap/src/core/message.rs @@ -7,14 +7,17 @@ use std::{collections::BTreeMap, sync::Arc}; use ahash::AHashMap; -use common::{listener::SessionStream, NextMailboxState}; +use common::{NextMailboxState, listener::SessionStream}; use email::mailbox::UidMailbox; -use imap_proto::protocol::{expunge, select::Exists, Sequence}; +use imap_proto::protocol::{Sequence, expunge, select::Exists}; use jmap_proto::{ object::Object, types::{collection::Collection, property::Property, value::Value}, }; -use store::write::assert::HashedValue; +use store::{ + ValueKey, + write::{ValueClass, assert::HashedValue}, +}; use trc::AddContext; use crate::core::ImapId; @@ -37,8 +40,9 @@ impl SessionData { .await? .unwrap_or_default(); - // Obtain UID validity + // Obtain UID validity and UID next let uid_validity = self.get_uid_validity(mailbox).await?; + let uid_next = self.get_uid_next(mailbox).await?; // Obtain current state let modseq = self @@ -104,7 +108,7 @@ impl SessionData { } let mut state = MailboxState { - uid_next: uid_max + 1, + uid_next, uid_validity, total_messages: id_to_imap.len(), id_to_imap, @@ -245,6 +249,21 @@ impl SessionData { }) .map(|v| v as u32) } + + pub async fn get_uid_next(&self, mailbox: &MailboxId) -> trc::Result { + self.server + .core + .storage + .data + .get_counter(ValueKey { + account_id: mailbox.account_id, + collection: Collection::Mailbox.into(), + document_id: mailbox.mailbox_id, + class: ValueClass::Property(Property::EmailIds.into()), + }) + .await + .map(|v| (v + 1) as u32) + } } impl SelectedMailbox { diff --git a/crates/imap/src/op/status.rs b/crates/imap/src/op/status.rs index 1badde82..f674b166 100644 --- a/crates/imap/src/op/status.rs +++ b/crates/imap/src/op/status.rs @@ -11,24 +11,22 @@ use crate::{ op::ImapContext, spawn_op, }; -use common::{listener::SessionStream, Mailbox}; +use common::{Mailbox, listener::SessionStream}; use directory::Permission; use imap_proto::{ + Command, ResponseCode, StatusResponse, parser::PushUnique, protocol::status::{Status, StatusItem, StatusItemType}, receiver::Request, - Command, ResponseCode, StatusResponse, }; use jmap_proto::{ object::Object, types::{collection::Collection, id::Id, keyword::Keyword, property::Property, value::Value}, }; -use store::{ - roaring::RoaringBitmap, - write::{key::DeserializeBigEndian, ValueClass}, - IndexKeyPrefix, IterateParams, ValueKey, -}; use store::{Deserialize, U32_LEN}; +use store::{ + IndexKeyPrefix, IterateParams, roaring::RoaringBitmap, write::key::DeserializeBigEndian, +}; use trc::AddContext; use super::ToModSeq; @@ -251,22 +249,10 @@ impl SessionData { for item in items_update { let result = match item { Status::Messages => mailbox_message_ids.as_ref().map(|v| v.len()).unwrap_or(0), - Status::UidNext => { - (self - .server - .core - .storage - .data - .get_counter(ValueKey { - account_id: mailbox.account_id, - collection: Collection::Mailbox.into(), - document_id: mailbox.mailbox_id, - class: ValueClass::Property(Property::EmailIds.into()), - }) - .await - .caused_by(trc::location!())? - + 1) as u64 - } + Status::UidNext => self + .get_uid_next(&mailbox) + .await + .caused_by(trc::location!())? as u64, Status::UidValidity => self .server .get_property::>(