use super::{Flag, Seq, Uid};
use chrono::{DateTime, FixedOffset};
use imap_proto::types::{AttributeValue, Envelope, MessageSection, SectionPath};
const DATE_TIME_FORMAT: &str = "%d-%b-%Y %H:%M:%S %z";
#[derive(Debug, Eq, PartialEq)]
pub struct Fetch {
pub message: Seq,
pub uid: Option<Uid>,
pub size: Option<u32>,
pub(crate) fetch: Vec<AttributeValue<'static>>,
pub(crate) flags: Vec<Flag<'static>>,
}
impl Fetch {
pub fn flags(&self) -> &[Flag] {
&self.flags[..]
}
pub fn header(&self) -> Option<&[u8]> {
self.fetch
.iter()
.filter_map(|av| match av {
AttributeValue::BodySection {
section: Some(SectionPath::Full(MessageSection::Header)),
data: Some(hdr),
..
}
| AttributeValue::Rfc822Header(Some(hdr)) => Some(*hdr),
_ => None,
})
.next()
}
pub fn body(&self) -> Option<&[u8]> {
self.fetch
.iter()
.filter_map(|av| match av {
AttributeValue::BodySection {
section: None,
data: Some(body),
..
}
| AttributeValue::Rfc822(Some(body)) => Some(*body),
_ => None,
})
.next()
}
pub fn text(&self) -> Option<&[u8]> {
self.fetch
.iter()
.filter_map(|av| match av {
AttributeValue::BodySection {
section: Some(SectionPath::Full(MessageSection::Text)),
data: Some(body),
..
}
| AttributeValue::Rfc822Text(Some(body)) => Some(*body),
_ => None,
})
.next()
}
pub fn envelope(&self) -> Option<&Envelope> {
self.fetch
.iter()
.filter_map(|av| match av {
AttributeValue::Envelope(env) => Some(&**env),
_ => None,
})
.next()
}
pub fn section(&self, path: &SectionPath) -> Option<&[u8]> {
self.fetch
.iter()
.filter_map(|av| match av {
AttributeValue::BodySection {
section: Some(sp),
data: Some(data),
..
} if sp == path => Some(*data),
_ => None,
})
.next()
}
pub fn internal_date(&self) -> Option<DateTime<FixedOffset>> {
self.fetch
.iter()
.filter_map(|av| match av {
AttributeValue::InternalDate(date_time) => Some(*date_time),
_ => None,
})
.next()
.and_then(
|date_time| match DateTime::parse_from_str(date_time, DATE_TIME_FORMAT) {
Ok(date_time) => Some(date_time),
Err(_) => None,
},
)
}
}