Move message readers into its own module
Signed-off-by: Jacob Kiers <jacob@jacobkiers.net>
This commit is contained in:
parent
dffd67b765
commit
8f29b35ae7
113
bin/src/main.rs
113
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<HashMap<String, Vec<u8>>, Box<dyn Error>> {
|
||||
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::<String, Vec<u8>>::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<dyn Error + 'static>,
|
||||
> {
|
||||
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<String, sanitize_html::errors::SanitizeError> {
|
||||
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<IntoIter<(String, Vec<u8>)>>;
|
||||
}
|
||||
|
||||
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<IntoIter<(String, Vec<u8>)>> {
|
||||
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::<Vec<(String, Vec<u8>)>>().into_iter();
|
||||
|
||||
Box::new(iter)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<IntoIter<(String, Vec<u8>)>>;
|
||||
}
|
||||
|
||||
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<IntoIter<(String, Vec<u8>)>> {
|
||||
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::<Vec<(String, Vec<u8>)>>().into_iter();
|
||||
|
||||
Box::new(iter)
|
||||
}
|
||||
}
|
||||
|
||||
fn connect(
|
||||
server: &str,
|
||||
port: u16,
|
||||
username: &str,
|
||||
password: &str,
|
||||
) -> Result<HashMap<String, Vec<u8>>, Box<dyn Error>> {
|
||||
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::<String, Vec<u8>>::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<dyn Error + 'static>,
|
||||
> {
|
||||
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)?)
|
||||
}
|
Loading…
Reference in New Issue