diff options
author | Matthias Beyer <mail@beyermatthias.de> | 2020-01-05 16:10:41 +0100 |
---|---|---|
committer | Matthias Beyer <mail@beyermatthias.de> | 2020-01-05 16:11:27 +0100 |
commit | 5944284b7c6023dea95190c75507c50129bc7824 (patch) | |
tree | 4c6b60fb49aa830ed72e72495f60a9938c36afb6 | |
parent | 56a85113b7bfb89ca22180f0923bf8cd30515daf (diff) |
WIP: Add function to parse mail and make data accessible
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
-rw-r--r-- | lib/domain/libimagmail/Cargo.toml | 2 | ||||
-rw-r--r-- | lib/domain/libimagmail/src/mail.rs | 110 |
2 files changed, 111 insertions, 1 deletions
diff --git a/lib/domain/libimagmail/Cargo.toml b/lib/domain/libimagmail/Cargo.toml index 96c9ae90..4d75d7e0 100644 --- a/lib/domain/libimagmail/Cargo.toml +++ b/lib/domain/libimagmail/Cargo.toml @@ -23,7 +23,7 @@ maintenance = { status = "actively-developed" } log = "0.4.6" toml = "0.5.1" toml-query = "0.9.2" -mailparse = "0.8.0" +mailparse = "0.10" filters = "0.3.0" failure = "0.1.5" resiter = "0.4.0" diff --git a/lib/domain/libimagmail/src/mail.rs b/lib/domain/libimagmail/src/mail.rs index dc7b3c0d..de3d8827 100644 --- a/lib/domain/libimagmail/src/mail.rs +++ b/lib/domain/libimagmail/src/mail.rs @@ -18,11 +18,17 @@ // use std::path::PathBuf; +use std::fs::OpenOptions; +use std::io::Read; +use std::fmt::{Debug, Result as FmtResult, Formatter}; use failure::Fallible as Result; use failure::Error; use toml_query::read::TomlValueReadTypeExt; use chrono::NaiveDateTime; +use mailparse::ParsedMail as MPParsedMail; +use resiter::Filter; +use resiter::AndThen; use libimagstore::store::Entry; use libimagentryutil::isa::IsKindHeaderPathProvider; @@ -140,4 +146,108 @@ impl<'a> LoadedMail<'a> { }) } + // Parsing the actual mail file for further processing + pub fn parsed(&'a self) -> Result<ParsedMail<'a>> { + let mut buffer = Vec::with_capacity(4096); + OpenOptions::new() + .read(true) + .open(self.get_filename())? + .read_to_end(&mut buffer)?; + + Ok(ParsedMail { + loaded: self, + raw_data: buffer, + parsed: mailparse::parse_mail(&buffer)?, + }) + } +} + +pub struct ParsedMail<'a> { + loaded: &'a LoadedMail<'a>, + raw_data: Vec<u8>, + parsed: MPParsedMail<'a>, +} + +impl<'a> Debug for ParsedMail<'a> { + fn fmt(&self, f: &mut Formatter) -> FmtResult { + write!(f, "ParsedMail {{ {:?}, ... }}", self.loaded) + } +} + +impl<'a> ParsedMail<'a> { + + pub fn get_keys(&self) -> Result<Vec<String>> { + self.parsed + .headers + .iter() + .map(|hdr| hdr.get_key().map_err(Error::from)) + .collect() + } + + pub fn get_values(&self) -> Result<Vec<String>> { + self.parsed + .headers + .iter() + .map(|hdr| hdr.get_value().map_err(Error::from)) + .collect() + } + + pub fn get(&self, key: &str) -> Result<Option<String>> { + self.parsed + .headers + .iter() + .map(|hdr| hdr.get_key().map_err(Error::from).map(|k| (k == key, hdr))) + .filter_ok(|tpl| tpl.0) + .and_then_ok(|tpl| tpl.1.get_value().map_err(Error::from)) + .next() + .transpose() + } + + pub fn body(&self) -> Result<String> { + self.parsed.get_body().map_err(Error::from) + } + + pub fn subject(&self) -> Result<Option<String>> { + self.get("Subject") + } + + pub fn message_id(&self) -> Result<Option<String>> { + self.get("Message-Id") + } + + pub fn from(&self) -> Result<Option<String>> { + self.get("From") + } + + pub fn to(&self) -> Result<Option<String>> { + self.get("To") + } + + pub fn cc(&self) -> Result<Option<String>> { + self.get("Cc") + } + + pub fn bcc(&self) -> Result<Option<String>> { + self.get("bcc") + } + + pub fn in_reply_to(&self) -> Result<Option<String>> { + self.get("In-Reply-To") + } + + pub fn user_agent(&self) -> Result<Option<String>> { + self.get("User-Agent") + } + + pub fn reply_to(&self) -> Result<Option<String>> { + self.get("Reply-To") + } + + pub fn date(&self) -> Result<Option<String>> { + self.get("Date") + } + + pub fn references(&self) -> Result<Option<String>> { + self.get("References") + } } |