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,
vec::IntoIter,
};
use std::io::Write;
use imap::Session;
use rustls_connector::RustlsConnector;
@ -93,27 +94,34 @@ impl ImapReader {
session.examine("INBOX")?;
let items = match session.uid_search("ALL") {
Ok(i) => i,
let mut items = match session.uid_search("ALL") {
Ok(i) => i.into_iter().collect::<Vec<_>>(),
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 {
let msg = session.uid_fetch(&item.to_string(), "(BODY.PEEK[] UID)")?;
println!("Available messages: {}", &items.len());
let message = if let Some(m) = msg.iter().next() {
m
} else {
continue;
};
let sequence_sets = items.chunks(100);
for set in sequence_sets {
let sequence_set = set.iter().map(|x| x.to_string()).collect::<Vec<_>>().join(",");
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");