From 7db49875ea36d37b8ed3838e6affd5ead5eee7d4 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Mon, 24 Jul 2023 18:32:26 +0200 Subject: [PATCH] capture preamble and epilogue --- src/part/composite.rs | 27 ++++++++++++++++++++++++++- src/part/mod.rs | 20 +++++++++----------- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/part/composite.rs b/src/part/composite.rs index af4c485..eb38bcb 100644 --- a/src/part/composite.rs +++ b/src/part/composite.rs @@ -11,6 +11,14 @@ use crate::text::boundary::{boundary, Delimiter}; pub struct Multipart<'a> { pub interpreted: mime::Multipart<'a>, pub children: Vec>, + pub preamble: &'a [u8], + pub epilogue: &'a [u8], +} +impl<'a> Multipart<'a> { + pub fn with_epilogue(mut self, e: &'a [u8]) -> Self { + self.epilogue = e; + self + } } pub fn multipart<'a>( @@ -20,7 +28,7 @@ pub fn multipart<'a>( move |input| { let bound = m.0.boundary.as_bytes(); - let (mut input_loop, _) = part::part_raw(bound)(input)?; + let (mut input_loop, preamble) = part::part_raw(bound)(input)?; let mut mparts: Vec = vec![]; loop { let input = match boundary(bound)(input_loop) { @@ -30,6 +38,8 @@ pub fn multipart<'a>( Multipart { interpreted: m.clone(), children: mparts, + preamble, + epilogue: &[], }, )) } @@ -39,6 +49,8 @@ pub fn multipart<'a>( Multipart { interpreted: m.clone(), children: mparts, + preamble, + epilogue: &[], }, )) } @@ -70,7 +82,14 @@ pub struct Message<'a> { pub interpreted: mime::Message<'a>, pub imf: imf::Imf<'a>, pub child: Box>, + pub epilogue: &'a [u8], } +impl<'a> Message<'a> { + pub fn with_epilogue(mut self, e: &'a [u8]) -> Self { + self.epilogue = e; + self + } +} pub fn message<'a>( m: mime::Message<'a>, @@ -88,6 +107,7 @@ pub fn message<'a>( interpreted: m.clone(), imf, child: Box::new(part), + epilogue: &[], }, )) } @@ -134,6 +154,8 @@ This is the epilogue. It is also to be ignored. Ok((&b"\nThis is the epilogue. It is also to be ignored.\n"[..], Multipart { interpreted: base_mime, + preamble: &b"This is the preamble. It is to be ignored, though it\nis a handy place for composition agents to include an\nexplanatory note to non-MIME conformant readers.\n"[..], + epilogue: &b""[..], children: vec![ AnyPart::Txt(Text { interpreted: mime::Text( @@ -215,6 +237,7 @@ OoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoO
&[][..], Message { interpreted: base_mime, + epilogue: &b""[..], imf: imf::Imf { date: Some(FixedOffset::east_opt(2 * 3600) .unwrap() @@ -288,6 +311,8 @@ OoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoO
}, mime::Generic::default(), ), + preamble: &b"This is a multi-part message in MIME format.\n"[..], + epilogue: &b""[..], children: vec![ AnyPart::Txt(Text { interpreted: mime::Text( diff --git a/src/part/mod.rs b/src/part/mod.rs index d3db613..32d55f2 100644 --- a/src/part/mod.rs +++ b/src/part/mod.rs @@ -10,7 +10,7 @@ pub mod field; use nom::{ branch::alt, bytes::complete::is_not, - combinator::{map, not, recognize}, + combinator::{not, recognize}, multi::many0, sequence::pair, IResult, @@ -63,20 +63,18 @@ impl<'a> AnyPart<'a> { pub fn to_anypart<'a>(m: AnyMIME<'a>, rpart: &'a [u8]) -> AnyPart<'a> { match m { - AnyMIME::Mult(a) => map(multipart(a), AnyPart::Mult)(rpart) - .map(|v| v.1) + AnyMIME::Mult(a) => multipart(a)(rpart) + .map(|(rest, multi)| AnyPart::Mult(multi.with_epilogue(rest))) + .unwrap_or(AnyPart::Txt(Text { + interpreted: mime::Text::default(), + body: rpart, + })), + AnyMIME::Msg(a) => message(a)(rpart) + .map(|(rest, msg)| AnyPart::Msg(msg.with_epilogue(rest))) .unwrap_or(AnyPart::Txt(Text { interpreted: mime::Text::default(), body: rpart, })), - AnyMIME::Msg(a) => { - map(message(a), AnyPart::Msg)(rpart) - .map(|v| v.1) - .unwrap_or(AnyPart::Txt(Text { - interpreted: mime::Text::default(), - body: rpart, - })) - } AnyMIME::Txt(a) => AnyPart::Txt(Text { interpreted: a, body: rpart,