diff options
Diffstat (limited to 'src/imap/command/authenticated.rs')
-rw-r--r-- | src/imap/command/authenticated.rs | 33 |
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 = |