From 131f2920deb5e4ac4079b022eab6788c0d09348b Mon Sep 17 00:00:00 2001 From: nulldev Date: Mon, 24 Jan 2022 00:40:03 -0500 Subject: [PATCH] Upgrade imap to 3.0.0-alpha.4 and allow skipping cert validation --- Cargo.lock | 97 +++++++++++++++++++++++++---------------------------- Cargo.toml | 2 +- src/main.rs | 58 ++++++++++++++++++++++---------- 3 files changed, 87 insertions(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2ae87e0..87be860 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "aho-corasick" version = "0.7.15" @@ -18,12 +20,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "arrayvec" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" - [[package]] name = "atty" version = "0.2.14" @@ -53,6 +49,18 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "bitvec" +version = "0.19.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "bufstream" version = "0.1.4" @@ -83,11 +91,8 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ - "libc", "num-integer", "num-traits", - "time", - "winapi", ] [[package]] @@ -171,6 +176,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + [[package]] name = "getrandom" version = "0.2.1" @@ -193,9 +204,9 @@ dependencies = [ [[package]] name = "imap" -version = "2.4.1" +version = "3.0.0-alpha.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c617c55def8c42129e0dd503f11d7ee39d73f5c7e01eff55768b3879ff1d107d" +checksum = "b26b6f9b2c28b6aa7fabf623e75a8b6bd382ee0951d0e052c1d32c887150fb67" dependencies = [ "base64", "bufstream", @@ -209,9 +220,9 @@ dependencies = [ [[package]] name = "imap-proto" -version = "0.10.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16a6def1d5ac8975d70b3fd101d57953fe3278ef2ee5d7816cba54b1d1dfc22f" +checksum = "3ad9b46a79efb6078e578ae04e51463d7c3e8767864687f7e63095b3cbefafbb" dependencies = [ "nom", ] @@ -234,19 +245,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -[[package]] -name = "lexical-core" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616" -dependencies = [ - "arrayvec", - "bitflags", - "cfg-if 0.1.10", - "ryu", - "static_assertions", -] - [[package]] name = "libc" version = "0.2.82" @@ -288,11 +286,12 @@ dependencies = [ [[package]] name = "nom" -version = "5.1.2" +version = "6.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6" dependencies = [ - "lexical-core", + "bitvec", + "funty", "memchr", "version_check", ] @@ -367,6 +366,12 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +[[package]] +name = "radium" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" + [[package]] name = "rand" version = "0.8.2" @@ -443,12 +448,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "ryu" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" - [[package]] name = "same-file" version = "1.0.6" @@ -491,18 +490,18 @@ dependencies = [ "libc", ] -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.2.0" @@ -545,16 +544,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "time" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "unicode-width" version = "0.1.8" @@ -626,3 +615,9 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" diff --git a/Cargo.toml b/Cargo.toml index e96b784..c07f9b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ keywords = ["email", "eml", "imap", "cli"] categories = ["command-line-utilities"] [dependencies] -imap = "2.4" +imap = "3.0.0-alpha.4" native-tls = "0.2" clap = "2.33" walkdir = "2" diff --git a/src/main.rs b/src/main.rs index 047ef40..fd273ce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,16 @@ #[macro_use] extern crate lazy_static; + use indicatif::ProgressStyle; -use regex::Regex; +use regex::bytes::Regex; use std::fs; use std::io::{Error, ErrorKind}; +use std::net::TcpStream; use std::path::{Path, PathBuf}; use clap::{App, Arg, ArgMatches}; +use imap::Session; +use native_tls::{TlsConnector, TlsStream}; use rand::distributions::Alphanumeric; use rand::Rng; use walkdir::WalkDir; @@ -47,12 +51,12 @@ fn list_eml_file( )); } -fn randomize_message_id(eml: &String) -> Result { +fn randomize_message_id(eml: &[u8]) -> Result, String> { lazy_static! { static ref MID_RE: Regex = Regex::new(r"(?imu)^message-id:.+$").unwrap(); } - let mut new_eml = String::new(); + let mut new_eml = Vec::new(); let header_pos = MID_RE.find(eml); if header_pos.is_none() { @@ -60,17 +64,19 @@ fn randomize_message_id(eml: &String) -> Result { } let (fpart, lpart) = eml.split_at(header_pos.unwrap().start()); - new_eml.push_str(fpart); + new_eml.extend_from_slice(fpart); - let (_mid, rest) = lpart.split_at(lpart.find('\n').expect("Malformed Message-ID.")); - new_eml.push_str("Message-ID: "); + let lpart_str = std::str::from_utf8(lpart) + .map_err(|e| format!("UTF error: {e:?}"))?; + let (_mid, rest) = lpart.split_at(lpart_str.find('\n').expect("Malformed Message-ID.")); + new_eml.extend_from_slice("Message-ID: ".as_bytes()); let rand_string: String = rand::thread_rng() .sample_iter(&Alphanumeric) .take(30) .map(char::from) .collect(); - new_eml.push_str(&rand_string); - new_eml.push_str(rest); + new_eml.extend_from_slice(rand_string.as_bytes()); + new_eml.extend_from_slice(rest); return Ok(new_eml); } @@ -85,6 +91,7 @@ struct Config { recursive: bool, symlink: bool, random_id: bool, + skip_verify_cert: bool, } impl Config { @@ -103,6 +110,7 @@ impl Config { let recursive = matches.is_present("recursive"); let symlink = matches.is_present("symlink"); let random_id = matches.is_present("random-message-id"); + let skip_verify_cert = matches.is_present("skip-verify-cert"); Config { server, @@ -114,6 +122,7 @@ impl Config { recursive, symlink, random_id, + skip_verify_cert } } } @@ -183,6 +192,11 @@ fn main() { .long("random-message-id") .help("Randomize the Message-ID in the emls before sending them."), ) + .arg( + Arg::with_name("skip-verify-cert") + .long("skip-verify-cert") + .help("Skip checking server certificate when connecting over TLS."), + ) .arg( Arg::with_name("DIR") .help("Directory in which to get the EML files.") @@ -205,10 +219,7 @@ fn main() { println!("Randomizing Message-IDs.") } - let tls = native_tls::TlsConnector::builder().build().unwrap(); - let client = - imap::connect((conf.server.clone(), conf.port.clone()), &conf.server, &tls).unwrap(); - let mut session = client.login(&conf.login, &conf.password).unwrap(); + let mut session = connect(&conf); let bar = indicatif::ProgressBar::new(emls_files.len() as u64); bar.set_style( ProgressStyle::default_bar() @@ -216,7 +227,7 @@ fn main() { ); bar.set_message("EML Copied"); for eml in &emls_files { - let mut rfc822 = fs::read_to_string(eml).expect("Failed to read eml file."); + let mut rfc822 = fs::read(eml).expect("Failed to read eml file."); if conf.random_id { let randomize_id = randomize_message_id(&rfc822); if randomize_id.is_err() { @@ -229,16 +240,15 @@ fn main() { } } - let send_res = session.append(&conf.folder, &rfc822); + let send_res = session.append(&conf.folder, &rfc822) + .finish(); if send_res.is_err() { // we might have been disconnected so we retry. let _ = session.close(); - let new_client = - imap::connect((conf.server.clone(), conf.port.clone()), &conf.server, &tls) - .unwrap(); - session = new_client.login(&conf.login, &conf.password).unwrap(); + session = connect(&conf); session .append(&conf.folder, &rfc822) + .finish() .expect("Could not copy email."); } @@ -246,3 +256,15 @@ fn main() { } bar.finish(); } + +fn connect(conf: &Config) -> Session> { + let skip_verify_cert = conf.skip_verify_cert; + let client = imap::ClientBuilder::new(&conf.server, conf.port) + .connect(|domain, tcp| { + let ssl_conn = TlsConnector::builder() + .danger_accept_invalid_certs(skip_verify_cert) + .build()?; + Ok(TlsConnector::connect(&ssl_conn, domain, tcp)?) + }).unwrap(); + client.login(&conf.login, &conf.password).unwrap() +}