126 lines
3.2 KiB
Rust
126 lines
3.2 KiB
Rust
|
use std::{
|
||
|
collections::HashMap,
|
||
|
error::Error,
|
||
|
fs::OpenOptions,
|
||
|
io::Write,
|
||
|
net::TcpStream,
|
||
|
path::{Path, PathBuf},
|
||
|
};
|
||
|
|
||
|
use imap::Session;
|
||
|
use mail_parser::Message;
|
||
|
use rustls_connector::RustlsConnector;
|
||
|
|
||
|
extern crate imap;
|
||
|
extern crate mail_parser;
|
||
|
extern crate rustls_connector;
|
||
|
|
||
|
fn main() {
|
||
|
let dir = Path::new("data");
|
||
|
if !dir.exists() {
|
||
|
std::fs::create_dir(&dir).expect("Could not create directory");
|
||
|
}
|
||
|
|
||
|
let messsages = connect("my.kiers.eu", 993, "newsletters@kie.rs", "Jjkcloudron1!")
|
||
|
.expect("A list of messages");
|
||
|
|
||
|
for (uid, message) in messsages {
|
||
|
println!("Processing message {}\n", &uid);
|
||
|
|
||
|
let parsed = Message::parse(&message).expect("A parsed messsage.");
|
||
|
|
||
|
// let from = match parsed.get_from() {
|
||
|
// mail_parser::HeaderValue::Address(a) => Some(a),
|
||
|
// _ => None,
|
||
|
// }
|
||
|
// .expect("An address");
|
||
|
|
||
|
// println!(
|
||
|
// "{} <{}>",
|
||
|
// from.name.as_ref().unwrap(),
|
||
|
// from.address.as_ref().unwrap()
|
||
|
// );
|
||
|
// println!(
|
||
|
// "HML: {}, Text: {}",
|
||
|
// parsed.get_html_body_count(),
|
||
|
// parsed.get_text_body_count()
|
||
|
// );
|
||
|
|
||
|
let html_body = parsed.get_html_body(0).expect("Could not read body");
|
||
|
let html_bytes = html_body.as_bytes();
|
||
|
|
||
|
println!("{}", &html_body);
|
||
|
|
||
|
let path: PathBuf = [dir, Path::new(&format!("{}.html", uid))].iter().collect();
|
||
|
let mut file = OpenOptions::new()
|
||
|
.write(true)
|
||
|
.create(true)
|
||
|
.open(path)
|
||
|
.expect("Could not open file fir writing");
|
||
|
|
||
|
file.write_all(html_bytes)
|
||
|
.expect("Could not write to file.");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn connect(
|
||
|
server: &str,
|
||
|
port: u16,
|
||
|
username: &str,
|
||
|
password: &str,
|
||
|
) -> Result<HashMap<u32, 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::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, 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)?)
|
||
|
}
|