aboutsummaryrefslogtreecommitdiff
path: root/src/imap/command/authenticated.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/imap/command/authenticated.rs')
-rw-r--r--src/imap/command/authenticated.rs33
1 files changed, 30 insertions, 3 deletions
diff --git a/src/imap/command/authenticated.rs b/src/imap/command/authenticated.rs
index 1bb4c6d..1481a80 100644
--- a/src/imap/command/authenticated.rs
+++ b/src/imap/command/authenticated.rs
@@ -3,13 +3,15 @@ use std::sync::Arc;
use anyhow::{anyhow, bail, Result};
use imap_codec::imap_types::command::{Command, CommandBody};
-use imap_codec::imap_types::core::{Atom, Literal, QuotedChar};
+use imap_codec::imap_types::core::{Atom, Literal, NonEmptyVec, QuotedChar};
use imap_codec::imap_types::datetime::DateTime;
+use imap_codec::imap_types::extensions::enable::CapabilityEnable;
use imap_codec::imap_types::flag::{Flag, FlagNameAttribute};
use imap_codec::imap_types::mailbox::{ListMailbox, Mailbox as MailboxCodec};
use imap_codec::imap_types::response::{Code, CodeOther, Data};
use imap_codec::imap_types::status::{StatusDataItem, StatusDataItemName};
+use crate::imap::capability::{ClientCapability, ServerCapability};
use crate::imap::command::{anystate, MailboxName};
use crate::imap::flow;
use crate::imap::mailbox_view::MailboxView;
@@ -22,6 +24,8 @@ use crate::mail::IMF;
pub struct AuthenticatedContext<'a> {
pub req: &'a Command<'static>,
+ pub server_capabilities: &'a ServerCapability,
+ pub client_capabilities: &'a mut ClientCapability,
pub user: &'a Arc<User>,
}
@@ -31,7 +35,9 @@ pub async fn dispatch<'a>(
match &ctx.req.body {
// Any state
CommandBody::Noop => anystate::noop_nothing(ctx.req.tag.clone()),
- 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 (11 commands)
@@ -61,6 +67,9 @@ pub async fn dispatch<'a>(
message,
} => ctx.append(mailbox, flags, date, message).await,
+ // rfc5161 ENABLE
+ CommandBody::Enable { capabilities } => ctx.enable(capabilities),
+
// Collect other commands
_ => anystate::wrong_state(ctx.req.tag.clone()),
}
@@ -301,6 +310,9 @@ impl<'a> AuthenticatedContext<'a> {
StatusDataItemName::DeletedStorage => {
bail!("quota not implemented, can't return freed storage after EXPUNGE will be run");
},
+ StatusDataItemName::HighestModSeq => {
+ bail!("highestmodseq not yet implemented");
+ }
});
}
@@ -504,6 +516,21 @@ impl<'a> AuthenticatedContext<'a> {
}
}
+ fn enable(
+ self,
+ cap_enable: &NonEmptyVec<CapabilityEnable<'static>>,
+ ) -> Result<(Response<'static>, flow::Transition)> {
+ let mut response_builder = Response::build().to_req(self.req);
+ let capabilities = self.client_capabilities.try_enable(cap_enable.as_ref());
+ if capabilities.len() > 0 {
+ response_builder = response_builder.data(Data::Enabled { capabilities });
+ }
+ Ok((
+ response_builder.message("ENABLE completed").ok()?,
+ flow::Transition::None,
+ ))
+ }
+
pub(crate) async fn append_internal(
self,
mailbox: &MailboxCodec<'a>,
@@ -520,7 +547,7 @@ impl<'a> AuthenticatedContext<'a> {
};
if date.is_some() {
- bail!("Cannot set date when appending message");
+ tracing::warn!("Cannot set date when appending message");
}
let msg =