This commit is contained in:
Quentin 2023-07-19 17:40:00 +02:00
parent 54f6ce82a3
commit b998aec37d
Signed by: quentin
GPG key ID: E9602264D639FF68
3 changed files with 59 additions and 32 deletions

View file

@ -63,9 +63,8 @@ pub fn mailbox(input: &[u8]) -> IResult<&[u8], MailboxRef> {
/// ``` /// ```
fn name_addr(input: &[u8]) -> IResult<&[u8], MailboxRef> { fn name_addr(input: &[u8]) -> IResult<&[u8], MailboxRef> {
let (input, name) = opt(phrase)(input)?; let (input, name) = opt(phrase)(input)?;
let (input, mut mbox) = angle_addr(input)?; let (input, addrspec) = angle_addr(input)?;
mbox.name = name; Ok((input, MailboxRef { name, addrspec }))
Ok((input, mbox))
} }
/// Enclosed addr-spec with < and > /// Enclosed addr-spec with < and >
@ -74,10 +73,10 @@ fn name_addr(input: &[u8]) -> IResult<&[u8], MailboxRef> {
/// angle-addr = [CFWS] "<" addr-spec ">" [CFWS] / /// angle-addr = [CFWS] "<" addr-spec ">" [CFWS] /
/// obs-angle-addr /// obs-angle-addr
/// ``` /// ```
pub fn angle_addr(input: &[u8]) -> IResult<&[u8], MailboxRef> { pub fn angle_addr(input: &[u8]) -> IResult<&[u8], AddrSpec> {
delimited( delimited(
tuple((opt(cfws), tag(&[ascii::LT]), opt(obs_route))), tuple((opt(cfws), tag(&[ascii::LT]), opt(obs_route))),
into(addr_spec), addr_spec,
pair(tag(&[ascii::GT]), opt(cfws)), pair(tag(&[ascii::GT]), opt(cfws)),
)(input) )(input)
} }

View file

@ -1,3 +1,4 @@
pub mod mailbox; pub mod mailbox;
pub mod address; pub mod address;
pub mod datetime; pub mod datetime;
pub mod trace;

View file

@ -1,17 +1,30 @@
use crate::error::IMFError;
use crate::fragments::{datetime, lazy, mailbox, misc_token, model, whitespace};
use nom::{ use nom::{
branch::alt, branch::alt,
bytes::complete::tag, bytes::complete::{is_a, tag},
combinator::{map, opt, recognize}, combinator::{map, opt, not},
multi::many0, multi::many0,
sequence::tuple, sequence::{tuple, terminated},
IResult, IResult,
}; };
use chrono::{DateTime, FixedOffset};
use crate::rfc5322::{datetime, mailbox};
use crate::text::{ascii, whitespace, misc_token };
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct ReceivedLog<'a>(pub &'a str); pub enum ReceivedLogToken<'a> {
Addr(mailbox::AddrSpec<'a>),
Domain(mailbox::Domain<'a>),
Word(misc_token::Word<'a>)
}
#[derive(Debug, PartialEq)]
pub struct ReceivedLog<'a> {
pub log: Vec<ReceivedLogToken<'a>>,
pub date: Option<DateTime<FixedOffset>>,
}
/*
impl<'a> TryFrom<&'a lazy::ReceivedLog<'a>> for ReceivedLog<'a> { impl<'a> TryFrom<&'a lazy::ReceivedLog<'a>> for ReceivedLog<'a> {
type Error = IMFError<'a>; type Error = IMFError<'a>;
@ -20,47 +33,48 @@ impl<'a> TryFrom<&'a lazy::ReceivedLog<'a>> for ReceivedLog<'a> {
.map_err(|e| IMFError::ReceivedLog(e)) .map_err(|e| IMFError::ReceivedLog(e))
.map(|(_, v)| ReceivedLog(v)) .map(|(_, v)| ReceivedLog(v))
} }
} }*/
pub fn received_body(input: &str) -> IResult<&str, &str> { pub fn received_body(input: &[u8]) -> IResult<&[u8], ReceivedLog> {
map( map(
tuple(( tuple((
recognize(many0(received_tokens)), many0(received_tokens),
tag(";"), tag(";"),
datetime::section, datetime::section,
)), )),
|(tokens, _, _)| tokens, |(tokens, _, dt)| ReceivedLog { log: tokens, date: dt } ,
)(input) )(input)
} }
pub fn return_path_body(input: &str) -> IResult<&str, Option<model::MailboxRef>> { pub fn return_path_body(input: &[u8]) -> IResult<&[u8], Option<mailbox::AddrSpec>> {
alt((map(mailbox::angle_addr, |a| Some(a)), empty_path))(input) alt((map(mailbox::angle_addr, |a| Some(a)), empty_path))(input)
} }
fn empty_path(input: &str) -> IResult<&str, Option<model::MailboxRef>> { fn empty_path(input: &[u8]) -> IResult<&[u8], Option<mailbox::AddrSpec>> {
let (input, _) = tuple(( let (input, _) = tuple((
opt(whitespace::cfws), opt(whitespace::cfws),
tag("<"), tag(&[ascii::LT]),
opt(whitespace::cfws), opt(whitespace::cfws),
tag(">"), tag(&[ascii::GT]),
opt(whitespace::cfws), opt(whitespace::cfws),
))(input)?; ))(input)?;
Ok((input, None)) Ok((input, None))
} }
// @FIXME use obs_domain as it is a superset of domain fn received_tokens(input: &[u8]) -> IResult<&[u8], ReceivedLogToken> {
fn received_tokens(input: &str) -> IResult<&str, &str> {
alt(( alt((
recognize(mailbox::angle_addr), terminated(map(misc_token::word, |x| ReceivedLogToken::Word(x)), not(is_a([ascii::PERIOD, ascii::AT]))),
recognize(mailbox::addr_spec), map(mailbox::angle_addr, |x| ReceivedLogToken::Addr(x)),
recognize(mailbox::obs_domain), map(mailbox::addr_spec, |x| ReceivedLogToken::Addr(x)),
recognize(misc_token::word), map(mailbox::obs_domain, |x| ReceivedLogToken::Domain(x)),
))(input) ))(input)
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use chrono::TimeZone;
use crate::rfc5322::trace::misc_token::Word;
#[test] #[test]
fn test_received_body() { fn test_received_body() {
@ -68,17 +82,30 @@ mod tests {
by server with LMTP by server with LMTP
id xxxxxxxxx id xxxxxxxxx
(envelope-from <gitlab@example.com>) (envelope-from <gitlab@example.com>)
for <me@example.com>; Tue, 13 Jun 2023 19:01:08 +0000"#; for <me@example.com>; Tue, 13 Jun 2023 19:01:08 +0000"#.as_bytes();
assert_eq!( assert_eq!(
received_body(hdrs), received_body(hdrs),
Ok(( Ok((
"", &b""[..],
r#"from smtp.example.com ([10.83.2.2]) ReceivedLog {
by server with LMTP date: Some(FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(2023, 06, 13, 19, 1, 8).unwrap()),
id xxxxxxxxx log: vec![
(envelope-from <gitlab@example.com>) ReceivedLogToken::Word(Word::Atom(&b"from"[..])),
for <me@example.com>"# ReceivedLogToken::Domain(mailbox::Domain::Atoms(vec![&b"smtp"[..], &b"example"[..], &b"com"[..]])),
ReceivedLogToken::Word(Word::Atom(&b"by"[..])),
ReceivedLogToken::Word(Word::Atom(&b"server"[..])),
ReceivedLogToken::Word(Word::Atom(&b"with"[..])),
ReceivedLogToken::Word(Word::Atom(&b"LMTP"[..])),
ReceivedLogToken::Word(Word::Atom(&b"id"[..])),
ReceivedLogToken::Word(Word::Atom(&b"xxxxxxxxx"[..])),
ReceivedLogToken::Word(Word::Atom(&b"for"[..])),
ReceivedLogToken::Addr(mailbox::AddrSpec {
local_part: mailbox::LocalPart(vec![mailbox::LocalPartToken::Word(Word::Atom(&b"me"[..]))]),
domain: mailbox::Domain::Atoms(vec![&b"example"[..], &b"com"[..]]),
})
],
}
)) ))
); );
} }