diff options
Diffstat (limited to 'src/imap/command/selected.rs')
-rw-r--r-- | src/imap/command/selected.rs | 87 |
1 files changed, 52 insertions, 35 deletions
diff --git a/src/imap/command/selected.rs b/src/imap/command/selected.rs index ca2e268..98b3b00 100644 --- a/src/imap/command/selected.rs +++ b/src/imap/command/selected.rs @@ -1,5 +1,5 @@ -use std::sync::Arc; use std::num::NonZeroU64; +use std::sync::Arc; use anyhow::Result; use imap_codec::imap_types::command::{Command, CommandBody, FetchModifier, StoreModifier}; @@ -11,12 +11,12 @@ use imap_codec::imap_types::response::{Code, CodeOther}; use imap_codec::imap_types::search::SearchKey; use imap_codec::imap_types::sequence::SequenceSet; +use crate::imap::attributes::AttributesProxy; use crate::imap::capability::{ClientCapability, ServerCapability}; use crate::imap::command::{anystate, authenticated, MailboxName}; use crate::imap::flow; use crate::imap::mailbox_view::{MailboxView, UpdateParameters}; use crate::imap::response::Response; -use crate::imap::attributes::AttributesProxy; use crate::mail::user::User; pub struct SelectedContext<'a> { @@ -50,7 +50,10 @@ pub async fn dispatch<'a>( macro_or_item_names, modifiers, uid, - } => ctx.fetch(sequence_set, macro_or_item_names, modifiers, uid).await, + } => { + ctx.fetch(sequence_set, macro_or_item_names, modifiers, uid) + .await + } CommandBody::Search { charset, criteria, @@ -64,7 +67,10 @@ pub async fn dispatch<'a>( flags, modifiers, uid, - } => ctx.store(sequence_set, kind, response, flags, modifiers, uid).await, + } => { + ctx.store(sequence_set, kind, response, flags, modifiers, uid) + .await + } CommandBody::Copy { sequence_set, mailbox, @@ -80,12 +86,13 @@ pub async fn dispatch<'a>( CommandBody::Unselect => ctx.unselect().await, // IDLE extension (rfc2177) - CommandBody::Idle => { - Ok(( - Response::build().to_req(ctx.req).message("DUMMY command due to anti-pattern in the code").ok()?, - flow::Transition::Idle(ctx.req.tag.clone(), tokio::sync::Notify::new()), - )) - } + CommandBody::Idle => Ok(( + Response::build() + .to_req(ctx.req) + .message("DUMMY command due to anti-pattern in the code") + .ok()?, + flow::Transition::Idle(ctx.req.tag.clone(), tokio::sync::Notify::new()), + )), // In selected mode, we fallback to authenticated when needed _ => { @@ -148,10 +155,14 @@ impl<'a> SelectedContext<'a> { modifiers.iter().for_each(|m| match m { FetchModifier::ChangedSince(val) => { changed_since = Some(*val); - }, + } }); - match self.mailbox.fetch(sequence_set, &ap, changed_since, uid).await { + match self + .mailbox + .fetch(sequence_set, &ap, changed_since, uid) + .await + { Ok(resp) => { // Capabilities enabling logic only on successful command // (according to my understanding of the spec) @@ -167,7 +178,7 @@ impl<'a> SelectedContext<'a> { .ok()?, flow::Transition::None, )) - }, + } Err(e) => Ok(( Response::build() .to_req(self.req) @@ -214,7 +225,7 @@ impl<'a> SelectedContext<'a> { async fn expunge(self) -> Result<(Response<'static>, flow::Transition)> { if let Some(failed) = self.fail_read_only() { - return Ok((failed, flow::Transition::None)) + return Ok((failed, flow::Transition::None)); } let tag = self.req.tag.clone(); @@ -240,14 +251,14 @@ impl<'a> SelectedContext<'a> { uid: &bool, ) -> Result<(Response<'static>, flow::Transition)> { if let Some(failed) = self.fail_read_only() { - return Ok((failed, flow::Transition::None)) + return Ok((failed, flow::Transition::None)); } let mut unchanged_since: Option<NonZeroU64> = None; modifiers.iter().for_each(|m| match m { StoreModifier::UnchangedSince(val) => { unchanged_since = Some(*val); - }, + } }); let (data, modified) = self @@ -256,25 +267,30 @@ impl<'a> SelectedContext<'a> { .await?; let mut ok_resp = Response::build() - .to_req(self.req) - .message("STORE completed") - .set_body(data); - + .to_req(self.req) + .message("STORE completed") + .set_body(data); match modified[..] { [] => (), [_head, ..] => { - let modified_str = format!("MODIFIED {}", modified.into_iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",")); - ok_resp = ok_resp.code(Code::Other(CodeOther::unvalidated(modified_str.into_bytes()))); - }, + let modified_str = format!( + "MODIFIED {}", + modified + .into_iter() + .map(|x| x.to_string()) + .collect::<Vec<_>>() + .join(",") + ); + ok_resp = ok_resp.code(Code::Other(CodeOther::unvalidated( + modified_str.into_bytes(), + ))); + } }; - self.client_capabilities.store_modifiers_enable(modifiers); - Ok((ok_resp.ok()?, - flow::Transition::None, - )) + Ok((ok_resp.ok()?, flow::Transition::None)) } async fn copy( @@ -285,7 +301,7 @@ impl<'a> SelectedContext<'a> { ) -> Result<(Response<'static>, flow::Transition)> { //@FIXME Could copy be valid in EXAMINE mode? if let Some(failed) = self.fail_read_only() { - return Ok((failed, flow::Transition::None)) + return Ok((failed, flow::Transition::None)); } let name: &str = MailboxName(mailbox).try_into()?; @@ -341,7 +357,7 @@ impl<'a> SelectedContext<'a> { uid: &bool, ) -> Result<(Response<'static>, flow::Transition)> { if let Some(failed) = self.fail_read_only() { - return Ok((failed, flow::Transition::None)) + return Ok((failed, flow::Transition::None)); } let name: &str = MailboxName(mailbox).try_into()?; @@ -395,12 +411,13 @@ impl<'a> SelectedContext<'a> { fn fail_read_only(&self) -> Option<Response<'static>> { match self.perm { flow::MailboxPerm::ReadWrite => None, - flow::MailboxPerm::ReadOnly => { - Some(Response::build() - .to_req(self.req) - .message("Write command are forbidden while exmining mailbox") - .no().unwrap()) - }, + flow::MailboxPerm::ReadOnly => Some( + Response::build() + .to_req(self.req) + .message("Write command are forbidden while exmining mailbox") + .no() + .unwrap(), + ), } } } |