Add Fetch.internal_date method (#113)

This method gives the parsed internal date from the FETCH answer.
This commit is contained in:
Baudouin Feildel 2019-06-28 23:39:10 +02:00 committed by Jon Gjengset
parent fec0fbae6e
commit e9f6a33bd5
4 changed files with 32 additions and 0 deletions

View file

@ -32,6 +32,7 @@ bufstream = "0.1"
imap-proto = "0.7" imap-proto = "0.7"
nom = "4.0" nom = "4.0"
base64 = "0.10" base64 = "0.10"
chrono = "0.4"
[dev-dependencies] [dev-dependencies]
lettre = "0.9" lettre = "0.9"

View file

@ -62,6 +62,7 @@
extern crate base64; extern crate base64;
extern crate bufstream; extern crate bufstream;
extern crate chrono;
extern crate imap_proto; extern crate imap_proto;
extern crate native_tls; extern crate native_tls;
extern crate nom; extern crate nom;

View file

@ -1,6 +1,12 @@
use super::{Flag, Seq, Uid}; use super::{Flag, Seq, Uid};
use chrono::{DateTime, FixedOffset};
use imap_proto::types::{AttributeValue, Envelope, MessageSection, SectionPath}; 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 /// 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` /// 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). /// command, as well as by unilateral server decision (e.g., flag updates).
@ -119,4 +125,24 @@ impl Fetch {
}) })
.next() .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<DateTime<FixedOffset>> {
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,
},
)
}
} }

View file

@ -134,6 +134,8 @@ fn inbox() {
let to = &e.to.as_ref().unwrap()[0]; let to = &e.to.as_ref().unwrap()[0];
assert_eq!(to.mailbox, Some("inbox")); assert_eq!(to.mailbox, Some("inbox"));
assert_eq!(to.host, Some("localhost")); 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 // and let's delete it to clean up
c.store("1", "+FLAGS (\\Deleted)").unwrap(); c.store("1", "+FLAGS (\\Deleted)").unwrap();
@ -190,6 +192,8 @@ fn inbox_uid() {
assert_eq!(fetch.uid, Some(uid)); assert_eq!(fetch.uid, Some(uid));
let e = fetch.envelope().unwrap(); let e = fetch.envelope().unwrap();
assert_eq!(e.subject, Some("My first e-mail")); 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 // and let's delete it to clean up
c.uid_store(format!("{}", uid), "+FLAGS (\\Deleted)") c.uid_store(format!("{}", uid), "+FLAGS (\\Deleted)")