aboutsummaryrefslogtreecommitdiff
path: root/src/imap/command
diff options
context:
space:
mode:
authorQuentin Dufour <quentin@deuxfleurs.fr>2024-01-17 08:33:08 +0100
committerQuentin Dufour <quentin@deuxfleurs.fr>2024-01-17 08:33:08 +0100
commit0eb8156cde27c54734cbe3d269ab05a876ef53ac (patch)
treea0f0434435c874aa98b82439f5d8acae6f37f5aa /src/imap/command
parent3d23f0c936516ed89f2888fb44babb3994e8d579 (diff)
downloadaerogramme-0eb8156cde27c54734cbe3d269ab05a876ef53ac.tar.gz
aerogramme-0eb8156cde27c54734cbe3d269ab05a876ef53ac.zip
Delete EXAMINE that has been merged in SELECTED
Diffstat (limited to 'src/imap/command')
-rw-r--r--src/imap/command/examined.rs164
-rw-r--r--src/imap/command/mod.rs1
2 files changed, 0 insertions, 165 deletions
diff --git a/src/imap/command/examined.rs b/src/imap/command/examined.rs
deleted file mode 100644
index 9fc0990..0000000
--- a/src/imap/command/examined.rs
+++ /dev/null
@@ -1,164 +0,0 @@
-use std::sync::Arc;
-use std::num::NonZeroU64;
-
-use anyhow::Result;
-use imap_codec::imap_types::command::{Command, CommandBody, FetchModifier};
-use imap_codec::imap_types::core::Charset;
-use imap_codec::imap_types::fetch::MacroOrMessageDataItemNames;
-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};
-use crate::imap::flow;
-use crate::imap::mailbox_view::{MailboxView, UpdateParameters};
-use crate::imap::response::Response;
-use crate::mail::user::User;
-
-pub struct ExaminedContext<'a> {
- pub req: &'a Command<'static>,
- pub user: &'a Arc<User>,
- pub mailbox: &'a mut MailboxView,
- pub server_capabilities: &'a ServerCapability,
- pub client_capabilities: &'a mut ClientCapability,
-}
-
-pub async fn dispatch(ctx: ExaminedContext<'_>) -> Result<(Response<'static>, flow::Transition)> {
- match &ctx.req.body {
- // Any State
- // noop is specific to this state
- CommandBody::Capability => {
- anystate::capability(ctx.req.tag.clone(), ctx.server_capabilities)
- }
- CommandBody::Logout => anystate::logout(),
-
- // Specific to the EXAMINE state (specialization of the SELECTED state)
- // ~3 commands -> close, fetch, search + NOOP
- CommandBody::Close => ctx.close("CLOSE").await,
- CommandBody::Fetch {
- sequence_set,
- macro_or_item_names,
- modifiers,
- uid,
- } => ctx.fetch(sequence_set, macro_or_item_names, modifiers, uid).await,
- CommandBody::Search {
- charset,
- criteria,
- uid,
- } => ctx.search(charset, criteria, uid).await,
- CommandBody::Noop | CommandBody::Check => ctx.noop().await,
- CommandBody::Expunge { .. } | CommandBody::Store { .. } => Ok((
- Response::build()
- .to_req(ctx.req)
- .message("Forbidden command: can't write in read-only mode (EXAMINE)")
- .no()?,
- flow::Transition::None,
- )),
-
- // UNSELECT extension (rfc3691)
- CommandBody::Unselect => ctx.close("UNSELECT").await,
-
- // In examined mode, we fallback to authenticated when needed
- _ => {
- authenticated::dispatch(authenticated::AuthenticatedContext {
- req: ctx.req,
- server_capabilities: ctx.server_capabilities,
- client_capabilities: ctx.client_capabilities,
- user: ctx.user,
- })
- .await
- }
- }
-}
-
-// --- PRIVATE ---
-
-impl<'a> ExaminedContext<'a> {
- /// CLOSE in examined state is not the same as in selected state
- /// (in selected state it also does an EXPUNGE, here it doesn't)
- async fn close(self, kind: &str) -> Result<(Response<'static>, flow::Transition)> {
- Ok((
- Response::build()
- .to_req(self.req)
- .message(format!("{} completed", kind))
- .ok()?,
- flow::Transition::Unselect,
- ))
- }
-
- pub async fn fetch(
- self,
- sequence_set: &SequenceSet,
- attributes: &'a MacroOrMessageDataItemNames<'static>,
- modifiers: &[FetchModifier],
- uid: &bool,
- ) -> Result<(Response<'static>, flow::Transition)> {
- let ap = AttributesProxy::new(attributes, modifiers, *uid);
- let mut changed_since: Option<NonZeroU64> = None;
- 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 {
- Ok(resp) => {
- // Capabilities enabling logic only on successful command
- // (according to my understanding of the spec)
- self.client_capabilities.attributes_enable(&ap);
- self.client_capabilities.fetch_modifiers_enable(modifiers);
-
- Ok((
- Response::build()
- .to_req(self.req)
- .message("FETCH completed")
- .set_body(resp)
- .ok()?,
- flow::Transition::None,
- ))
- },
- Err(e) => Ok((
- Response::build()
- .to_req(self.req)
- .message(e.to_string())
- .no()?,
- flow::Transition::None,
- )),
- }
- }
-
- pub async fn search(
- self,
- charset: &Option<Charset<'a>>,
- criteria: &SearchKey<'a>,
- uid: &bool,
- ) -> Result<(Response<'static>, flow::Transition)> {
- let (found, enable_condstore) = self.mailbox.search(charset, criteria, *uid).await?;
- if enable_condstore {
- self.client_capabilities.enable_condstore();
- }
- Ok((
- Response::build()
- .to_req(self.req)
- .set_body(found)
- .message("SEARCH completed")
- .ok()?,
- flow::Transition::None,
- ))
- }
-
- pub async fn noop(self) -> Result<(Response<'static>, flow::Transition)> {
- self.mailbox.internal.mailbox.force_sync().await?;
-
- let updates = self.mailbox.update(UpdateParameters::default()).await?;
- Ok((
- Response::build()
- .to_req(self.req)
- .message("NOOP completed.")
- .set_body(updates)
- .ok()?,
- flow::Transition::None,
- ))
- }
-}
diff --git a/src/imap/command/mod.rs b/src/imap/command/mod.rs
index dc95746..073040e 100644
--- a/src/imap/command/mod.rs
+++ b/src/imap/command/mod.rs
@@ -1,7 +1,6 @@
pub mod anonymous;
pub mod anystate;
pub mod authenticated;
-pub mod examined;
pub mod selected;
use crate::mail::user::INBOX;