From 28b1f4f14dffc5dcd5152ce931f6c50b17c134db Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Tue, 20 Feb 2024 11:42:51 +0100 Subject: [PATCH] Unsollicited responses on APPEND --- src/imap/command/authenticated.rs | 18 ++++++++++++------ tests/behavior.rs | 2 +- tests/common/fragments.rs | 3 +-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/imap/command/authenticated.rs b/src/imap/command/authenticated.rs index 26b1946..baf3033 100644 --- a/src/imap/command/authenticated.rs +++ b/src/imap/command/authenticated.rs @@ -14,13 +14,13 @@ use imap_codec::imap_types::mailbox::{ListMailbox, Mailbox as MailboxCodec}; use imap_codec::imap_types::response::{Code, CodeOther, Data}; use imap_codec::imap_types::status::{StatusDataItem, StatusDataItemName}; +use crate::imap::Body; use crate::imap::capability::{ClientCapability, ServerCapability}; use crate::imap::command::{anystate, MailboxName}; use crate::imap::flow; -use crate::imap::mailbox_view::MailboxView; +use crate::imap::mailbox_view::{MailboxView, UpdateParameters}; use crate::imap::response::Response; -use crate::mail::mailbox::Mailbox; use crate::mail::uidindex::*; use crate::mail::user::{User, MAILBOX_HIERARCHY_DELIMITER as MBX_HIER_DELIM_RAW}; use crate::mail::IMF; @@ -558,9 +558,12 @@ impl<'a> AuthenticatedContext<'a> { ) -> Result<(Response<'static>, flow::Transition)> { let append_tag = self.req.tag.clone(); match self.append_internal(mailbox, flags, date, message).await { - Ok((_mb, uidvalidity, uid, _modseq)) => Ok(( + + + Ok((_mb_view, unsollicited, uidvalidity, uid, _modseq)) => Ok(( Response::build() .tag(append_tag) + .set_body(unsollicited) .message("APPEND completed") .code(Code::Other(CodeOther::unvalidated( format!("APPENDUID {} {}", uidvalidity, uid).into_bytes(), @@ -593,13 +596,14 @@ impl<'a> AuthenticatedContext<'a> { )) } + //@FIXME should be refactored and integrated to the mailbox view pub(crate) async fn append_internal( self, mailbox: &MailboxCodec<'a>, flags: &[Flag<'a>], date: &Option, message: &Literal<'a>, - ) -> Result<(Arc, ImapUidvalidity, ImapUid, ModSeq)> { + ) -> Result<(MailboxView, Vec>, ImapUidvalidity, ImapUid, ModSeq)> { let name: &str = MailboxName(mailbox).try_into()?; let mb_opt = self.user.open_mailbox(&name).await?; @@ -607,6 +611,7 @@ impl<'a> AuthenticatedContext<'a> { Some(mb) => mb, None => bail!("Mailbox does not exist"), }; + let mut view = MailboxView::new(mb, self.client_capabilities.condstore.is_enabled()).await; if date.is_some() { tracing::warn!("Cannot set date when appending message"); @@ -617,9 +622,10 @@ impl<'a> AuthenticatedContext<'a> { let flags = flags.iter().map(|x| x.to_string()).collect::>(); // TODO: filter allowed flags? ping @Quentin - let (uidvalidity, uid, modseq) = mb.append(msg, None, &flags[..]).await?; + let (uidvalidity, uid, modseq) = view.internal.mailbox.append(msg, None, &flags[..]).await?; + let unsollicited = view.update(UpdateParameters::default()).await?; - Ok((mb, uidvalidity, uid, modseq)) + Ok((view, unsollicited, uidvalidity, uid, modseq)) } } diff --git a/tests/behavior.rs b/tests/behavior.rs index 7fdd553..13baf0e 100644 --- a/tests/behavior.rs +++ b/tests/behavior.rs @@ -225,7 +225,7 @@ fn rfc4551_imapext_condstore() { FetchKind::Rfc822Size, FetchMod::ChangedSince(2), )?; - assert!(fetch_res.contains("* 1 FETCH (RFC822.SIZE 84 MODSEQ (3))")); + assert!(fetch_res.contains("* 1 FETCH (RFC822.SIZE 81 MODSEQ (3))")); assert!(!fetch_res.contains("* 2 FETCH")); assert_eq!(store_res.lines().count(), 2); diff --git a/tests/common/fragments.rs b/tests/common/fragments.rs index a10d4e0..606af2b 100644 --- a/tests/common/fragments.rs +++ b/tests/common/fragments.rs @@ -384,8 +384,7 @@ pub fn append(imap: &mut TcpStream, content: Email) -> Result { // write our stuff imap.write(ref_mail)?; imap.write(&b"\r\n"[..])?; - let read = read_lines(imap, &mut buffer, None)?; - assert_eq!(&read[..5], &b"47 OK"[..]); + let read = read_lines(imap, &mut buffer, Some(&b"47 OK"[..]))?; let srv_msg = std::str::from_utf8(read)?; Ok(srv_msg.to_string())