Retrieve messages in batches instead of one by one

This is somewhat more efficient, even though the time is still dwarfed
by the message sizes.

Signed-off-by: Jacob Kiers <code@kiers.eu>
This commit is contained in:
Jacob Kiers 2024-06-25 23:54:28 +02:00
parent 9f815f3f9c
commit 28d402f0e0

View File

@ -6,6 +6,7 @@ use std::{
path::PathBuf, path::PathBuf,
vec::IntoIter, vec::IntoIter,
}; };
use std::io::Write;
use imap::Session; use imap::Session;
use rustls_connector::RustlsConnector; use rustls_connector::RustlsConnector;
@ -93,27 +94,34 @@ impl ImapReader {
session.examine("INBOX")?; session.examine("INBOX")?;
let items = match session.uid_search("ALL") { let mut items = match session.uid_search("ALL") {
Ok(i) => i, Ok(i) => i.into_iter().collect::<Vec<_>>(),
Err(e) => return Err(Box::new(e)), Err(e) => return Err(Box::new(e)),
}; };
let mut msgs = HashMap::<String, Vec<u8>>::with_capacity(items.len()); items.sort();
//println!("# of messages: {}", &items.len()); let mut msgs = HashMap::with_capacity(items.len());
for item in items { println!("Available messages: {}", &items.len());
let msg = session.uid_fetch(&item.to_string(), "(BODY.PEEK[] UID)")?;
let message = if let Some(m) = msg.iter().next() { let sequence_sets = items.chunks(100);
m for set in sequence_sets {
} else { let sequence_set = set.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",");
continue;
};
let body = message.body().expect("Message did not have a body."); print!("Fetching {} messages...", set.len());
let _ = std::io::stdout().flush();
msgs.insert(item.to_string(), body.to_owned()); let fetched_msgs = session.uid_fetch(sequence_set, "(BODY.PEEK[] UID)")?;
for message in fetched_msgs.iter() {
let uid = message.uid.expect("Message did not have a UID").to_string();
let body = message.body().expect("Message did not have a body.");
msgs.insert(uid, body.to_owned());
}
println!(" done");
} }
session.logout().expect("Could not log out"); session.logout().expect("Could not log out");