eml_codec/mime/
mod.rs

1/// Parsed and represent an email character set
2pub mod charset;
3
4/// MIME specific headers
5pub mod field;
6
7/// Transfer-Encoding representation
8pub mod mechanism;
9
10/// Content-Type representation
11pub mod r#type;
12
13use std::fmt;
14use std::marker::PhantomData;
15
16use crate::header;
17use crate::imf::identification::MessageID;
18use crate::mime::field::Content;
19use crate::mime::mechanism::Mechanism;
20use crate::mime::r#type::{AnyType, NaiveType};
21use crate::text::misc_token::Unstructured; //Multipart, Message, Text, Binary};
22
23#[derive(Debug, PartialEq, Clone)]
24pub struct MIME<'a, T> {
25    pub interpreted_type: T,
26    pub fields: NaiveMIME<'a>,
27}
28impl<'a> Default for MIME<'a, r#type::DeductibleText> {
29    fn default() -> Self {
30        Self {
31            interpreted_type: r#type::DeductibleText::default(),
32            fields: NaiveMIME::default(),
33        }
34    }
35}
36impl<'a> Default for MIME<'a, r#type::DeductibleMessage> {
37    fn default() -> Self {
38        Self {
39            interpreted_type: r#type::DeductibleMessage::default(),
40            fields: NaiveMIME::default(),
41        }
42    }
43}
44
45#[derive(Debug, PartialEq, Clone)]
46pub enum AnyMIME<'a> {
47    Mult(MIME<'a, r#type::Multipart>),
48    Msg(MIME<'a, r#type::DeductibleMessage>),
49    Txt(MIME<'a, r#type::DeductibleText>),
50    Bin(MIME<'a, r#type::Binary>),
51}
52impl<'a> AnyMIME<'a> {
53    pub fn fields(&self) -> &NaiveMIME<'a> {
54        match self {
55            Self::Mult(v) => &v.fields,
56            Self::Msg(v) => &v.fields,
57            Self::Txt(v) => &v.fields,
58            Self::Bin(v) => &v.fields,
59        }
60    }
61}
62
63impl<'a, T: WithDefaultType> From<AnyMIMEWithDefault<'a, T>> for AnyMIME<'a> {
64    fn from(a: AnyMIMEWithDefault<'a, T>) -> Self {
65        a.0
66    }
67}
68
69#[derive(PartialEq, Default, Clone)]
70pub struct NaiveMIME<'a> {
71    pub ctype: Option<NaiveType<'a>>,
72    pub transfer_encoding: Mechanism<'a>,
73    pub id: Option<MessageID<'a>>,
74    pub description: Option<Unstructured<'a>>,
75    pub kv: Vec<header::Field<'a>>,
76    pub raw: &'a [u8],
77}
78impl<'a> fmt::Debug for NaiveMIME<'a> {
79    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
80        fmt.debug_struct("NaiveMime")
81            .field("ctype", &self.ctype)
82            .field("transfer_encoding", &self.transfer_encoding)
83            .field("id", &self.id)
84            .field("description", &self.description)
85            .field("kv", &self.kv)
86            .field("raw", &String::from_utf8_lossy(self.raw))
87            .finish()
88    }
89}
90
91impl<'a> FromIterator<Content<'a>> for NaiveMIME<'a> {
92    fn from_iter<I: IntoIterator<Item = Content<'a>>>(it: I) -> Self {
93        it.into_iter()
94            .fold(NaiveMIME::default(), |mut section, field| {
95                match field {
96                    Content::Type(v) => section.ctype = Some(v),
97                    Content::TransferEncoding(v) => section.transfer_encoding = v,
98                    Content::ID(v) => section.id = Some(v),
99                    Content::Description(v) => section.description = Some(v),
100                };
101                section
102            })
103    }
104}
105
106impl<'a> NaiveMIME<'a> {
107    pub fn with_kv(mut self, fields: Vec<header::Field<'a>>) -> Self {
108        self.kv = fields;
109        self
110    }
111    pub fn with_raw(mut self, raw: &'a [u8]) -> Self {
112        self.raw = raw;
113        self
114    }
115    pub fn to_interpreted<T: WithDefaultType>(self) -> AnyMIME<'a> {
116        self.ctype
117            .as_ref()
118            .map(|c| c.to_type())
119            .unwrap_or(T::default_type())
120            .to_mime(self)
121            .into()
122    }
123}
124
125pub trait WithDefaultType {
126    fn default_type() -> AnyType;
127}
128
129pub struct WithGenericDefault {}
130impl WithDefaultType for WithGenericDefault {
131    fn default_type() -> AnyType {
132        AnyType::Text(r#type::DeductibleText::default())
133    }
134}
135pub struct WithDigestDefault {}
136impl WithDefaultType for WithDigestDefault {
137    fn default_type() -> AnyType {
138        AnyType::Message(r#type::DeductibleMessage::default())
139    }
140}
141
142#[derive(Debug, PartialEq)]
143pub struct AnyMIMEWithDefault<'a, T: WithDefaultType>(pub AnyMIME<'a>, PhantomData<T>);
144
145impl<'a, T: WithDefaultType> Default for AnyMIMEWithDefault<'a, T> {
146    fn default() -> Self {
147        Self(T::default_type().to_mime(NaiveMIME::default()), PhantomData)
148    }
149}