message structure msg
This commit is contained in:
parent
e25576e363
commit
0e7595d65a
1 changed files with 140 additions and 16 deletions
|
@ -5,15 +5,18 @@ use std::collections::HashSet;
|
||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{anyhow, bail, Result};
|
||||||
|
|
||||||
use imap_codec::imap_types::body::{BasicFields, Body as FetchBody, BodyStructure, SpecificFields};
|
use imap_codec::imap_types::body::{BasicFields, Body as FetchBody, BodyStructure, SpecificFields};
|
||||||
use imap_codec::imap_types::core::{AString, IString, NonEmptyVec};
|
use imap_codec::imap_types::core::{AString, IString, NString, NonEmptyVec};
|
||||||
use imap_codec::imap_types::fetch::{
|
use imap_codec::imap_types::fetch::{
|
||||||
Section as FetchSection, Part as FetchPart
|
Section as FetchSection, Part as FetchPart
|
||||||
};
|
};
|
||||||
|
|
||||||
use eml_codec::{
|
use eml_codec::{
|
||||||
header, part::AnyPart, part::composite, part::discrete,
|
header, mime,
|
||||||
|
part::AnyPart, part::composite, part::discrete,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::imap::imf_view::message_envelope;
|
||||||
|
|
||||||
|
|
||||||
pub enum BodySection<'a> {
|
pub enum BodySection<'a> {
|
||||||
Full(Cow<'a, [u8]>),
|
Full(Cow<'a, [u8]>),
|
||||||
|
@ -80,14 +83,13 @@ pub fn body_ext<'a>(
|
||||||
/// b OK Fetch completed (0.001 + 0.000 secs).
|
/// b OK Fetch completed (0.001 + 0.000 secs).
|
||||||
/// ```
|
/// ```
|
||||||
pub fn bodystructure(part: &AnyPart) -> Result<BodyStructure<'static>> {
|
pub fn bodystructure(part: &AnyPart) -> Result<BodyStructure<'static>> {
|
||||||
unimplemented!();
|
NodeMime(part).structure()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// NodeMime
|
/// NodeMime
|
||||||
///
|
///
|
||||||
|
/// Used for recursive logic on MIME.
|
||||||
|
/// See SelectedMime for inspection.
|
||||||
|
|
||||||
struct NodeMime<'a>(&'a AnyPart<'a>);
|
struct NodeMime<'a>(&'a AnyPart<'a>);
|
||||||
impl<'a> NodeMime<'a> {
|
impl<'a> NodeMime<'a> {
|
||||||
/// A MIME object is a tree of elements.
|
/// A MIME object is a tree of elements.
|
||||||
|
@ -119,6 +121,15 @@ impl<'a> NodeMime<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn structure(&self) -> Result<BodyStructure<'static>> {
|
||||||
|
match self.0 {
|
||||||
|
AnyPart::Txt(x) => NodeTxt(self, x).structure(),
|
||||||
|
AnyPart::Bin(x) => NodeBin(self, x).structure(),
|
||||||
|
AnyPart::Mult(x) => NodeMult(self, x).structure(),
|
||||||
|
AnyPart::Msg(x) => NodeMsg(self, x).structure(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------
|
//----------------------------------------------------------
|
||||||
|
@ -150,6 +161,9 @@ impl<'a> SubsettedSection<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used for current MIME inspection
|
||||||
|
///
|
||||||
|
/// See NodeMime for recursive logic
|
||||||
struct SelectedMime<'a>(&'a AnyPart<'a>);
|
struct SelectedMime<'a>(&'a AnyPart<'a>);
|
||||||
impl<'a> SelectedMime<'a> {
|
impl<'a> SelectedMime<'a> {
|
||||||
/// The subsetted fetch section basically tells us the
|
/// The subsetted fetch section basically tells us the
|
||||||
|
@ -253,18 +267,110 @@ impl<'a> SelectedMime<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------
|
// ------------
|
||||||
|
|
||||||
/// Returns the structure of the message
|
/// Basic field of a MIME part that is
|
||||||
fn structure(&self) -> Result<BodyStructure<'static>> {
|
/// common to all parts
|
||||||
unimplemented!();
|
fn basic_fields(&self) -> Result<BasicFields<'static>> {
|
||||||
}
|
let sz = match self.0 {
|
||||||
|
AnyPart::Txt(x) => x.body.len(),
|
||||||
|
AnyPart::Bin(x) => x.body.len(),
|
||||||
|
AnyPart::Msg(x) => x.raw_part.len(),
|
||||||
|
AnyPart::Mult(x) => 0
|
||||||
|
};
|
||||||
|
let m = self.0.mime();
|
||||||
|
let parameter_list = m
|
||||||
|
.ctype
|
||||||
|
.as_ref()
|
||||||
|
.map(|x| {
|
||||||
|
x.params
|
||||||
|
.iter()
|
||||||
|
.map(|p| {
|
||||||
|
(
|
||||||
|
IString::try_from(String::from_utf8_lossy(p.name).to_string()),
|
||||||
|
IString::try_from(p.value.to_string()),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.filter(|(k, v)| k.is_ok() && v.is_ok())
|
||||||
|
.map(|(k, v)| (k.unwrap(), v.unwrap()))
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.unwrap_or(vec![]);
|
||||||
|
|
||||||
|
Ok(BasicFields {
|
||||||
|
parameter_list,
|
||||||
|
id: NString(
|
||||||
|
m.id.as_ref()
|
||||||
|
.and_then(|ci| IString::try_from(ci.to_string()).ok()),
|
||||||
|
),
|
||||||
|
description: NString(
|
||||||
|
m.description
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|cd| IString::try_from(cd.to_string()).ok()),
|
||||||
|
),
|
||||||
|
content_transfer_encoding: match m.transfer_encoding {
|
||||||
|
mime::mechanism::Mechanism::_8Bit => unchecked_istring("8bit"),
|
||||||
|
mime::mechanism::Mechanism::Binary => unchecked_istring("binary"),
|
||||||
|
mime::mechanism::Mechanism::QuotedPrintable => unchecked_istring("quoted-printable"),
|
||||||
|
mime::mechanism::Mechanism::Base64 => unchecked_istring("base64"),
|
||||||
|
_ => unchecked_istring("7bit"),
|
||||||
|
},
|
||||||
|
// @FIXME we can't compute the size of the message currently...
|
||||||
|
size: u32::try_from(sz)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
struct SelectedMsg<'a>(&'a SelectedMime<'a>, &'a composite::Message<'a>);
|
struct NodeMsg<'a>(&'a NodeMime<'a>, &'a composite::Message<'a>);
|
||||||
struct SelectedMult<'a>(&'a SelectedMime<'a>, &'a composite::Multipart<'a>);
|
impl<'a> NodeMsg<'a> {
|
||||||
struct SelectedTxt<'a>(&'a SelectedMime<'a>, &'a discrete::Text<'a>);
|
fn structure(&self) -> Result<BodyStructure<'static>> {
|
||||||
struct SelectedBin<'a>(&'a SelectedMime<'a>, &'a discrete::Binary<'a>);
|
let basic = SelectedMime(self.0.0).basic_fields()?;
|
||||||
|
|
||||||
|
Ok(BodyStructure::Single {
|
||||||
|
body: FetchBody {
|
||||||
|
basic,
|
||||||
|
specific: SpecificFields::Message {
|
||||||
|
envelope: Box::new(message_envelope(&self.1.imf)),
|
||||||
|
body_structure: Box::new(NodeMime(&self.1.child).structure()?),
|
||||||
|
number_of_lines: nol(self.1.raw_part),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extension_data: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct NodeMult<'a>(&'a NodeMime<'a>, &'a composite::Multipart<'a>);
|
||||||
|
impl<'a> NodeMult<'a> {
|
||||||
|
fn structure(&self) -> Result<BodyStructure<'static>> {
|
||||||
|
let itype = &self.1.mime.interpreted_type;
|
||||||
|
let subtype = IString::try_from(itype.subtype.to_string())
|
||||||
|
.unwrap_or(unchecked_istring("alternative"));
|
||||||
|
|
||||||
|
let inner_bodies = self.1
|
||||||
|
.children
|
||||||
|
.iter()
|
||||||
|
.filter_map(|inner| NodeMime(&inner).structure().ok())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
NonEmptyVec::validate(&inner_bodies)?;
|
||||||
|
let bodies = NonEmptyVec::unvalidated(inner_bodies);
|
||||||
|
|
||||||
|
Ok(BodyStructure::Multi {
|
||||||
|
bodies,
|
||||||
|
subtype,
|
||||||
|
extension_data: None,
|
||||||
|
/*Some(MultipartExtensionData {
|
||||||
|
parameter_list: vec![],
|
||||||
|
disposition: None,
|
||||||
|
language: None,
|
||||||
|
location: None,
|
||||||
|
extension: vec![],
|
||||||
|
})*/
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct NodeTxt<'a>(&'a NodeMime<'a>, &'a discrete::Text<'a>);
|
||||||
|
struct NodeBin<'a>(&'a NodeMime<'a>, &'a discrete::Binary<'a>);
|
||||||
|
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
|
|
||||||
|
@ -329,3 +435,21 @@ impl<'a> ExtractedFull<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ---- LEGACY
|
||||||
|
|
||||||
|
/// s is set to static to ensure that only compile time values
|
||||||
|
/// checked by developpers are passed.
|
||||||
|
fn unchecked_istring(s: &'static str) -> IString {
|
||||||
|
IString::try_from(s).expect("this value is expected to be a valid imap-codec::IString")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number Of Lines
|
||||||
|
fn nol(input: &[u8]) -> u32 {
|
||||||
|
input
|
||||||
|
.iter()
|
||||||
|
.filter(|x| **x == b'\n')
|
||||||
|
.count()
|
||||||
|
.try_into()
|
||||||
|
.unwrap_or(0)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue