eml-codec/src/rfc5322/trace.rs

113 lines
3.7 KiB
Rust
Raw Normal View History

2023-06-13 17:47:57 +02:00
use nom::{
2023-06-13 22:50:29 +02:00
branch::alt,
2023-07-19 17:40:00 +02:00
bytes::complete::{is_a, tag},
combinator::{map, opt, not},
2023-06-16 09:58:07 +02:00
multi::many0,
2023-07-19 17:40:00 +02:00
sequence::{tuple, terminated},
2023-06-22 15:08:50 +02:00
IResult,
2023-06-13 19:35:41 +02:00
};
2023-07-19 17:40:00 +02:00
use chrono::{DateTime, FixedOffset};
use crate::rfc5322::{datetime, mailbox};
use crate::text::{ascii, whitespace, misc_token };
2023-06-20 17:03:18 +02:00
#[derive(Debug, PartialEq)]
2023-07-19 17:40:00 +02:00
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>>,
}
2023-06-20 17:03:18 +02:00
2023-07-19 17:40:00 +02:00
/*
2023-06-22 10:48:07 +02:00
impl<'a> TryFrom<&'a lazy::ReceivedLog<'a>> for ReceivedLog<'a> {
2023-06-20 17:03:18 +02:00
type Error = IMFError<'a>;
2023-06-22 10:48:07 +02:00
fn try_from(input: &'a lazy::ReceivedLog<'a>) -> Result<Self, Self::Error> {
2023-06-20 17:03:18 +02:00
received_body(input.0)
.map_err(|e| IMFError::ReceivedLog(e))
.map(|(_, v)| ReceivedLog(v))
}
2023-07-19 17:40:00 +02:00
}*/
2023-06-16 09:58:07 +02:00
2023-07-19 22:27:59 +02:00
pub fn received_log(input: &[u8]) -> IResult<&[u8], ReceivedLog> {
2023-06-16 09:58:07 +02:00
map(
tuple((
2023-07-19 17:40:00 +02:00
many0(received_tokens),
2023-06-16 09:58:07 +02:00
tag(";"),
datetime::section,
)),
2023-07-19 17:40:00 +02:00
|(tokens, _, dt)| ReceivedLog { log: tokens, date: dt } ,
2023-06-13 22:50:29 +02:00
)(input)
}
2023-07-19 22:27:59 +02:00
pub fn return_path(input: &[u8]) -> IResult<&[u8], Option<mailbox::AddrSpec>> {
2023-06-22 15:08:50 +02:00
alt((map(mailbox::angle_addr, |a| Some(a)), empty_path))(input)
2023-06-13 22:50:29 +02:00
}
2023-07-19 17:40:00 +02:00
fn empty_path(input: &[u8]) -> IResult<&[u8], Option<mailbox::AddrSpec>> {
2023-06-13 22:50:29 +02:00
let (input, _) = tuple((
opt(whitespace::cfws),
2023-07-19 17:40:00 +02:00
tag(&[ascii::LT]),
2023-06-13 22:50:29 +02:00
opt(whitespace::cfws),
2023-07-19 17:40:00 +02:00
tag(&[ascii::GT]),
2023-06-13 22:50:29 +02:00
opt(whitespace::cfws),
))(input)?;
Ok((input, None))
}
2023-07-19 17:40:00 +02:00
fn received_tokens(input: &[u8]) -> IResult<&[u8], ReceivedLogToken> {
2023-06-13 22:50:29 +02:00
alt((
2023-07-19 17:40:00 +02:00
terminated(map(misc_token::word, |x| ReceivedLogToken::Word(x)), not(is_a([ascii::PERIOD, ascii::AT]))),
map(mailbox::angle_addr, |x| ReceivedLogToken::Addr(x)),
map(mailbox::addr_spec, |x| ReceivedLogToken::Addr(x)),
map(mailbox::obs_domain, |x| ReceivedLogToken::Domain(x)),
2023-06-13 22:50:29 +02:00
))(input)
}
#[cfg(test)]
mod tests {
use super::*;
2023-07-19 17:40:00 +02:00
use chrono::TimeZone;
use crate::rfc5322::trace::misc_token::Word;
2023-06-13 22:50:29 +02:00
#[test]
2023-06-16 10:19:28 +02:00
fn test_received_body() {
2023-06-16 09:58:07 +02:00
let hdrs = r#"from smtp.example.com ([10.83.2.2])
2023-06-13 22:50:29 +02:00
by server with LMTP
id xxxxxxxxx
(envelope-from <gitlab@example.com>)
2023-07-19 17:40:00 +02:00
for <me@example.com>; Tue, 13 Jun 2023 19:01:08 +0000"#.as_bytes();
2023-06-16 09:58:07 +02:00
2023-06-13 22:50:29 +02:00
assert_eq!(
2023-06-16 09:58:07 +02:00
received_body(hdrs),
2023-06-22 15:08:50 +02:00
Ok((
2023-07-19 17:40:00 +02:00
&b""[..],
ReceivedLog {
date: Some(FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(2023, 06, 13, 19, 1, 8).unwrap()),
log: vec![
ReceivedLogToken::Word(Word::Atom(&b"from"[..])),
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"[..]]),
})
],
}
2023-06-22 15:08:50 +02:00
))
2023-06-13 22:50:29 +02:00
);
}
2023-06-13 17:47:57 +02:00
}