2022-06-12 19:42:18 +00:00
|
|
|
use std::{
|
2022-06-12 20:11:47 +00:00
|
|
|
collections::HashMap,
|
2022-06-12 19:42:18 +00:00
|
|
|
error::Error,
|
|
|
|
fs::{read_dir, DirEntry},
|
|
|
|
net::TcpStream,
|
|
|
|
path::PathBuf,
|
2022-06-12 20:11:47 +00:00
|
|
|
vec::IntoIter,
|
2022-06-12 19:42:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
use imap::Session;
|
|
|
|
use rustls_connector::RustlsConnector;
|
|
|
|
|
2022-07-20 21:03:23 +00:00
|
|
|
use crate::Message;
|
|
|
|
|
2022-08-06 21:01:24 +00:00
|
|
|
pub(crate) trait EmailReader {
|
2022-07-20 21:03:23 +00:00
|
|
|
fn read_rfc822_messages(&mut self) -> Box<IntoIter<Message>>;
|
2022-06-12 19:42:18 +00:00
|
|
|
}
|
|
|
|
|
2022-08-06 21:01:24 +00:00
|
|
|
pub(crate) struct DataDirectoryMessageReader {
|
2022-06-12 19:42:18 +00:00
|
|
|
path: PathBuf,
|
|
|
|
}
|
|
|
|
|
2022-08-06 21:01:24 +00:00
|
|
|
impl DataDirectoryMessageReader {
|
2022-06-12 19:42:18 +00:00
|
|
|
pub fn new(path: PathBuf) -> Self {
|
2022-08-06 21:01:24 +00:00
|
|
|
DataDirectoryMessageReader { path }
|
2022-06-12 19:42:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-06 21:01:24 +00:00
|
|
|
impl EmailReader for DataDirectoryMessageReader {
|
2022-07-20 21:03:23 +00:00
|
|
|
fn read_rfc822_messages(&mut self) -> Box<IntoIter<Message>> {
|
2022-08-06 21:01:24 +00:00
|
|
|
println!("Reading files in {}", &self.path.display());
|
2022-06-12 19:42:18 +00:00
|
|
|
let reader = match read_dir(&self.path) {
|
|
|
|
Ok(r) => r,
|
2022-08-06 21:01:24 +00:00
|
|
|
Err(e) => {
|
|
|
|
dbg!(e);
|
|
|
|
return Box::new(Vec::new().into_iter());
|
|
|
|
}
|
2022-06-12 19:42:18 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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,
|
|
|
|
})
|
2022-12-14 14:34:29 +00:00
|
|
|
.filter_map(|i| {
|
2022-08-06 21:01:24 +00:00
|
|
|
let uid = i
|
|
|
|
.path()
|
|
|
|
.file_stem()
|
|
|
|
.unwrap()
|
|
|
|
.to_owned()
|
|
|
|
.into_string()
|
|
|
|
.expect("Could not convert filename to string.")
|
2022-12-14 14:34:29 +00:00
|
|
|
.split('_')
|
2022-08-06 21:01:24 +00:00
|
|
|
.collect::<Vec<&str>>()[0]
|
2022-12-14 14:34:29 +00:00
|
|
|
.trim_start_matches('0')
|
2022-08-06 21:01:24 +00:00
|
|
|
.to_string();
|
|
|
|
|
2022-06-12 19:42:18 +00:00
|
|
|
if let Ok(data) = std::fs::read(i.path()) {
|
2022-08-06 21:01:24 +00:00
|
|
|
Some((uid, data))
|
2022-06-12 19:42:18 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
})
|
2022-07-20 21:03:23 +00:00
|
|
|
.map(|i| Message::new(i.0, i.1));
|
2022-06-12 19:42:18 +00:00
|
|
|
|
2022-07-20 21:03:23 +00:00
|
|
|
let iter = items.collect::<Vec<Message>>().into_iter();
|
2022-06-12 19:42:18 +00:00
|
|
|
|
|
|
|
Box::new(iter)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-12 20:11:47 +00:00
|
|
|
pub struct ImapReader {
|
|
|
|
host: String,
|
2022-06-12 19:42:18 +00:00
|
|
|
port: u16,
|
2022-06-12 20:11:47 +00:00
|
|
|
username: String,
|
|
|
|
password: String,
|
|
|
|
}
|
2022-06-12 19:42:18 +00:00
|
|
|
|
2022-06-12 20:11:47 +00:00
|
|
|
impl ImapReader {
|
|
|
|
pub fn new(host: String, port: u16, username: String, password: String) -> Self {
|
|
|
|
ImapReader {
|
|
|
|
host,
|
|
|
|
port,
|
|
|
|
username,
|
|
|
|
password,
|
|
|
|
}
|
|
|
|
}
|
2022-06-12 19:42:18 +00:00
|
|
|
|
2022-06-12 20:11:47 +00:00
|
|
|
fn connect(&self) -> Result<HashMap<String, Vec<u8>>, Box<dyn Error>> {
|
|
|
|
let mut session = self.open_session()?;
|
2022-06-12 19:42:18 +00:00
|
|
|
|
2022-06-12 20:11:47 +00:00
|
|
|
session.examine("INBOX")?;
|
2022-06-12 19:42:18 +00:00
|
|
|
|
2022-06-12 20:11:47 +00:00
|
|
|
let items = match session.uid_search("ALL") {
|
|
|
|
Ok(i) => i,
|
|
|
|
Err(e) => return Err(Box::new(e)),
|
|
|
|
};
|
2022-06-12 19:42:18 +00:00
|
|
|
|
2022-06-12 20:11:47 +00:00
|
|
|
let mut msgs = HashMap::<String, Vec<u8>>::with_capacity(items.len());
|
2022-06-12 19:42:18 +00:00
|
|
|
|
2022-06-12 20:11:47 +00:00
|
|
|
//println!("# of messages: {}", &items.len());
|
|
|
|
|
|
|
|
for item in items {
|
|
|
|
let msg = session.uid_fetch(&item.to_string(), "(BODY.PEEK[] UID)")?;
|
2022-06-12 19:42:18 +00:00
|
|
|
|
2022-06-12 20:11:47 +00:00
|
|
|
let message = if let Some(m) = msg.iter().next() {
|
|
|
|
m
|
|
|
|
} else {
|
|
|
|
continue;
|
|
|
|
};
|
2022-06-12 19:42:18 +00:00
|
|
|
|
2022-06-12 20:11:47 +00:00
|
|
|
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)
|
2022-06-12 19:42:18 +00:00
|
|
|
}
|
|
|
|
|
2022-06-12 20:11:47 +00:00
|
|
|
fn open_session(
|
|
|
|
&self,
|
|
|
|
) -> Result<
|
|
|
|
Session<
|
|
|
|
rustls_connector::rustls::StreamOwned<
|
|
|
|
rustls_connector::rustls::ClientConnection,
|
|
|
|
TcpStream,
|
|
|
|
>,
|
|
|
|
>,
|
|
|
|
Box<dyn Error + 'static>,
|
|
|
|
> {
|
|
|
|
let stream = TcpStream::connect((self.host.as_ref(), self.port))?;
|
|
|
|
let tls = RustlsConnector::new_with_webpki_roots_certs();
|
|
|
|
let tls_stream = tls.connect(&self.host, stream)?;
|
|
|
|
|
|
|
|
let client = imap::Client::new(tls_stream);
|
2022-06-12 19:42:18 +00:00
|
|
|
|
2022-06-12 20:11:47 +00:00
|
|
|
Ok(client
|
|
|
|
.login(&self.username, &self.password)
|
|
|
|
.map_err(|e| e.0)?)
|
|
|
|
}
|
2022-06-12 19:42:18 +00:00
|
|
|
}
|
|
|
|
|
2022-06-12 20:11:47 +00:00
|
|
|
impl EmailReader for ImapReader {
|
2022-07-20 21:03:23 +00:00
|
|
|
fn read_rfc822_messages(&mut self) -> Box<IntoIter<Message>> {
|
2022-06-12 20:11:47 +00:00
|
|
|
let msgs = match self.connect() {
|
|
|
|
Ok(m) => m,
|
2022-08-06 21:01:24 +00:00
|
|
|
Err(e) => {
|
|
|
|
dbg!(e);
|
|
|
|
return Box::new(Vec::new().into_iter());
|
|
|
|
}
|
2022-06-12 20:11:47 +00:00
|
|
|
};
|
|
|
|
|
2022-08-06 21:01:24 +00:00
|
|
|
let items = msgs
|
|
|
|
.iter()
|
|
|
|
.map(|i| Message::new(i.0.to_owned(), i.1.to_owned()));
|
2022-06-12 19:42:18 +00:00
|
|
|
|
2022-07-20 21:03:23 +00:00
|
|
|
let iter = items.collect::<Vec<Message>>().into_iter();
|
2022-06-12 19:42:18 +00:00
|
|
|
|
2022-06-12 20:11:47 +00:00
|
|
|
Box::new(iter)
|
|
|
|
}
|
2022-06-12 19:42:18 +00:00
|
|
|
}
|