diff options
Diffstat (limited to 'src/imap/command')
-rw-r--r-- | src/imap/command/anonymous.rs | 22 | ||||
-rw-r--r-- | src/imap/command/anystate.rs | 6 | ||||
-rw-r--r-- | src/imap/command/authenticated.rs | 40 | ||||
-rw-r--r-- | src/imap/command/examined.rs | 16 | ||||
-rw-r--r-- | src/imap/command/selected.rs | 24 |
5 files changed, 55 insertions, 53 deletions
diff --git a/src/imap/command/anonymous.rs b/src/imap/command/anonymous.rs index 4de5fbd..fbd10e9 100644 --- a/src/imap/command/anonymous.rs +++ b/src/imap/command/anonymous.rs @@ -1,7 +1,6 @@ use anyhow::Result; use imap_codec::imap_types::command::{Command, CommandBody}; -use imap_codec::imap_types::core::{AString, NonEmptyVec}; -use imap_codec::imap_types::response::{Capability, Data}; +use imap_codec::imap_types::core::AString; use imap_codec::imap_types::secret::Secret; use crate::imap::command::anystate; @@ -13,16 +12,16 @@ use crate::mail::user::User; //--- dispatching pub struct AnonymousContext<'a> { - pub req: &'a Command<'a>, + pub req: &'a Command<'static>, pub login_provider: &'a ArcLoginProvider, } -pub async fn dispatch<'a>(ctx: AnonymousContext<'a>) -> Result<(Response<'a>, flow::Transition)> { +pub async fn dispatch(ctx: AnonymousContext<'_>) -> Result<(Response<'static>, flow::Transition)> { match &ctx.req.body { // Any State CommandBody::Noop => anystate::noop_nothing(ctx.req.tag.clone()), CommandBody::Capability => anystate::capability(ctx.req.tag.clone()), - CommandBody::Logout => Ok((Response::bye()?, flow::Transition::Logout)), + CommandBody::Logout => anystate::logout(), // Specific to anonymous context (3 commands) CommandBody::Login { username, password } => ctx.login(username, password).await, @@ -39,22 +38,11 @@ pub async fn dispatch<'a>(ctx: AnonymousContext<'a>) -> Result<(Response<'a>, fl //--- Command controllers, private impl<'a> AnonymousContext<'a> { - async fn capability(self) -> Result<(Response<'a>, flow::Transition)> { - let capabilities: NonEmptyVec<Capability> = - (vec![Capability::Imap4Rev1, Capability::Idle]).try_into()?; - let res = Response::build() - .to_req(self.req) - .message("Server capabilities") - .data(Data::Capability(capabilities)) - .ok()?; - Ok((res, flow::Transition::None)) - } - async fn login( self, username: &AString<'a>, password: &Secret<AString<'a>>, - ) -> Result<(Response<'a>, flow::Transition)> { + ) -> Result<(Response<'static>, flow::Transition)> { let (u, p) = ( std::str::from_utf8(username.as_ref())?, std::str::from_utf8(password.declassify().as_ref())?, diff --git a/src/imap/command/anystate.rs b/src/imap/command/anystate.rs index ea3bc16..42fe645 100644 --- a/src/imap/command/anystate.rs +++ b/src/imap/command/anystate.rs @@ -5,7 +5,7 @@ use imap_codec::imap_types::response::{Capability, Data}; use crate::imap::flow; use crate::imap::response::Response; -pub(crate) fn capability<'a>(tag: Tag<'a>) -> Result<(Response<'a>, flow::Transition)> { +pub(crate) fn capability(tag: Tag<'static>) -> Result<(Response<'static>, flow::Transition)> { let capabilities: NonEmptyVec<Capability> = (vec![Capability::Imap4Rev1, Capability::Idle]).try_into()?; let res = Response::build() @@ -17,7 +17,7 @@ pub(crate) fn capability<'a>(tag: Tag<'a>) -> Result<(Response<'a>, flow::Transi Ok((res, flow::Transition::None)) } -pub(crate) fn noop_nothing<'a>(tag: Tag<'a>) -> Result<(Response<'a>, flow::Transition)> { +pub(crate) fn noop_nothing(tag: Tag<'static>) -> Result<(Response<'static>, flow::Transition)> { Ok(( Response::build().tag(tag).message("Noop completed.").ok()?, flow::Transition::None, @@ -41,7 +41,7 @@ pub(crate) fn not_implemented<'a>( )) } -pub(crate) fn wrong_state<'a>(tag: Tag<'a>) -> Result<(Response<'a>, flow::Transition)> { +pub(crate) fn wrong_state(tag: Tag<'static>) -> Result<(Response<'static>, flow::Transition)> { Ok(( Response::build() .tag(tag) diff --git a/src/imap/command/authenticated.rs b/src/imap/command/authenticated.rs index c9f9ff7..74ebbfa 100644 --- a/src/imap/command/authenticated.rs +++ b/src/imap/command/authenticated.rs @@ -21,18 +21,18 @@ use crate::mail::user::{User, MAILBOX_HIERARCHY_DELIMITER as MBX_HIER_DELIM_RAW} use crate::mail::IMF; pub struct AuthenticatedContext<'a> { - pub req: &'a Command<'a>, + pub req: &'a Command<'static>, pub user: &'a Arc<User>, } pub async fn dispatch<'a>( ctx: AuthenticatedContext<'a>, -) -> Result<(Response<'a>, flow::Transition)> { +) -> Result<(Response<'static>, flow::Transition)> { match &ctx.req.body { // Any state CommandBody::Noop => anystate::noop_nothing(ctx.req.tag.clone()), CommandBody::Capability => anystate::capability(ctx.req.tag.clone()), - CommandBody::Logout => Ok((Response::bye()?, flow::Transition::Logout)), + CommandBody::Logout => anystate::logout(), // Specific to this state (11 commands) CommandBody::Create { mailbox } => ctx.create(mailbox).await, @@ -68,7 +68,10 @@ pub async fn dispatch<'a>( // --- PRIVATE --- impl<'a> AuthenticatedContext<'a> { - async fn create(self, mailbox: &MailboxCodec<'a>) -> Result<(Response<'a>, flow::Transition)> { + async fn create( + self, + mailbox: &MailboxCodec<'a>, + ) -> Result<(Response<'static>, flow::Transition)> { let name = match mailbox { MailboxCodec::Inbox => { return Ok(( @@ -100,7 +103,10 @@ impl<'a> AuthenticatedContext<'a> { } } - async fn delete(self, mailbox: &MailboxCodec<'a>) -> Result<(Response<'a>, flow::Transition)> { + async fn delete( + self, + mailbox: &MailboxCodec<'a>, + ) -> Result<(Response<'static>, flow::Transition)> { let name: &str = MailboxName(mailbox).try_into()?; match self.user.delete_mailbox(&name).await { @@ -125,7 +131,7 @@ impl<'a> AuthenticatedContext<'a> { self, from: &MailboxCodec<'a>, to: &MailboxCodec<'a>, - ) -> Result<(Response<'a>, flow::Transition)> { + ) -> Result<(Response<'static>, flow::Transition)> { let name: &str = MailboxName(from).try_into()?; let new_name: &str = MailboxName(to).try_into()?; @@ -152,7 +158,7 @@ impl<'a> AuthenticatedContext<'a> { reference: &MailboxCodec<'a>, mailbox_wildcard: &ListMailbox<'a>, is_lsub: bool, - ) -> Result<(Response<'a>, flow::Transition)> { + ) -> Result<(Response<'static>, flow::Transition)> { let mbx_hier_delim: QuotedChar = QuotedChar::unvalidated(MBX_HIER_DELIM_RAW); let reference: &str = MailboxName(reference).try_into()?; @@ -259,9 +265,9 @@ impl<'a> AuthenticatedContext<'a> { async fn status( self, - mailbox: &MailboxCodec<'a>, + mailbox: &MailboxCodec<'static>, attributes: &[StatusDataItemName], - ) -> Result<(Response<'a>, flow::Transition)> { + ) -> 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 { @@ -316,7 +322,7 @@ impl<'a> AuthenticatedContext<'a> { async fn subscribe( self, mailbox: &MailboxCodec<'a>, - ) -> Result<(Response<'a>, flow::Transition)> { + ) -> Result<(Response<'static>, flow::Transition)> { let name: &str = MailboxName(mailbox).try_into()?; if self.user.has_mailbox(&name).await? { @@ -341,7 +347,7 @@ impl<'a> AuthenticatedContext<'a> { async fn unsubscribe( self, mailbox: &MailboxCodec<'a>, - ) -> Result<(Response<'a>, flow::Transition)> { + ) -> Result<(Response<'static>, flow::Transition)> { let name: &str = MailboxName(mailbox).try_into()?; if self.user.has_mailbox(&name).await? { @@ -399,7 +405,10 @@ impl<'a> AuthenticatedContext<'a> { * TRACE END --- */ - async fn select(self, mailbox: &MailboxCodec<'a>) -> Result<(Response<'a>, flow::Transition)> { + async fn select( + self, + mailbox: &MailboxCodec<'a>, + ) -> Result<(Response<'static>, flow::Transition)> { let name: &str = MailboxName(mailbox).try_into()?; let mb_opt = self.user.open_mailbox(&name).await?; @@ -430,7 +439,10 @@ impl<'a> AuthenticatedContext<'a> { )) } - async fn examine(self, mailbox: &MailboxCodec<'a>) -> Result<(Response<'a>, flow::Transition)> { + async fn examine( + self, + mailbox: &MailboxCodec<'a>, + ) -> Result<(Response<'static>, flow::Transition)> { let name: &str = MailboxName(mailbox).try_into()?; let mb_opt = self.user.open_mailbox(&name).await?; @@ -468,7 +480,7 @@ impl<'a> AuthenticatedContext<'a> { flags: &[Flag<'a>], date: &Option<DateTime>, message: &Literal<'a>, - ) -> Result<(Response<'a>, flow::Transition)> { + ) -> 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)) => Ok(( diff --git a/src/imap/command/examined.rs b/src/imap/command/examined.rs index 7f9c39c..eec85cd 100644 --- a/src/imap/command/examined.rs +++ b/src/imap/command/examined.rs @@ -14,17 +14,17 @@ use crate::imap::response::Response; use crate::mail::user::User; pub struct ExaminedContext<'a> { - pub req: &'a Command<'a>, + pub req: &'a Command<'static>, pub user: &'a Arc<User>, pub mailbox: &'a mut MailboxView, } -pub async fn dispatch<'a>(ctx: ExaminedContext<'a>) -> Result<(Response<'a>, flow::Transition)> { +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()), - CommandBody::Logout => Ok((Response::bye()?, flow::Transition::Logout)), + CommandBody::Logout => anystate::logout(), // Specific to the EXAMINE state (specialization of the SELECTED state) // ~3 commands -> close, fetch, search + NOOP @@ -58,7 +58,7 @@ pub async fn dispatch<'a>(ctx: ExaminedContext<'a>) -> Result<(Response<'a>, flo 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) -> Result<(Response<'a>, flow::Transition)> { + async fn close(self) -> Result<(Response<'static>, flow::Transition)> { Ok(( Response::build() .to_req(self.req) @@ -71,9 +71,9 @@ impl<'a> ExaminedContext<'a> { pub async fn fetch( self, sequence_set: &SequenceSet, - attributes: &'a MacroOrMessageDataItemNames<'a>, + attributes: &'a MacroOrMessageDataItemNames<'static>, uid: &bool, - ) -> Result<(Response<'a>, flow::Transition)> { + ) -> Result<(Response<'static>, flow::Transition)> { match self.mailbox.fetch(sequence_set, attributes, uid).await { Ok(resp) => Ok(( Response::build() @@ -98,7 +98,7 @@ impl<'a> ExaminedContext<'a> { _charset: &Option<Charset<'a>>, _criteria: &SearchKey<'a>, _uid: &bool, - ) -> Result<(Response<'a>, flow::Transition)> { + ) -> Result<(Response<'static>, flow::Transition)> { Ok(( Response::build() .to_req(self.req) @@ -108,7 +108,7 @@ impl<'a> ExaminedContext<'a> { )) } - pub async fn noop(self) -> Result<(Response<'a>, flow::Transition)> { + pub async fn noop(self) -> Result<(Response<'static>, flow::Transition)> { self.mailbox.mailbox.force_sync().await?; let updates = self.mailbox.update().await?; diff --git a/src/imap/command/selected.rs b/src/imap/command/selected.rs index cd5d221..d5dcd61 100644 --- a/src/imap/command/selected.rs +++ b/src/imap/command/selected.rs @@ -18,17 +18,19 @@ use crate::imap::response::Response; use crate::mail::user::User; pub struct SelectedContext<'a> { - pub req: &'a Command<'a>, + pub req: &'a Command<'static>, pub user: &'a Arc<User>, pub mailbox: &'a mut MailboxView, } -pub async fn dispatch<'a>(ctx: SelectedContext<'a>) -> Result<(Response<'a>, flow::Transition)> { +pub async fn dispatch<'a>( + ctx: SelectedContext<'a>, +) -> 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()), - CommandBody::Logout => Ok((Response::bye()?, flow::Transition::Logout)), + CommandBody::Logout => anystate::logout(), // Specific to this state (7 commands + NOOP) CommandBody::Close => ctx.close().await, @@ -65,7 +67,7 @@ pub async fn dispatch<'a>(ctx: SelectedContext<'a>) -> Result<(Response<'a>, flo // --- PRIVATE --- impl<'a> SelectedContext<'a> { - async fn close(self) -> Result<(Response<'a>, flow::Transition)> { + async fn close(self) -> Result<(Response<'static>, flow::Transition)> { // We expunge messages, // but we don't send the untagged EXPUNGE responses let tag = self.req.tag.clone(); @@ -79,9 +81,9 @@ impl<'a> SelectedContext<'a> { pub async fn fetch( self, sequence_set: &SequenceSet, - attributes: &'a MacroOrMessageDataItemNames<'a>, + attributes: &'a MacroOrMessageDataItemNames<'static>, uid: &bool, - ) -> Result<(Response<'a>, flow::Transition)> { + ) -> Result<(Response<'static>, flow::Transition)> { match self.mailbox.fetch(sequence_set, attributes, uid).await { Ok(resp) => Ok(( Response::build() @@ -106,7 +108,7 @@ impl<'a> SelectedContext<'a> { _charset: &Option<Charset<'a>>, _criteria: &SearchKey<'a>, _uid: &bool, - ) -> Result<(Response<'a>, flow::Transition)> { + ) -> Result<(Response<'static>, flow::Transition)> { Ok(( Response::build() .to_req(self.req) @@ -116,7 +118,7 @@ impl<'a> SelectedContext<'a> { )) } - pub async fn noop(self) -> Result<(Response<'a>, flow::Transition)> { + pub async fn noop(self) -> Result<(Response<'static>, flow::Transition)> { self.mailbox.mailbox.force_sync().await?; let updates = self.mailbox.update().await?; @@ -130,7 +132,7 @@ impl<'a> SelectedContext<'a> { )) } - async fn expunge(self) -> Result<(Response<'a>, flow::Transition)> { + async fn expunge(self) -> Result<(Response<'static>, flow::Transition)> { let tag = self.req.tag.clone(); let data = self.mailbox.expunge().await?; @@ -151,7 +153,7 @@ impl<'a> SelectedContext<'a> { response: &StoreResponse, flags: &[Flag<'a>], uid: &bool, - ) -> Result<(Response<'a>, flow::Transition)> { + ) -> Result<(Response<'static>, flow::Transition)> { let data = self .mailbox .store(sequence_set, kind, response, flags, uid) @@ -172,7 +174,7 @@ impl<'a> SelectedContext<'a> { sequence_set: &SequenceSet, mailbox: &MailboxCodec<'a>, uid: &bool, - ) -> Result<(Response<'a>, flow::Transition)> { + ) -> Result<(Response<'static>, flow::Transition)> { let name: &str = MailboxName(mailbox).try_into()?; let mb_opt = self.user.open_mailbox(&name).await?; |