From 8f29b35ae75217817ec9a0c7fc9ecc59d3ad4341 Mon Sep 17 00:00:00 2001 From: Jacob Kiers Date: Sun, 12 Jun 2022 21:42:18 +0200 Subject: [PATCH] Move message readers into its own module Signed-off-by: Jacob Kiers --- bin/src/main.rs | 113 ++----------------------------------- bin/src/message_reader.rs | 116 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 108 deletions(-) create mode 100644 bin/src/message_reader.rs diff --git a/bin/src/main.rs b/bin/src/main.rs index 1b09dc2..580120f 100644 --- a/bin/src/main.rs +++ b/bin/src/main.rs @@ -1,11 +1,12 @@ +mod message_reader; + use std::{ collections::HashMap, error::Error, - fs::{read_dir, DirEntry, OpenOptions}, + fs::OpenOptions, io::Write, net::TcpStream, path::{Path, PathBuf}, - vec::IntoIter, }; use imap::Session; @@ -21,6 +22,8 @@ extern crate rustls_connector; extern crate sanitize_html; extern crate sha2; +use message_reader::{EmailReader, TestMessagesReader}; + fn main() { let dir = Path::new("data"); if !dir.exists() { @@ -65,67 +68,6 @@ fn main() { } } -fn connect( - server: &str, - port: u16, - username: &str, - password: &str, -) -> Result>, Box> { - let mut session = open_session(server, port, username, password)?; - - session.examine("INBOX")?; - - let items = match session.uid_search("ALL") { - Ok(i) => i, - Err(e) => return Err(Box::new(e)), - }; - - let mut msgs = HashMap::>::with_capacity(items.len()); - - //println!("# of messages: {}", &items.len()); - - for item in items { - let msg = session.uid_fetch(&item.to_string(), "(BODY.PEEK[] UID)")?; - - let message = if let Some(m) = msg.iter().next() { - m - } else { - continue; - }; - - let body = message.body().expect("Message did not have a body."); - - msgs.insert(item.to_string(), body.to_owned()); - } - - session.logout().expect("Could not log out"); - - Ok(msgs) -} - -fn open_session( - server: &str, - port: u16, - username: &str, - password: &str, -) -> Result< - Session< - rustls_connector::rustls::StreamOwned< - rustls_connector::rustls::ClientConnection, - TcpStream, - >, - >, - Box, -> { - let stream = TcpStream::connect((server, port))?; - let tls = RustlsConnector::new_with_webpki_roots_certs(); - let tls_stream = tls.connect(server, stream)?; - - let client = imap::Client::new(tls_stream); - - Ok(client.login(username, password).map_err(|e| e.0)?) -} - fn process_html(input: &str) -> Result { let mut rules = sanitize_html::rules::predefined::relaxed().delete("style"); @@ -161,48 +103,3 @@ fn write_to_test_path(uid: &str, message: &[u8]) { .expect("Could not open file fir writing") .write_all(&message); } - -pub trait EmailReader { - fn read_rfc822_messages(&mut self) -> Box)>>; -} - -struct TestMessagesReader { - path: PathBuf, -} - -impl TestMessagesReader { - pub fn new(path: PathBuf) -> Self { - TestMessagesReader { path } - } -} - -impl EmailReader for TestMessagesReader { - fn read_rfc822_messages(&mut self) -> Box)>> { - let reader = match read_dir(&self.path) { - Ok(r) => r, - Err(_) => return Box::new(Vec::new().into_iter()), - }; - - let items = reader - .filter(|i| i.is_ok()) - .map(|i| i.unwrap() as DirEntry) - .filter(|d| match d.path().extension() { - Some(ext) => ext == "eml", - None => false, - }) - .map(|i| { - let uid = i.path().file_stem().unwrap().to_owned(); - if let Ok(data) = std::fs::read(i.path()) { - Some((uid.into_string().unwrap(), data)) - } else { - None - } - }) - .filter(|i| i.is_some()) - .map(|i| i.unwrap()); - - let iter = items.collect::)>>().into_iter(); - - Box::new(iter) - } -} diff --git a/bin/src/message_reader.rs b/bin/src/message_reader.rs new file mode 100644 index 0000000..1c4d15e --- /dev/null +++ b/bin/src/message_reader.rs @@ -0,0 +1,116 @@ +use std::{ + error::Error, + fs::{read_dir, DirEntry}, + net::TcpStream, + path::PathBuf, + vec::IntoIter, collections::HashMap, +}; + +use imap::Session; +use rustls_connector::RustlsConnector; + +pub trait EmailReader { + fn read_rfc822_messages(&mut self) -> Box)>>; +} + +pub(crate) struct TestMessagesReader { + path: PathBuf, +} + +impl TestMessagesReader { + pub fn new(path: PathBuf) -> Self { + TestMessagesReader { path } + } +} + +impl EmailReader for TestMessagesReader { + fn read_rfc822_messages(&mut self) -> Box)>> { + let reader = match read_dir(&self.path) { + Ok(r) => r, + Err(_) => return Box::new(Vec::new().into_iter()), + }; + + let items = reader + .filter(|i| i.is_ok()) + .map(|i| i.unwrap() as DirEntry) + .filter(|d| match d.path().extension() { + Some(ext) => ext == "eml", + None => false, + }) + .map(|i| { + let uid = i.path().file_stem().unwrap().to_owned(); + if let Ok(data) = std::fs::read(i.path()) { + Some((uid.into_string().unwrap(), data)) + } else { + None + } + }) + .filter(|i| i.is_some()) + .map(|i| i.unwrap()); + + let iter = items.collect::)>>().into_iter(); + + Box::new(iter) + } +} + +fn connect( + server: &str, + port: u16, + username: &str, + password: &str, +) -> Result>, Box> { + let mut session = open_session(server, port, username, password)?; + + session.examine("INBOX")?; + + let items = match session.uid_search("ALL") { + Ok(i) => i, + Err(e) => return Err(Box::new(e)), + }; + + let mut msgs = HashMap::>::with_capacity(items.len()); + + //println!("# of messages: {}", &items.len()); + + for item in items { + let msg = session.uid_fetch(&item.to_string(), "(BODY.PEEK[] UID)")?; + + let message = if let Some(m) = msg.iter().next() { + m + } else { + continue; + }; + + let body = message.body().expect("Message did not have a body."); + + msgs.insert(item.to_string(), body.to_owned()); + } + + session.logout().expect("Could not log out"); + + Ok(msgs) +} + +fn open_session( + server: &str, + port: u16, + username: &str, + password: &str, +) -> Result< + Session< + rustls_connector::rustls::StreamOwned< + rustls_connector::rustls::ClientConnection, + TcpStream, + >, + >, + Box, +> { + let stream = TcpStream::connect((server, port))?; + let tls = RustlsConnector::new_with_webpki_roots_certs(); + let tls_stream = tls.connect(server, stream)?; + + let client = imap::Client::new(tls_stream); + + Ok(client.login(username, password).map_err(|e| e.0)?) +}