wip trace
This commit is contained in:
parent
35ff869454
commit
09a6c6acdf
6 changed files with 160 additions and 32 deletions
|
@ -24,7 +24,7 @@ use crate::model;
|
|||
/// Header section
|
||||
///
|
||||
/// See: https://www.rfc-editor.org/rfc/rfc5322.html#section-2.2
|
||||
pub fn header_section(input: &str) -> IResult<&str, PermissiveHeaderSection> {
|
||||
pub fn section(input: &str) -> IResult<&str, PermissiveHeaderSection> {
|
||||
let (input, headers) = fold_many0(
|
||||
header_field,
|
||||
PermissiveHeaderSection::default,
|
||||
|
@ -95,10 +95,6 @@ pub fn header_section(input: &str) -> IResult<&str, PermissiveHeaderSection> {
|
|||
section.keywords.append(&mut kws);
|
||||
}
|
||||
|
||||
// 3.6.6. Resent Fields
|
||||
|
||||
// 3.6.7. Trace Fields
|
||||
|
||||
// 3.6.8. Optional Fields
|
||||
HeaderField::Optional(name, body) => {
|
||||
section.optional.insert(name, body);
|
||||
|
@ -138,18 +134,6 @@ enum HeaderField<'a> {
|
|||
Comments(String),
|
||||
Keywords(Vec<String>),
|
||||
|
||||
// 3.6.6. Resent Fields
|
||||
ResentDate,
|
||||
ResentFrom,
|
||||
ResentSender,
|
||||
ResentTo,
|
||||
ResentCc,
|
||||
ResentBcc,
|
||||
ResentMessageID,
|
||||
|
||||
// 3.6.7. Trace Fields
|
||||
Trace,
|
||||
|
||||
// 3.6.8. Optional Fields
|
||||
Optional(&'a str, String)
|
||||
}
|
||||
|
@ -174,7 +158,10 @@ fn header_field(input: &str) -> IResult<&str, HeaderField> {
|
|||
// Extract field body
|
||||
let (input, hfield) = match field_name {
|
||||
// 3.6.1. The Origination Date Field
|
||||
"Date" => datetime(input)?,
|
||||
"Date" => {
|
||||
let (input, body) = datetime(input)?;
|
||||
Ok((input, HeaderField::Date(body)))
|
||||
}
|
||||
|
||||
// 3.6.2. Originator Fields
|
||||
"From" => {
|
||||
|
@ -233,6 +220,28 @@ fn header_field(input: &str) -> IResult<&str, HeaderField> {
|
|||
}
|
||||
|
||||
// 3.6.6. Resent Fields
|
||||
"Resent-Date" => {
|
||||
let (input, body) = datetime(input)?;
|
||||
Ok((input, HeaderField::ResentDate(body)))
|
||||
}
|
||||
"Resent-From" => {
|
||||
unimplemented!();
|
||||
}
|
||||
"Resent-Sender" => {
|
||||
unimplemented!();
|
||||
}
|
||||
"Resent-To" => {
|
||||
unimplemented!();
|
||||
}
|
||||
"Resent-Cc" => {
|
||||
unimplemented!();
|
||||
}
|
||||
"Resent-Bcc" => {
|
||||
unimplemented!();
|
||||
}
|
||||
"Resent-Message-ID" => {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
// 3.6.7. Trace Fields
|
||||
|
||||
|
@ -248,15 +257,14 @@ fn header_field(input: &str) -> IResult<&str, HeaderField> {
|
|||
return Ok((input, hfield));
|
||||
}
|
||||
|
||||
fn datetime(input: &str) -> IResult<&str, HeaderField> {
|
||||
fn datetime(input: &str) -> IResult<&str, HeaderDate> {
|
||||
// @FIXME want to extract datetime our way in the future
|
||||
// to better handle obsolete/bad cases instead of returning raw text.
|
||||
let (input, raw_date) = unstructured(input)?;
|
||||
let date = match DateTime::parse_from_rfc2822(&raw_date) {
|
||||
match DateTime::parse_from_rfc2822(&raw_date) {
|
||||
Ok(chronodt) => HeaderDate::Parsed(chronodt),
|
||||
Err(e) => HeaderDate::Unknown(raw_date, e),
|
||||
};
|
||||
Ok((input, HeaderField::Date(date)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
16
src/header.rs
Normal file
16
src/header.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
use nom::{
|
||||
IResult,
|
||||
multi::many0,
|
||||
}
|
||||
|
||||
use crate::{common_fields, trace, whitespace};
|
||||
|
||||
pub fn section(input: &str) -> IResult(&str, HeaderSection) {
|
||||
let (input, traces) = many0(trace::section)(input)?;
|
||||
let (input, common) = common_fields::section(input)?;
|
||||
let (input, _) = whitespace::perm_crlf(input)?;
|
||||
|
||||
Ok((input, HeaderSection { traces, common }))
|
||||
}
|
||||
|
||||
|
11
src/lib.rs
11
src/lib.rs
|
@ -1,4 +1,4 @@
|
|||
pub mod headers;
|
||||
// Model
|
||||
pub mod model;
|
||||
|
||||
// Generic
|
||||
|
@ -11,3 +11,12 @@ mod misc_token;
|
|||
mod mailbox;
|
||||
mod address;
|
||||
mod identification;
|
||||
|
||||
// Header blocks
|
||||
pub mod common_fields;
|
||||
pub mod trace;
|
||||
|
||||
// Global mail
|
||||
pub mod header;
|
||||
|
||||
|
||||
|
|
39
src/model.rs
39
src/model.rs
|
@ -63,6 +63,27 @@ pub struct MessageId<'a> {
|
|||
pub right: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Trace {
|
||||
// 3.6.7 Traces
|
||||
pub received: Vec<String>,
|
||||
pub return_path: Option<String>,
|
||||
|
||||
// 3.6.6. Resent Fields
|
||||
pub resent_date: HeaderDate,
|
||||
pub resent_from: Vec<MailboxRef>,
|
||||
pub resent_sender: Option<MailboxRef>,
|
||||
pub resent_to: Vec<AddressRef>,
|
||||
pub resent_cc: Vec<AddressRef>,
|
||||
pub resent_bcc: Vec<AddressRef>,
|
||||
pub resent_msg_id: Option<MessageId<'a>>,
|
||||
|
||||
// 3.6.8. Optional Fields
|
||||
pub optional: HashMap<&'a str, String>,
|
||||
//pub failed: HashMap<&'a str, String>,
|
||||
//pub garbage: &'a str,
|
||||
}
|
||||
|
||||
/// Permissive Header Section
|
||||
///
|
||||
/// This is a structure intended for parsing/decoding,
|
||||
|
@ -70,7 +91,7 @@ pub struct MessageId<'a> {
|
|||
/// as invalid according to RFC5322 but for which we can
|
||||
/// still extract some data.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct PermissiveHeaderSection<'a> {
|
||||
pub struct CommonFields<'a> {
|
||||
// 3.6.1. The Origination Date Field
|
||||
pub date: HeaderDate,
|
||||
|
||||
|
@ -94,14 +115,18 @@ pub struct PermissiveHeaderSection<'a> {
|
|||
pub comments: Vec<String>,
|
||||
pub keywords: Vec<String>,
|
||||
|
||||
// 3.6.6. Resent Fields
|
||||
|
||||
// 3.6.7. Trace Fields
|
||||
|
||||
// 3.6.8. Optional Fields
|
||||
|
||||
// Rest
|
||||
pub optional: HashMap<&'a str, String>,
|
||||
//pub failed: HashMap<&'a str, String>,
|
||||
//pub garbage: &'a str,
|
||||
}
|
||||
|
||||
pub struct HeaderSection<'a> {
|
||||
// 3.6.7 Traces
|
||||
pub traces: Vec<Trace>,
|
||||
|
||||
// 3.6.x
|
||||
pub common: CommonFields,
|
||||
}
|
||||
|
||||
enum InvalidEmailErr {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use imf_codec::headers;
|
||||
use imf_codec::common_headers;
|
||||
|
||||
fn main() {
|
||||
let header = r#"Date: Fri, 21 Nov 1997 10:01:10 -0600
|
||||
|
@ -21,5 +21,5 @@ References: <1234@local.machine.example>
|
|||
This is a reply to your hello.
|
||||
"#;
|
||||
|
||||
println!("{:?}", headers::header_section(header));
|
||||
println!("{:?}", common_headers::section(header));
|
||||
}
|
||||
|
|
70
src/trace.rs
Normal file
70
src/trace.rs
Normal file
|
@ -0,0 +1,70 @@
|
|||
use nom::{
|
||||
IResult,
|
||||
|
||||
}
|
||||
use crate::model;
|
||||
|
||||
enum RestField<'a> {
|
||||
// 3.6.6. Resent Fields
|
||||
ResentDate(HeaderDate),
|
||||
ResentFrom(Vec<MailboxRef>),
|
||||
ResentSender(MailboxRef),
|
||||
ResentTo(Vec<AddressRef>),
|
||||
ResentCc(Vec<AddressRef>),
|
||||
ResentBcc(Vec<AddressRef>),
|
||||
ResentMessageID(model::MessageId<'a>),
|
||||
|
||||
// 3.6.8. Optional fields
|
||||
Optional(&'a str, String),
|
||||
}
|
||||
|
||||
enum PreludeField<'a> {
|
||||
// 3.6.7. Trace Fields
|
||||
ReturnPath(String),
|
||||
Received(Vec<String>),
|
||||
}
|
||||
|
||||
/// Section
|
||||
///
|
||||
/// Rewritten section for more compatibility
|
||||
///
|
||||
/// ```abnf
|
||||
///*(trace
|
||||
/// *(optional-field /
|
||||
/// resent-date /
|
||||
/// resent-from /
|
||||
/// resent-sender /
|
||||
/// resent-to /
|
||||
/// resent-cc /
|
||||
/// resent-bcc /
|
||||
/// resent-msg-id))
|
||||
/// ```
|
||||
pub fn section(input: &str) -> IResult<&str, model::Trace> {
|
||||
let (input, mut prelude_trace) = prelude(input)?;
|
||||
let (input, full_trace) = fold_many0(
|
||||
rest_field,
|
||||
prelude_trace,
|
||||
|mut trace, field| {
|
||||
match field {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Trace prelude
|
||||
///
|
||||
/// ```abnf
|
||||
/// trace = [return]
|
||||
/// 1*received
|
||||
/// return = "Return-Path:" path CRLF
|
||||
/// path = angle-addr / ([CFWS] "<" [CFWS] ">" [CFWS])
|
||||
/// received = "Received:" *received-token ";" date-time CRLF
|
||||
/// received-token = word / angle-addr / addr-spec / domain
|
||||
/// ```
|
||||
fn prelude(input: &str) -> IResult<&str, model::Trace> {
|
||||
}
|
||||
|
||||
fn rest_field(input: &str) -> IResult<&str, RestField> {
|
||||
// Ensure this is not a new prelude
|
||||
}
|
Loading…
Reference in a new issue