aboutsummaryrefslogtreecommitdiff
path: root/src/imap/mail_view.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/imap/mail_view.rs')
-rw-r--r--src/imap/mail_view.rs94
1 files changed, 38 insertions, 56 deletions
diff --git a/src/imap/mail_view.rs b/src/imap/mail_view.rs
index 94215dc..1f87f02 100644
--- a/src/imap/mail_view.rs
+++ b/src/imap/mail_view.rs
@@ -1,9 +1,9 @@
use std::num::NonZeroU32;
-use anyhow::{anyhow, bail, Result, Context};
+use anyhow::{anyhow, bail, Result};
use chrono::{Offset, TimeZone, Utc};
-use imap_codec::imap_types::core::{IString, NString};
+use imap_codec::imap_types::core::NString;
use imap_codec::imap_types::datetime::DateTime;
use imap_codec::imap_types::fetch::{
MessageDataItem, MessageDataItemName, Section as FetchSection,
@@ -16,87 +16,73 @@ use eml_codec::{
part::{composite::Message, AnyPart},
};
+
+use crate::mail::query::QueryResult;
+
use crate::imap::attributes::AttributesProxy;
use crate::imap::flags;
use crate::imap::imf_view::message_envelope;
-use crate::imap::mailbox_view::MailIdentifiers;
use crate::imap::mime_view;
use crate::imap::response::Body;
-use crate::mail::query::QueryResult;
+use crate::imap::index::MailIndex;
pub struct MailView<'a> {
+ pub in_idx: MailIndex<'a>,
pub query_result: &'a QueryResult<'a>,
pub content: FetchedMail<'a>,
}
impl<'a> MailView<'a> {
- pub fn new(query_result: &'a QueryResult<'a>) -> Result<Self> {
+ pub fn new(query_result: &'a QueryResult<'a>, in_idx: MailIndex<'a>) -> Result<MailView<'a>> {
Ok(Self {
+ in_idx,
query_result,
content: match query_result {
QueryResult::FullResult { content, .. } => {
- let (_, parsed) = eml_codec::parse_message(content).context("Invalid mail body")?;
+ let (_, parsed) = eml_codec::parse_message(&content).or(Err(anyhow!("Invalid mail body")))?;
FetchedMail::new_from_message(parsed)
},
QueryResult::PartialResult { metadata, .. } => {
- let (_, parsed) = eml_codec::parse_imf(&metadata.headers).context("Invalid mail headers")?;
+ let (_, parsed) = eml_codec::parse_imf(&metadata.headers).or(Err(anyhow!("unable to parse email headers")))?;
FetchedMail::Partial(parsed)
}
- QueryResult::IndexResult { .. } => FetchedMail::None,
+ QueryResult::IndexResult { .. } => FetchedMail::IndexOnly,
}
})
}
-
+
fn uid(&self) -> MessageDataItem<'static> {
- MessageDataItem::Uid(self.ids.uid.clone())
+ MessageDataItem::Uid(self.in_idx.uid.clone())
}
fn flags(&self) -> MessageDataItem<'static> {
MessageDataItem::Flags(
- self.flags
+ self.in_idx
+ .flags
.iter()
.filter_map(|f| flags::from_str(f))
.collect(),
)
}
- fn rfc_822_size(&self) -> MessageDataItem<'static> {
- MessageDataItem::Rfc822Size(self.meta.rfc822_size as u32)
+ fn rfc_822_size(&self) -> Result<MessageDataItem<'static>> {
+ let sz = self.query_result.metadata().ok_or(anyhow!("mail metadata are required"))?.rfc822_size;
+ Ok(MessageDataItem::Rfc822Size(sz as u32))
}
- fn rfc_822_header(&self) -> MessageDataItem<'static> {
- MessageDataItem::Rfc822Header(NString(
- self.meta
- .headers
- .to_vec()
- .try_into()
- .ok()
- .map(IString::Literal),
- ))
+ fn rfc_822_header(&self) -> Result<MessageDataItem<'static>> {
+ let hdrs: NString = self.query_result.metadata().ok_or(anyhow!("mail metadata are required"))?.headers.to_vec().try_into()?;
+ Ok(MessageDataItem::Rfc822Header(hdrs))
}
fn rfc_822_text(&self) -> Result<MessageDataItem<'static>> {
- Ok(MessageDataItem::Rfc822Text(NString(
- self.content
- .as_full()?
- .raw_body
- .to_vec()
- .try_into()
- .ok()
- .map(IString::Literal),
- )))
+ let txt: NString = self.content.as_full()?.raw_body.to_vec().try_into()?;
+ Ok(MessageDataItem::Rfc822Text(txt))
}
fn rfc822(&self) -> Result<MessageDataItem<'static>> {
- Ok(MessageDataItem::Rfc822(NString(
- self.content
- .as_full()?
- .raw_part
- .to_vec()
- .try_into()
- .ok()
- .map(IString::Literal),
- )))
+ let full: NString = self.content.as_full()?.raw_part.to_vec().try_into()?;
+ Ok(MessageDataItem::Rfc822(full))
}
fn envelope(&self) -> MessageDataItem<'static> {
@@ -119,16 +105,16 @@ impl<'a> MailView<'a> {
/// peek does not implicitly set the \Seen flag
/// eg. BODY[HEADER.FIELDS (DATE FROM)]
/// eg. BODY[]<0.2048>
- fn body_ext<'b>(
+ fn body_ext(
&self,
- section: &Option<FetchSection<'b>>,
+ section: &Option<FetchSection<'static>>,
partial: &Option<(u32, NonZeroU32)>,
peek: &bool,
- ) -> Result<(MessageDataItem<'b>, SeenFlag)> {
+ ) -> Result<(MessageDataItem<'static>, SeenFlag)> {
// Manage Seen flag
let mut seen = SeenFlag::DoNothing;
let seen_flag = Flag::Seen.to_string();
- if !peek && !self.flags.iter().any(|x| *x == seen_flag) {
+ if !peek && !self.in_idx.flags.iter().any(|x| *x == seen_flag) {
// Add \Seen flag
//self.mailbox.add_flags(uuid, &[seen_flag]).await?;
seen = SeenFlag::MustAdd;
@@ -141,7 +127,7 @@ impl<'a> MailView<'a> {
mime_view::BodySection::Slice { body, origin_octet } => (body, Some(origin_octet)),
};
- let data = NString(text.to_vec().try_into().ok().map(IString::Literal));
+ let data: NString = text.to_vec().try_into()?;
return Ok((
MessageDataItem::BodyExt {
@@ -156,13 +142,13 @@ impl<'a> MailView<'a> {
fn internal_date(&self) -> Result<MessageDataItem<'static>> {
let dt = Utc
.fix()
- .timestamp_opt(i64::try_from(self.meta.internaldate / 1000)?, 0)
+ .timestamp_opt(i64::try_from(self.query_result.metadata().ok_or(anyhow!("mail metadata were not fetched"))?.internaldate / 1000)?, 0)
.earliest()
.ok_or(anyhow!("Unable to parse internal date"))?;
Ok(MessageDataItem::InternalDate(DateTime::unvalidated(dt)))
}
- pub fn filter<'b>(&self, ap: &AttributesProxy) -> Result<(Body<'static>, SeenFlag)> {
+ pub fn filter(&self, ap: &AttributesProxy) -> Result<(Body<'static>, SeenFlag)> {
let mut seen = SeenFlag::DoNothing;
let res_attrs = ap
.attrs
@@ -170,8 +156,8 @@ impl<'a> MailView<'a> {
.map(|attr| match attr {
MessageDataItemName::Uid => Ok(self.uid()),
MessageDataItemName::Flags => Ok(self.flags()),
- MessageDataItemName::Rfc822Size => Ok(self.rfc_822_size()),
- MessageDataItemName::Rfc822Header => Ok(self.rfc_822_header()),
+ MessageDataItemName::Rfc822Size => self.rfc_822_size(),
+ MessageDataItemName::Rfc822Header => self.rfc_822_header(),
MessageDataItemName::Rfc822Text => self.rfc_822_text(),
MessageDataItemName::Rfc822 => self.rfc822(),
MessageDataItemName::Envelope => Ok(self.envelope()),
@@ -192,7 +178,7 @@ impl<'a> MailView<'a> {
Ok((
Body::Data(Data::Fetch {
- seq: self.ids.i,
+ seq: self.in_idx.i,
items: res_attrs.try_into()?,
}),
seen,
@@ -208,19 +194,15 @@ pub enum SeenFlag {
// -------------------
pub enum FetchedMail<'a> {
- None,
+ IndexOnly,
Partial(imf::Imf<'a>),
Full(AnyPart<'a>),
}
impl<'a> FetchedMail<'a> {
pub fn new_from_message(msg: Message<'a>) -> Self {
- FetchedMail::Full(AnyPart::Msg(msg))
+ Self::Full(AnyPart::Msg(msg))
}
- /*fn new_from_header(hdr: imf::Imf<'a>) -> Self {
- FetchedMail::Partial(hdr)
- }*/
-
fn as_anypart(&self) -> Result<&AnyPart<'a>> {
match self {
FetchedMail::Full(x) => Ok(&x),