diff --git a/Cargo.toml b/Cargo.toml index 08db3d2..54e917f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ bufstream = "0.1" imap-proto = "0.7" nom = "4.0" base64 = "0.10" +chrono = "0.4" [dev-dependencies] lettre = "0.9" diff --git a/src/lib.rs b/src/lib.rs index 87249d0..5dbece9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,6 +62,7 @@ extern crate base64; extern crate bufstream; +extern crate chrono; extern crate imap_proto; extern crate native_tls; extern crate nom; diff --git a/src/types/fetch.rs b/src/types/fetch.rs index ac07e7b..0b4cf54 100644 --- a/src/types/fetch.rs +++ b/src/types/fetch.rs @@ -1,6 +1,12 @@ use super::{Flag, Seq, Uid}; +use chrono::{DateTime, FixedOffset}; use imap_proto::types::{AttributeValue, Envelope, MessageSection, SectionPath}; +/// Format of Date and Time as defined RFC3501. +/// See `date-time` element in [Formal Syntax](https://tools.ietf.org/html/rfc3501#section-9) +/// chapter of this RFC. +const DATE_TIME_FORMAT: &str = "%d-%b-%Y %H:%M:%S %z"; + /// An IMAP [`FETCH` response](https://tools.ietf.org/html/rfc3501#section-7.4.2) that contains /// data about a particular message. This response occurs as the result of a `FETCH` or `STORE` /// command, as well as by unilateral server decision (e.g., flag updates). @@ -119,4 +125,24 @@ impl Fetch { }) .next() } + + /// Extract the `INTERNALDATE` of a `FETCH` response + /// + /// See [section 2.3.3 of RFC 3501](https://tools.ietf.org/html/rfc3501#section-2.3.3) for + /// details. + pub fn internal_date(&self) -> Option> { + self.fetch + .iter() + .filter_map(|av| match av { + AttributeValue::InternalDate(date_time) => Some(*date_time), + _ => None, + }) + .next() + .and_then( + |date_time| match DateTime::parse_from_str(date_time, DATE_TIME_FORMAT) { + Ok(date_time) => Some(date_time), + Err(_) => None, + }, + ) + } } diff --git a/tests/imap_integration.rs b/tests/imap_integration.rs index ef6e964..3fc4052 100644 --- a/tests/imap_integration.rs +++ b/tests/imap_integration.rs @@ -134,6 +134,8 @@ fn inbox() { let to = &e.to.as_ref().unwrap()[0]; assert_eq!(to.mailbox, Some("inbox")); assert_eq!(to.host, Some("localhost")); + let date_opt = fetch.internal_date(); + assert!(date_opt.is_some()); // and let's delete it to clean up c.store("1", "+FLAGS (\\Deleted)").unwrap(); @@ -190,6 +192,8 @@ fn inbox_uid() { assert_eq!(fetch.uid, Some(uid)); let e = fetch.envelope().unwrap(); assert_eq!(e.subject, Some("My first e-mail")); + let date_opt = fetch.internal_date(); + assert!(date_opt.is_some()); // and let's delete it to clean up c.uid_store(format!("{}", uid), "+FLAGS (\\Deleted)")