header fields identification

This commit is contained in:
Quentin 2023-06-13 15:43:14 +02:00
parent 30507aafec
commit 7334085166
Signed by: quentin
GPG key ID: E9602264D639FF68
2 changed files with 61 additions and 8 deletions

View file

@ -7,7 +7,7 @@ use nom::{
character::complete::space0, character::complete::space0,
combinator::opt, combinator::opt,
multi::fold_many0, multi::fold_many0,
multi::many0, multi::{many0, many1},
sequence::tuple, sequence::tuple,
}; };
@ -17,6 +17,8 @@ use crate::misc_token::unstructured;
use crate::model::{PermissiveHeaderSection, HeaderDate, MailboxRef, AddressRef}; use crate::model::{PermissiveHeaderSection, HeaderDate, MailboxRef, AddressRef};
use crate::mailbox::mailbox; use crate::mailbox::mailbox;
use crate::address::{mailbox_list, address_list, address_list_cfws}; use crate::address::{mailbox_list, address_list, address_list_cfws};
use crate::identification::msg_id;
use crate::model;
/// HEADERS /// HEADERS
@ -34,7 +36,6 @@ pub fn header_section(input: &str) -> IResult<&str, PermissiveHeaderSection> {
// 3.6.1. The Origination Date Field // 3.6.1. The Origination Date Field
HeaderField::Date(d) => { HeaderField::Date(d) => {
//encountered? Currently, we override...
// | orig-date | 1 | 1 | | // | orig-date | 1 | 1 | |
section.date = d; section.date = d;
} }
@ -67,6 +68,20 @@ pub fn header_section(input: &str) -> IResult<&str, PermissiveHeaderSection> {
section.bcc = addr_list; section.bcc = addr_list;
} }
// 3.6.4. Identification Fields
HeaderField::MessageID(msg_id) => {
// | message-id | 0* | 1 | SHOULD be present - see 3.6.4 |
section.msg_id = Some(msg_id);
}
HeaderField::InReplyTo(id_list) => {
// | in-reply-to | 0* | 1 | SHOULD occur in some replies - see 3.6.4 |
section.in_reply_to = id_list;
}
HeaderField::References(id_list) => {
// | in-reply-to | 0* | 1 | SHOULD occur in some replies - see 3.6.4 |
section.references = id_list;
}
HeaderField::Subject(title) => { HeaderField::Subject(title) => {
section.subject = Some(title); section.subject = Some(title);
@ -100,9 +115,9 @@ enum HeaderField<'a> {
Bcc(Vec<AddressRef>), Bcc(Vec<AddressRef>),
// 3.6.4. Identification Fields // 3.6.4. Identification Fields
MessageID, MessageID(model::MessageId<'a>),
InReplyTo, InReplyTo(Vec<model::MessageId<'a>>),
References, References(Vec<model::MessageId<'a>>),
// 3.6.5. Informational Fields // 3.6.5. Informational Fields
Subject(String), Subject(String),
@ -177,13 +192,16 @@ fn header_field(input: &str) -> IResult<&str, HeaderField> {
// 3.6.4. Identification Fields // 3.6.4. Identification Fields
"Message-ID" => { "Message-ID" => {
unimplemented!(); let (input, body) = msg_id(input)?;
(input, HeaderField::MessageID(body))
}, },
"In-Reply-To" => { "In-Reply-To" => {
unimplemented!(); let (input, body) = many1(msg_id)(input)?;
(input, HeaderField::InReplyTo(body))
}, },
"References" => { "References" => {
unimplemented!(); let (input, body) = many1(msg_id)(input)?;
(input, HeaderField::References(body))
}, },
// Rest // Rest
@ -317,6 +335,35 @@ mod tests {
); );
} }
// 3.6.4. Identification Fields
#[test]
fn test_message_id() {
assert_eq!(
header_field("Message-ID: <310@[127.0.0.1]>\r\n"),
Ok(("", HeaderField::MessageID(model::MessageId { left: "310", right: "127.0.0.1" })))
);
}
#[test]
fn test_in_reply_to() {
assert_eq!(
header_field("In-Reply-To: <a@b> <c@example.com>\r\n"),
Ok(("", HeaderField::InReplyTo(vec![
model::MessageId { left: "a", right: "b" },
model::MessageId { left: "c", right: "example.com" },
])))
);
}
#[test]
fn test_references() {
assert_eq!(
header_field("References: <1234@local.machine.example> <3456@example.net>\r\n"),
Ok(("", HeaderField::References(vec![
model::MessageId { left: "1234", right: "local.machine.example" },
model::MessageId { left: "3456", right: "example.net" },
])))
);
}
} }

View file

@ -84,6 +84,12 @@ pub struct PermissiveHeaderSection<'a> {
pub cc: Vec<AddressRef>, pub cc: Vec<AddressRef>,
pub bcc: Vec<AddressRef>, pub bcc: Vec<AddressRef>,
// 3.6.4. Identification Fields
pub msg_id: Option<MessageId<'a>>,
pub in_reply_to: Vec<MessageId<'a>>,
pub references: Vec<MessageId<'a>>,
// Rest
pub subject: Option<String>, pub subject: Option<String>,
pub optional: HashMap<&'a str, String>, pub optional: HashMap<&'a str, String>,
} }