aboutsummaryrefslogtreecommitdiff
path: root/src/imap/command/selected.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/imap/command/selected.rs')
-rw-r--r--src/imap/command/selected.rs87
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(),
+ ),
}
}
}