parse message-id

This commit is contained in:
Quentin 2023-06-13 15:12:16 +02:00
parent de6926bb92
commit 30507aafec
Signed by: quentin
GPG key ID: E9602264D639FF68
6 changed files with 75 additions and 2 deletions

View file

@ -175,6 +175,18 @@ fn header_field(input: &str) -> IResult<&str, HeaderField> {
(input, HeaderField::Bcc(body.unwrap_or(vec![]))) (input, HeaderField::Bcc(body.unwrap_or(vec![])))
}, },
// 3.6.4. Identification Fields
"Message-ID" => {
unimplemented!();
},
"In-Reply-To" => {
unimplemented!();
},
"References" => {
unimplemented!();
},
// Rest
"Subject" => { "Subject" => {
let (input, body) = unstructured(input)?; let (input, body) = unstructured(input)?;
(input, HeaderField::Subject(body)) (input, HeaderField::Subject(body))

54
src/identification.rs Normal file
View file

@ -0,0 +1,54 @@
use std::borrow::Cow;
use nom::{
IResult,
branch::alt,
bytes::complete::{take_while, tag},
combinator::opt,
sequence::{delimited, pair, tuple},
};
use crate::whitespace::cfws;
use crate::words::dot_atom_text;
use crate::mailbox::is_dtext;
use crate::model::MessageId;
/// Message identifier
///
/// ```abnf
/// msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS]
/// ```
pub fn msg_id(input: &str) -> IResult<&str, MessageId> {
let (input, (left, _, right)) = delimited(
pair(opt(cfws), tag("<")),
tuple((id_left, tag("@"), id_right)),
pair(tag(">"), opt(cfws)),
)(input)?;
Ok((input, MessageId{ left, right }))
}
// Missing obsolete
fn id_left(input: &str) -> IResult<&str, &str> {
dot_atom_text(input)
}
// Missing obsolete
fn id_right(input: &str) -> IResult<&str, &str> {
alt((dot_atom_text, no_fold_litteral))(input)
}
fn no_fold_litteral(input: &str) -> IResult<&str, &str> {
delimited(tag("["), take_while(is_dtext), tag("]"))(input)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_msg_id() {
assert_eq!(
msg_id("<5678.21-Nov-1997@example.com>"),
Ok(("", MessageId{left: "5678.21-Nov-1997", right: "example.com"})),
);
}
}

View file

@ -10,3 +10,4 @@ mod misc_token;
// Header specific // Header specific
mod mailbox; mod mailbox;
mod address; mod address;
mod identification;

View file

@ -118,7 +118,7 @@ fn inner_domain_litteral(input: &str) -> IResult<&str, String> {
/// %d94-126 / ; characters not including /// %d94-126 / ; characters not including
/// obs-dtext ; "[", "]", or "\" /// obs-dtext ; "[", "]", or "\"
/// ``` /// ```
fn is_dtext(c: char) -> bool { pub fn is_dtext(c: char) -> bool {
(c >= '\x21' && c <= '\x5A') || (c >= '\x5E' && c <= '\x7E') || !c.is_ascii() (c >= '\x21' && c <= '\x5A') || (c >= '\x5E' && c <= '\x7E') || !c.is_ascii()
} }

View file

@ -57,6 +57,12 @@ impl From<GroupRef> for AddressRef {
} }
} }
#[derive(Debug, PartialEq)]
pub struct MessageId<'a> {
pub left: &'a str,
pub right: &'a str,
}
/// Permissive Header Section /// Permissive Header Section
/// ///
/// This is a structure intended for parsing/decoding, /// This is a structure intended for parsing/decoding,

View file

@ -40,7 +40,7 @@ pub fn atom(input: &str) -> IResult<&str, &str> {
/// dot-atom-text /// dot-atom-text
/// ///
/// `1*atext *("." 1*atext)` /// `1*atext *("." 1*atext)`
fn dot_atom_text(input: &str) -> IResult<&str, &str> { pub fn dot_atom_text(input: &str) -> IResult<&str, &str> {
recognize(pair(take_while1(is_atext), many0(pair(tag("."), take_while1(is_atext)))))(input) recognize(pair(take_while1(is_atext), many0(pair(tag("."), take_while1(is_atext)))))(input)
} }