aboutsummaryrefslogtreecommitdiff
path: root/src/imap/command
diff options
context:
space:
mode:
Diffstat (limited to 'src/imap/command')
-rw-r--r--src/imap/command/anonymous.rs22
-rw-r--r--src/imap/command/anystate.rs6
-rw-r--r--src/imap/command/authenticated.rs40
-rw-r--r--src/imap/command/examined.rs16
-rw-r--r--src/imap/command/selected.rs24
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?;