From 0f0a8d415e45df178778260d3be1b83ab2785675 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Thu, 30 Jun 2022 13:36:21 +0200 Subject: [PATCH] Implement RFC822.TEXT --- src/imap/command/authenticated.rs | 17 +++++++++--- src/imap/command/examined.rs | 4 +-- src/imap/command/mod.rs | 2 +- src/imap/command/selected.rs | 22 ++++++--------- src/imap/mailbox_view.rs | 46 +++++++++++++++++++++++++------ src/imap/session.rs | 2 +- 6 files changed, 62 insertions(+), 31 deletions(-) diff --git a/src/imap/command/authenticated.rs b/src/imap/command/authenticated.rs index 391b7ff..dfcb52e 100644 --- a/src/imap/command/authenticated.rs +++ b/src/imap/command/authenticated.rs @@ -19,7 +19,10 @@ pub async fn dispatch<'a>(ctx: AuthenticatedContext<'a>) -> Result<(Response, fl match &ctx.req.command.body { CommandBody::Create { mailbox } => ctx.create(mailbox).await, CommandBody::Delete { mailbox } => ctx.delete(mailbox).await, - CommandBody::Rename { mailbox, new_mailbox } => ctx.rename(mailbox, new_mailbox).await, + CommandBody::Rename { + mailbox, + new_mailbox, + } => ctx.rename(mailbox, new_mailbox).await, CommandBody::Lsub { reference, mailbox_wildcard, @@ -28,8 +31,10 @@ pub async fn dispatch<'a>(ctx: AuthenticatedContext<'a>) -> Result<(Response, fl reference, mailbox_wildcard, } => ctx.list(reference, mailbox_wildcard).await, - CommandBody::Status { mailbox, attributes } => - ctx.status(mailbox, attributes).await, + CommandBody::Status { + mailbox, + attributes, + } => ctx.status(mailbox, attributes).await, CommandBody::Select { mailbox } => ctx.select(mailbox).await, CommandBody::Examine { mailbox } => ctx.examine(mailbox).await, _ => { @@ -53,7 +58,11 @@ impl<'a> AuthenticatedContext<'a> { Ok((Response::bad("Not implemented")?, flow::Transition::None)) } - async fn rename(self, mailbox: &MailboxCodec, new_mailbox: &MailboxCodec) -> Result<(Response, flow::Transition)> { + async fn rename( + self, + mailbox: &MailboxCodec, + new_mailbox: &MailboxCodec, + ) -> Result<(Response, flow::Transition)> { Ok((Response::bad("Not implemented")?, flow::Transition::None)) } diff --git a/src/imap/command/examined.rs b/src/imap/command/examined.rs index d459cf0..aad7874 100644 --- a/src/imap/command/examined.rs +++ b/src/imap/command/examined.rs @@ -48,9 +48,7 @@ pub async fn dispatch<'a>(ctx: ExaminedContext<'a>) -> Result<(Response, flow::T // --- PRIVATE --- impl<'a> ExaminedContext<'a> { - async fn close( - self, - ) -> Result<(Response, flow::Transition)> { + async fn close(self) -> Result<(Response, flow::Transition)> { Ok((Response::ok("CLOSE completed")?, flow::Transition::Unselect)) } diff --git a/src/imap/command/mod.rs b/src/imap/command/mod.rs index 559dddf..0b7e576 100644 --- a/src/imap/command/mod.rs +++ b/src/imap/command/mod.rs @@ -1,4 +1,4 @@ pub mod anonymous; pub mod authenticated; -pub mod selected; pub mod examined; +pub mod selected; diff --git a/src/imap/command/selected.rs b/src/imap/command/selected.rs index b8598f5..a447a49 100644 --- a/src/imap/command/selected.rs +++ b/src/imap/command/selected.rs @@ -2,9 +2,9 @@ use anyhow::Result; use boitalettres::proto::Request; use boitalettres::proto::Response; use imap_codec::types::command::CommandBody; -use imap_codec::types::mailbox::{Mailbox as MailboxCodec}; -use imap_codec::types::flag::{Flag, StoreType, StoreResponse}; use imap_codec::types::fetch_attributes::MacroOrFetchAttributes; +use imap_codec::types::flag::{Flag, StoreResponse, StoreType}; +use imap_codec::types::mailbox::Mailbox as MailboxCodec; use imap_codec::types::sequence::SequenceSet; @@ -27,11 +27,11 @@ pub async fn dispatch<'a>(ctx: SelectedContext<'a>) -> Result<(Response, flow::T CommandBody::Close => ctx.close().await, CommandBody::Expunge => ctx.expunge().await, CommandBody::Store { - sequence_set, - kind, - response, - flags, - uid + sequence_set, + kind, + response, + flags, + uid, } => ctx.store(sequence_set, kind, response, flags, uid).await, CommandBody::Copy { sequence_set, @@ -52,18 +52,14 @@ pub async fn dispatch<'a>(ctx: SelectedContext<'a>) -> Result<(Response, flow::T // --- PRIVATE --- impl<'a> SelectedContext<'a> { - async fn close( - self, - ) -> Result<(Response, flow::Transition)> { + async fn close(self) -> Result<(Response, flow::Transition)> { // We expunge messages, // but we don't send the untagged EXPUNGE responses self.expunge().await?; Ok((Response::ok("CLOSE completed")?, flow::Transition::Unselect)) } - async fn expunge( - self, - ) -> Result<(Response, flow::Transition)> { + async fn expunge(self) -> Result<(Response, flow::Transition)> { Ok((Response::bad("Not implemented")?, flow::Transition::None)) } diff --git a/src/imap/mailbox_view.rs b/src/imap/mailbox_view.rs index 58e71a2..0feb588 100644 --- a/src/imap/mailbox_view.rs +++ b/src/imap/mailbox_view.rs @@ -6,7 +6,7 @@ use anyhow::{anyhow, bail, Error, Result}; use boitalettres::proto::res::body::Data as Body; use futures::stream::{FuturesOrdered, StreamExt}; use imap_codec::types::address::Address; -use imap_codec::types::core::{Atom, IString, NString}; +use imap_codec::types::core::{Atom, IString, NString, NonZeroBytes}; use imap_codec::types::envelope::Envelope; use imap_codec::types::fetch_attributes::{FetchAttribute, MacroOrFetchAttributes}; use imap_codec::types::flag::Flag; @@ -247,21 +247,49 @@ impl MailboxView { FetchAttribute::Rfc822Size => { attributes.push(MessageAttribute::Rfc822Size(meta.rfc822_size as u32)) } - FetchAttribute::Rfc822Header => { - attributes.push(MessageAttribute::Rfc822Header(NString(Some( - IString::Literal(meta.headers.clone().try_into().unwrap()), + FetchAttribute::Rfc822Header => attributes.push( + MessageAttribute::Rfc822Header(NString(Some(IString::Literal( + meta.headers + .clone() + .try_into() + .or(Err(Error::msg("IString conversion error")))?, + )))), + ), + FetchAttribute::Rfc822Text => { + let r = parsed + .raw_message.get(parsed.offset_body..parsed.offset_end) + .ok_or(Error::msg("Unable to extract email body, cursors out of bound. This is a bug."))? + .try_into() + .or(Err(Error::msg("IString conversion error")))?; + + attributes.push(MessageAttribute::Rfc822Text(NString(Some( + IString::Literal(r), )))) } FetchAttribute::Rfc822 => { - attributes.push(MessageAttribute::Rfc822(NString(Some( - IString::Literal(body.as_ref().unwrap().clone().try_into().unwrap()), - )))) + attributes.push(MessageAttribute::Rfc822(NString(Some(IString::Literal( + body.as_ref().unwrap().clone().try_into().unwrap(), + ))))) } FetchAttribute::Envelope => { attributes.push(MessageAttribute::Envelope(message_envelope(&parsed))) } - // TODO - _ => (), + FetchAttribute::Body => { + todo!() + } + FetchAttribute::BodyExt { + section, + partial, + peek, + } => { + todo!() + } + FetchAttribute::BodyStructure => { + todo!() + } + FetchAttribute::InternalDate => { + todo!() + } } } diff --git a/src/imap/session.rs b/src/imap/session.rs index 17753ea..9841cf8 100644 --- a/src/imap/session.rs +++ b/src/imap/session.rs @@ -7,7 +7,7 @@ use futures::future::FutureExt; use tokio::sync::mpsc::error::TrySendError; use tokio::sync::{mpsc, oneshot}; -use crate::imap::command::{anonymous, authenticated, selected, examined}; +use crate::imap::command::{anonymous, authenticated, examined, selected}; use crate::imap::flow; use crate::login::ArcLoginProvider;