aboutsummaryrefslogtreecommitdiff
path: root/src/imap/command/examined.rs
diff options
context:
space:
mode:
authorQuentin <quentin@dufour.io>2024-01-04 11:11:01 +0000
committerQuentin <quentin@dufour.io>2024-01-04 11:11:01 +0000
commitbcf6de83419b405fea95b740869f98d43586ea7c (patch)
tree9f52832b90685913beda8f1bf19a22b2ec7bc6c6 /src/imap/command/examined.rs
parentb9a0c1e6eced036eb71e8221a4f236f72832fec2 (diff)
parent7ae9966675c85b34f1a99d81062b44b74385a15b (diff)
downloadaerogramme-bcf6de83419b405fea95b740869f98d43586ea7c.tar.gz
aerogramme-bcf6de83419b405fea95b740869f98d43586ea7c.zip
Merge pull request 'Implement some IMAP extensions' (#50) from feat/more-ext into main
Reviewed-on: https://git.deuxfleurs.fr/Deuxfleurs/aerogramme/pulls/50
Diffstat (limited to 'src/imap/command/examined.rs')
-rw-r--r--src/imap/command/examined.rs20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/imap/command/examined.rs b/src/imap/command/examined.rs
index 7de94f4..0d688c0 100644
--- a/src/imap/command/examined.rs
+++ b/src/imap/command/examined.rs
@@ -7,6 +7,7 @@ use imap_codec::imap_types::fetch::MacroOrMessageDataItemNames;
use imap_codec::imap_types::search::SearchKey;
use imap_codec::imap_types::sequence::SequenceSet;
+use crate::imap::capability::{ClientCapability, ServerCapability};
use crate::imap::command::{anystate, authenticated};
use crate::imap::flow;
use crate::imap::mailbox_view::MailboxView;
@@ -17,18 +18,22 @@ pub struct ExaminedContext<'a> {
pub req: &'a Command<'static>,
pub user: &'a Arc<User>,
pub mailbox: &'a mut MailboxView,
+ pub server_capabilities: &'a ServerCapability,
+ pub client_capabilities: &'a mut ClientCapability,
}
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::Capability => {
+ anystate::capability(ctx.req.tag.clone(), ctx.server_capabilities)
+ }
CommandBody::Logout => anystate::logout(),
// Specific to the EXAMINE state (specialization of the SELECTED state)
// ~3 commands -> close, fetch, search + NOOP
- CommandBody::Close => ctx.close().await,
+ CommandBody::Close => ctx.close("CLOSE").await,
CommandBody::Fetch {
sequence_set,
macro_or_item_names,
@@ -44,14 +49,19 @@ pub async fn dispatch(ctx: ExaminedContext<'_>) -> Result<(Response<'static>, fl
Response::build()
.to_req(ctx.req)
.message("Forbidden command: can't write in read-only mode (EXAMINE)")
- .bad()?,
+ .no()?,
flow::Transition::None,
)),
+ // UNSELECT extension (rfc3691)
+ CommandBody::Unselect => ctx.close("UNSELECT").await,
+
// In examined mode, we fallback to authenticated when needed
_ => {
authenticated::dispatch(authenticated::AuthenticatedContext {
req: ctx.req,
+ server_capabilities: ctx.server_capabilities,
+ client_capabilities: ctx.client_capabilities,
user: ctx.user,
})
.await
@@ -64,11 +74,11 @@ pub async fn dispatch(ctx: ExaminedContext<'_>) -> Result<(Response<'static>, fl
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<'static>, flow::Transition)> {
+ async fn close(self, kind: &str) -> Result<(Response<'static>, flow::Transition)> {
Ok((
Response::build()
.to_req(self.req)
- .message("CLOSE completed")
+ .message(format!("{} completed", kind))
.ok()?,
flow::Transition::Unselect,
))