aboutsummaryrefslogtreecommitdiff
path: root/src/imap/command
diff options
context:
space:
mode:
Diffstat (limited to 'src/imap/command')
-rw-r--r--src/imap/command/anonymous.rs39
-rw-r--r--src/imap/command/authenticated.rs59
-rw-r--r--src/imap/command/selected.rs8
3 files changed, 29 insertions, 77 deletions
diff --git a/src/imap/command/anonymous.rs b/src/imap/command/anonymous.rs
index c1b800e..a2f2260 100644
--- a/src/imap/command/anonymous.rs
+++ b/src/imap/command/anonymous.rs
@@ -10,16 +10,13 @@ use crate::imap::session::InnerContext;
//--- dispatching
pub async fn dispatch<'a>(ctx: InnerContext<'a>) -> Result<(Response, flow::Transition)> {
- match &ctx.req.body {
+ match &ctx.req.command.body {
CommandBody::Capability => capability(ctx).await,
CommandBody::Login { username, password } => login(ctx, username, password).await,
- _ => Status::no(
- Some(ctx.req.tag.clone()),
- None,
- "This command is not available in the ANONYMOUS state.",
- )
- .map(|s| (vec![ImapRes::Status(s)], flow::Transition::No))
- .map_err(Error::msg),
+ _ => Ok((
+ Response::no("This command is not available in the ANONYMOUS state.")?,
+ flow::Transition::No
+ )),
}
}
@@ -27,13 +24,7 @@ pub async fn dispatch<'a>(ctx: InnerContext<'a>) -> Result<(Response, flow::Tran
async fn capability<'a>(ctx: InnerContext<'a>) -> Result<(Response, flow::Transition)> {
let capabilities = vec![Capability::Imap4Rev1, Capability::Idle];
- let res = vec![
- ImapRes::Data(Data::Capability(capabilities)),
- ImapRes::Status(
- Status::ok(Some(ctx.req.tag.clone()), None, "Server capabilities")
- .map_err(Error::msg)?,
- ),
- ];
+ let res = Response::ok("Server capabilities")?.with_body(Data::Capability(capabilities));
Ok((res, flow::Transition::No))
}
@@ -51,13 +42,7 @@ async fn login<'a>(
let creds = match ctx.login.login(&u, &p).await {
Err(e) => {
tracing::debug!(error=%e, "authentication failed");
- return Ok((
- vec![ImapRes::Status(
- Status::no(Some(ctx.req.tag.clone()), None, "Authentication failed")
- .map_err(Error::msg)?,
- )],
- flow::Transition::No,
- ));
+ return Ok((Response::no("Authentication failed")?, flow::Transition::No));
}
Ok(c) => c,
};
@@ -66,16 +51,10 @@ async fn login<'a>(
creds,
name: u.clone(),
};
- let tr = flow::Transition::Authenticate(user);
tracing::info!(username=%u, "connected");
Ok((
- vec![
- //@FIXME we could send a capability status here too
- ImapRes::Status(
- Status::ok(Some(ctx.req.tag.clone()), None, "completed").map_err(Error::msg)?,
- ),
- ],
- tr,
+ Response::ok("Completed")?,
+ flow::Transition::Authenticate(user)
))
}
diff --git a/src/imap/command/authenticated.rs b/src/imap/command/authenticated.rs
index 0b1f01e..85c1c82 100644
--- a/src/imap/command/authenticated.rs
+++ b/src/imap/command/authenticated.rs
@@ -1,7 +1,7 @@
use anyhow::{anyhow, Error, Result};
-use boitalettres::proto::Response;
+use boitalettres::proto::{Response, res::body::Data as Body};
use imap_codec::types::command::CommandBody;
-use imap_codec::types::core::{Atom, Tag};
+use imap_codec::types::core::Atom;
use imap_codec::types::flag::Flag;
use imap_codec::types::mailbox::{ListMailbox, Mailbox as MailboxCodec};
use imap_codec::types::response::{Code, Data, Response as ImapRes, Status};
@@ -23,13 +23,9 @@ pub async fn dispatch<'a>(
inner: InnerContext<'a>,
user: &'a flow::User,
) -> Result<(Response, flow::Transition)> {
- let ctx = StateContext {
- user,
- tag: &inner.req.tag,
- inner,
- };
+ let ctx = StateContext { user, inner };
- match &ctx.inner.req.body {
+ match &ctx.inner.req.command.body {
CommandBody::Lsub {
reference,
mailbox_wildcard,
@@ -48,7 +44,6 @@ pub async fn dispatch<'a>(
struct StateContext<'a> {
inner: InnerContext<'a>,
user: &'a flow::User,
- tag: &'a Tag,
}
impl<'a> StateContext<'a> {
@@ -58,9 +53,7 @@ impl<'a> StateContext<'a> {
mailbox_wildcard: &ListMailbox,
) -> Result<(Response, flow::Transition)> {
Ok((
- vec![ImapRes::Status(
- Status::bad(Some(self.tag.clone()), None, "Not implemented").map_err(Error::msg)?,
- )],
+ Response::bad("Not implemented")?,
flow::Transition::No,
))
}
@@ -71,9 +64,7 @@ impl<'a> StateContext<'a> {
mailbox_wildcard: &ListMailbox,
) -> Result<(Response, flow::Transition)> {
Ok((
- vec![ImapRes::Status(
- Status::bad(Some(self.tag.clone()), None, "Not implemented").map_err(Error::msg)?,
- )],
+ Response::bad("Not implemented")?,
flow::Transition::No,
))
}
@@ -115,20 +106,11 @@ impl<'a> StateContext<'a> {
let sum = mb.summary().await?;
tracing::trace!(summary=%sum, "mailbox.summary");
- let r_unseen = Status::ok(
- None,
- Some(Code::Unseen(
- std::num::NonZeroU32::new(1).ok_or(anyhow!("Invalid message identifier"))?,
- )),
- "First unseen UID",
- )
- .map_err(Error::msg)?;
-
- let mut res = Vec::<ImapRes>::new();
+ let mut res = Vec::<Body>::new();
- res.push(ImapRes::Data(Data::Exists(sum.exists)));
+ res.push(Body::Data(Data::Exists(sum.exists)));
- res.push(ImapRes::Data(Data::Recent(sum.recent)));
+ res.push(Body::Data(Data::Recent(sum.recent)));
let mut flags: Vec<Flag> = sum.flags.map(|f| match f.chars().next() {
Some('\\') => None,
@@ -144,7 +126,7 @@ impl<'a> StateContext<'a> {
}).flatten().collect();
flags.extend_from_slice(&DEFAULT_FLAGS);
- res.push(ImapRes::Data(Data::Flags(flags.clone())));
+ res.push(Body::Data(Data::Flags(flags.clone())));
let uid_validity = Status::ok(
None,
@@ -152,14 +134,14 @@ impl<'a> StateContext<'a> {
"UIDs valid"
)
.map_err(Error::msg)?;
- res.push(ImapRes::Status(uid_validity));
+ res.push(Body::Status(uid_validity));
let next_uid = Status::ok(
None,
Some(Code::UidNext(sum.next)),
"Predict next UID"
).map_err(Error::msg)?;
- res.push(ImapRes::Status(next_uid));
+ res.push(Body::Status(next_uid));
if let Some(unseen) = sum.unseen {
let status_unseen = Status::ok(
@@ -168,7 +150,7 @@ impl<'a> StateContext<'a> {
"First unseen UID",
)
.map_err(Error::msg)?;
- res.push(ImapRes::Status(status_unseen));
+ res.push(Body::Status(status_unseen));
}
flags.push(Flag::Permanent);
@@ -177,16 +159,11 @@ impl<'a> StateContext<'a> {
Some(Code::PermanentFlags(flags)),
"Flags permitted",
).map_err(Error::msg)?;
- res.push(ImapRes::Status(permanent_flags));
-
- let last = Status::ok(
- Some(self.tag.clone()),
- Some(Code::ReadWrite),
- "Select completed",
- ).map_err(Error::msg)?;
- res.push(ImapRes::Status(last));
+ res.push(Body::Status(permanent_flags));
- let tr = flow::Transition::Select(mb);
- Ok((res, tr))
+ Ok((
+ Response::ok("Select completed")?.with_body(res),
+ flow::Transition::Select(mb),
+ ))
}
}
diff --git a/src/imap/command/selected.rs b/src/imap/command/selected.rs
index e44bf36..e013eaa 100644
--- a/src/imap/command/selected.rs
+++ b/src/imap/command/selected.rs
@@ -17,13 +17,12 @@ pub async fn dispatch<'a>(
mailbox: &'a Mailbox,
) -> Result<(Response, flow::Transition)> {
let ctx = StateContext {
- tag: &inner.req.tag,
inner,
user,
mailbox,
};
- match &ctx.inner.req.body {
+ match &ctx.inner.req.command.body {
CommandBody::Fetch {
sequence_set,
attributes,
@@ -39,7 +38,6 @@ struct StateContext<'a> {
inner: InnerContext<'a>,
user: &'a flow::User,
mailbox: &'a Mailbox,
- tag: &'a Tag,
}
impl<'a> StateContext<'a> {
@@ -50,9 +48,7 @@ impl<'a> StateContext<'a> {
uid: &bool,
) -> Result<(Response, flow::Transition)> {
Ok((
- vec![ImapRes::Status(
- Status::bad(Some(self.tag.clone()), None, "Not implemented").map_err(Error::msg)?,
- )],
+ Response::bad("Not implemented")?,
flow::Transition::No,
))
}