From 7ebc708acab9c91db41652cfbfe2814a3a27569d Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 3 Jan 2024 09:21:46 +0100 Subject: unselect implemented rfc3691 --- src/imap/command/selected.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/imap/command/selected.rs') diff --git a/src/imap/command/selected.rs b/src/imap/command/selected.rs index 220a952..0653226 100644 --- a/src/imap/command/selected.rs +++ b/src/imap/command/selected.rs @@ -59,6 +59,9 @@ pub async fn dispatch<'a>( uid, } => ctx.copy(sequence_set, mailbox, uid).await, + // UNSELECT extension (rfc3691) + CommandBody::Unselect => ctx.unselect().await, + // In selected mode, we fallback to authenticated when needed _ => { authenticated::dispatch(authenticated::AuthenticatedContext { @@ -84,6 +87,16 @@ impl<'a> SelectedContext<'a> { )) } + async fn unselect(self) -> Result<(Response<'static>, flow::Transition)> { + Ok(( + Response::build() + .to_req(self.req) + .message("UNSELECT completed") + .ok()?, + flow::Transition::Unselect, + )) + } + pub async fn fetch( self, sequence_set: &SequenceSet, -- cgit v1.2.3 From 6d37924399dd5d04f5be2506e3e044dd165f6399 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 3 Jan 2024 12:29:19 +0100 Subject: rework capability --- src/imap/command/selected.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/imap/command/selected.rs') diff --git a/src/imap/command/selected.rs b/src/imap/command/selected.rs index 0653226..681b509 100644 --- a/src/imap/command/selected.rs +++ b/src/imap/command/selected.rs @@ -14,6 +14,7 @@ use crate::imap::command::{anystate, authenticated, MailboxName}; use crate::imap::flow; use crate::imap::mailbox_view::MailboxView; use crate::imap::response::Response; +use crate::imap::capability::ServerCapability; use crate::mail::user::User; @@ -21,6 +22,7 @@ pub struct SelectedContext<'a> { pub req: &'a Command<'static>, pub user: &'a Arc, pub mailbox: &'a mut MailboxView, + pub server_capabilities: &'a ServerCapability, } pub async fn dispatch<'a>( @@ -29,7 +31,10 @@ pub async fn dispatch<'a>( match &ctx.req.body { // Any State // noop is specific to this state - CommandBody::Capability => anystate::capability(ctx.req.tag.clone()), + CommandBody::Capability => anystate::capability( + ctx.req.tag.clone(), + ctx.server_capabilities, + ), CommandBody::Logout => anystate::logout(), // Specific to this state (7 commands + NOOP) @@ -66,6 +71,7 @@ pub async fn dispatch<'a>( _ => { authenticated::dispatch(authenticated::AuthenticatedContext { req: ctx.req, + server_capabilities: ctx.server_capabilities, user: ctx.user, }) .await -- cgit v1.2.3 From ef257e286a5377031bfde9645629825d3223b3d4 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 3 Jan 2024 15:00:05 +0100 Subject: implement move --- src/imap/command/selected.rs | 68 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 5 deletions(-) (limited to 'src/imap/command/selected.rs') diff --git a/src/imap/command/selected.rs b/src/imap/command/selected.rs index 681b509..28ebbe8 100644 --- a/src/imap/command/selected.rs +++ b/src/imap/command/selected.rs @@ -10,11 +10,11 @@ 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::capability::ServerCapability; use crate::imap::command::{anystate, authenticated, MailboxName}; use crate::imap::flow; use crate::imap::mailbox_view::MailboxView; use crate::imap::response::Response; -use crate::imap::capability::ServerCapability; use crate::mail::user::User; @@ -31,10 +31,9 @@ pub async fn dispatch<'a>( match &ctx.req.body { // Any State // noop is specific to this state - CommandBody::Capability => anystate::capability( - ctx.req.tag.clone(), - ctx.server_capabilities, - ), + CommandBody::Capability => { + anystate::capability(ctx.req.tag.clone(), ctx.server_capabilities) + } CommandBody::Logout => anystate::logout(), // Specific to this state (7 commands + NOOP) @@ -63,6 +62,11 @@ pub async fn dispatch<'a>( mailbox, uid, } => ctx.copy(sequence_set, mailbox, uid).await, + CommandBody::Move { + sequence_set, + mailbox, + uid, + } => ctx.r#move(sequence_set, mailbox, uid).await, // UNSELECT extension (rfc3691) CommandBody::Unselect => ctx.unselect().await, @@ -245,4 +249,58 @@ impl<'a> SelectedContext<'a> { flow::Transition::None, )) } + + async fn r#move( + self, + sequence_set: &SequenceSet, + mailbox: &MailboxCodec<'a>, + uid: &bool, + ) -> Result<(Response<'static>, flow::Transition)> { + let name: &str = MailboxName(mailbox).try_into()?; + + let mb_opt = self.user.open_mailbox(&name).await?; + let mb = match mb_opt { + Some(mb) => mb, + None => { + return Ok(( + Response::build() + .to_req(self.req) + .message("Destination mailbox does not exist") + .code(Code::TryCreate) + .no()?, + flow::Transition::None, + )) + } + }; + + let (uidval, uid_map, data) = self.mailbox.r#move(sequence_set, mb, uid).await?; + + // compute code + let copyuid_str = format!( + "{} {} {}", + uidval, + uid_map + .iter() + .map(|(sid, _)| format!("{}", sid)) + .collect::>() + .join(","), + uid_map + .iter() + .map(|(_, tuid)| format!("{}", tuid)) + .collect::>() + .join(",") + ); + + Ok(( + Response::build() + .to_req(self.req) + .message("COPY completed") + .code(Code::Other(CodeOther::unvalidated( + format!("COPYUID {}", copyuid_str).into_bytes(), + ))) + .set_body(data) + .ok()?, + flow::Transition::None, + )) + } } -- cgit v1.2.3 From a6a0e1994db2b43f559e5c2e8ae5c58342e5136f Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 3 Jan 2024 20:53:07 +0100 Subject: ENABLE is now supported --- src/imap/command/selected.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/imap/command/selected.rs') diff --git a/src/imap/command/selected.rs b/src/imap/command/selected.rs index 28ebbe8..c8cc680 100644 --- a/src/imap/command/selected.rs +++ b/src/imap/command/selected.rs @@ -10,7 +10,7 @@ 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::capability::ServerCapability; +use crate::imap::capability::{ClientCapability, ServerCapability}; use crate::imap::command::{anystate, authenticated, MailboxName}; use crate::imap::flow; use crate::imap::mailbox_view::MailboxView; @@ -23,6 +23,7 @@ pub struct SelectedContext<'a> { pub user: &'a Arc, pub mailbox: &'a mut MailboxView, pub server_capabilities: &'a ServerCapability, + pub client_capabilities: &'a mut ClientCapability, } pub async fn dispatch<'a>( @@ -76,6 +77,7 @@ pub async fn dispatch<'a>( authenticated::dispatch(authenticated::AuthenticatedContext { req: ctx.req, server_capabilities: ctx.server_capabilities, + client_capabilities: ctx.client_capabilities, user: ctx.user, }) .await -- cgit v1.2.3