Implement RFC822.TEXT
This commit is contained in:
parent
69428eaf25
commit
0f0a8d415e
6 changed files with 62 additions and 31 deletions
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
pub mod anonymous;
|
||||
pub mod authenticated;
|
||||
pub mod selected;
|
||||
pub mod examined;
|
||||
pub mod selected;
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
@ -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!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue