diff --git a/src/imf/field.rs b/src/imf/field.rs index d16078b..82c7df6 100644 --- a/src/imf/field.rs +++ b/src/imf/field.rs @@ -11,7 +11,7 @@ use crate::imf::address::{address_list, mailbox_list, nullable_address_list, Add use crate::imf::datetime::section as date; use crate::imf::identification::{msg_id, msg_list, MessageID, MessageIDList}; use crate::imf::mailbox::{mailbox, AddrSpec, MailboxList, MailboxRef}; -use crate::imf::message::Message; +use crate::imf::Imf; use crate::imf::mime::{version, Version}; use crate::imf::trace::{received_log, return_path, ReceivedLog}; use crate::text::misc_token::{phrase_list, unstructured, PhraseList, Unstructured}; @@ -53,8 +53,8 @@ pub enum Field<'a> { #[derive(Debug, PartialEq)] pub struct FieldList<'a>(pub Vec>); impl<'a> FieldList<'a> { - pub fn message(self) -> Message<'a> { - Message::from_iter(self.0) + pub fn imf(self) -> Imf<'a> { + Imf::from_iter(self.0) } } @@ -88,8 +88,8 @@ pub fn field(input: &[u8]) -> IResult<&[u8], Field> { )(input) } -pub fn message(input: &[u8]) -> IResult<&[u8], Message> { - map(header(field), |v| FieldList(v.known()).message())(input) +pub fn imf(input: &[u8]) -> IResult<&[u8], Imf> { + map(header(field), |v| FieldList(v.known()).imf())(input) } #[cfg(test)] @@ -111,10 +111,10 @@ This is the plain text body of the message. Note the blank line between the header information and the body of the message."; assert_eq!( - message(fullmail), + imf(fullmail), Ok(( &b"This is the plain text body of the message. Note the blank line\nbetween the header information and the body of the message."[..], - Message { + Imf { date: Some(FixedOffset::east_opt(2 * 3600).unwrap().with_ymd_and_hms(2023, 3, 7, 8, 0, 0).unwrap()), from: vec![MailboxRef { name: None, @@ -137,7 +137,7 @@ between the header information and the body of the message."; UnstrToken::Plain(&b"formatted"[..]), UnstrToken::Plain(&b"message"[..]), ])), - ..Message::default() + ..Imf::default() } )), ) diff --git a/src/imf/message.rs b/src/imf/message.rs deleted file mode 100644 index c985149..0000000 --- a/src/imf/message.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::imf::address::AddressRef; -use crate::imf::field::Field; -use crate::imf::identification::MessageID; -use crate::imf::mailbox::{AddrSpec, MailboxRef}; -use crate::imf::mime::Version; -use crate::imf::trace::ReceivedLog; -use crate::text::misc_token::{PhraseList, Unstructured}; -use chrono::{DateTime, FixedOffset}; - -#[derive(Debug, PartialEq, Default)] -pub struct Message<'a> { - // 3.6.1. The Origination Date Field - pub date: Option>, - - // 3.6.2. Originator Fields - pub from: Vec>, - pub sender: Option>, - pub reply_to: Vec>, - - // 3.6.3. Destination Address Fields - pub to: Vec>, - pub cc: Vec>, - pub bcc: Vec>, - - // 3.6.4. Identification Fields - pub msg_id: Option>, - pub in_reply_to: Vec>, - pub references: Vec>, - - // 3.6.5. Informational Fields - pub subject: Option>, - pub comments: Vec>, - pub keywords: Vec>, - - // 3.6.6 Not implemented - // 3.6.7 Trace Fields - pub return_path: Vec>, - pub received: Vec>, - - // MIME - pub mime_version: Option, -} - -//@FIXME min and max limits are not enforced, -// it may result in missing data or silently overriden data. -impl<'a> FromIterator> for Message<'a> { - fn from_iter>>(iter: I) -> Self { - iter.into_iter() - .fold(Message::default(), |mut section, field| { - match field { - Field::Date(v) => section.date = v, - Field::From(v) => section.from.extend(v), - Field::Sender(v) => section.sender = Some(v), - Field::ReplyTo(v) => section.reply_to.extend(v), - Field::To(v) => section.to.extend(v), - Field::Cc(v) => section.cc.extend(v), - Field::Bcc(v) => section.bcc.extend(v), - Field::MessageID(v) => section.msg_id = Some(v), - Field::InReplyTo(v) => section.in_reply_to.extend(v), - Field::References(v) => section.references.extend(v), - Field::Subject(v) => section.subject = Some(v), - Field::Comments(v) => section.comments.push(v), - Field::Keywords(v) => section.keywords.push(v), - Field::ReturnPath(v) => v.map(|x| section.return_path.push(x)).unwrap_or(()), - Field::Received(v) => section.received.push(v), - Field::MIMEVersion(v) => section.mime_version = Some(v), - }; - section - }) - } -} diff --git a/src/imf/mod.rs b/src/imf/mod.rs index c4426f5..d4d044b 100644 --- a/src/imf/mod.rs +++ b/src/imf/mod.rs @@ -3,6 +3,77 @@ pub mod datetime; pub mod field; pub mod identification; pub mod mailbox; -pub mod message; pub mod mime; pub mod trace; + +use crate::imf::address::AddressRef; +use crate::imf::field::Field; +use crate::imf::identification::MessageID; +use crate::imf::mailbox::{AddrSpec, MailboxRef}; +use crate::imf::mime::Version; +use crate::imf::trace::ReceivedLog; +use crate::text::misc_token::{PhraseList, Unstructured}; +use chrono::{DateTime, FixedOffset}; + +#[derive(Debug, PartialEq, Default)] +pub struct Imf<'a> { + // 3.6.1. The Origination Date Field + pub date: Option>, + + // 3.6.2. Originator Fields + pub from: Vec>, + pub sender: Option>, + pub reply_to: Vec>, + + // 3.6.3. Destination Address Fields + pub to: Vec>, + pub cc: Vec>, + pub bcc: Vec>, + + // 3.6.4. Identification Fields + pub msg_id: Option>, + pub in_reply_to: Vec>, + pub references: Vec>, + + // 3.6.5. Informational Fields + pub subject: Option>, + pub comments: Vec>, + pub keywords: Vec>, + + // 3.6.6 Not implemented + // 3.6.7 Trace Fields + pub return_path: Vec>, + pub received: Vec>, + + // MIME + pub mime_version: Option, +} + +//@FIXME min and max limits are not enforced, +// it may result in missing data or silently overriden data. +impl<'a> FromIterator> for Imf<'a> { + fn from_iter>>(iter: I) -> Self { + iter.into_iter() + .fold(Imf::default(), |mut section, field| { + match field { + Field::Date(v) => section.date = v, + Field::From(v) => section.from.extend(v), + Field::Sender(v) => section.sender = Some(v), + Field::ReplyTo(v) => section.reply_to.extend(v), + Field::To(v) => section.to.extend(v), + Field::Cc(v) => section.cc.extend(v), + Field::Bcc(v) => section.bcc.extend(v), + Field::MessageID(v) => section.msg_id = Some(v), + Field::InReplyTo(v) => section.in_reply_to.extend(v), + Field::References(v) => section.references.extend(v), + Field::Subject(v) => section.subject = Some(v), + Field::Comments(v) => section.comments.push(v), + Field::Keywords(v) => section.keywords.push(v), + Field::ReturnPath(v) => v.map(|x| section.return_path.push(x)).unwrap_or(()), + Field::Received(v) => section.received.push(v), + Field::MIMEVersion(v) => section.mime_version = Some(v), + }; + section + }) + } +} diff --git a/src/lib.rs b/src/lib.rs index 41b23bb..9825acb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,8 +11,8 @@ pub fn email(input: &[u8]) -> Result { .map_err(error::EMLError::ParseError) } -pub fn imf(input: &[u8]) -> Result { - imf::field::message(input) +pub fn imf(input: &[u8]) -> Result { + imf::field::imf(input) .map(|(_, v)| v) .map_err(error::EMLError::ParseError) } diff --git a/src/part/part.rs b/src/part/part.rs index 802fd2b..082e793 100644 --- a/src/part/part.rs +++ b/src/part/part.rs @@ -22,7 +22,7 @@ pub struct Multipart<'a>(pub mime::mime::Multipart<'a>, pub Vec>); #[derive(Debug, PartialEq)] pub struct Message<'a>( pub mime::mime::Message<'a>, - pub imf::message::Message<'a>, + pub imf::Imf<'a>, pub Box>, ); @@ -90,7 +90,7 @@ impl<'a> MixedField<'a> { } } impl<'a> CompFieldList<'a, MixedField<'a>> { - pub fn sections(self) -> (mime::mime::AnyMIME<'a>, imf::message::Message<'a>) { + pub fn sections(self) -> (mime::mime::AnyMIME<'a>, imf::Imf<'a>) { let k = self.known(); let (v1, v2): (Vec, Vec) = k.into_iter().partition(|v| v.mime().is_some()); @@ -101,7 +101,7 @@ impl<'a> CompFieldList<'a, MixedField<'a>> { let imf = v2 .into_iter() .filter_map(|v| v.to_imf()) - .collect::(); + .collect::(); (mime, imf) } } @@ -338,7 +338,7 @@ OoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoO
&[][..], Message ( base_mime, - imf::message::Message { + imf::Imf { date: Some(FixedOffset::east_opt(2 * 3600) .unwrap() .with_ymd_and_hms(2023, 07, 8, 7, 14, 29) @@ -401,7 +401,7 @@ OoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoO
right: &b"www.grrrndzero.org"[..], }), mime_version: Some(imf::mime::Version { major: 1, minor: 0}), - ..imf::message::Message::default() + ..imf::Imf::default() }, Box::new(AnyPart::Mult(Multipart ( mime::mime::Multipart(