Add automatic per-email address unread folders
This commit is contained in:
@@ -207,6 +207,7 @@
|
||||
//! ```
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ffi::OsStr,
|
||||
io::{self},
|
||||
path::{Path, PathBuf},
|
||||
@@ -459,6 +460,8 @@ pub enum NotmuchError {
|
||||
StringUtf8Error(#[from] std::string::FromUtf8Error),
|
||||
#[error("failed to parse str as int")]
|
||||
ParseIntError(#[from] std::num::ParseIntError),
|
||||
#[error("failed to parse mail: {0}")]
|
||||
MailParseError(#[from] mailparse::MailParseError),
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@@ -605,6 +608,59 @@ impl Notmuch {
|
||||
Ok(serde_json::from_slice(&res)?)
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub fn unread_recipients(&self) -> Result<HashMap<String, usize>, NotmuchError> {
|
||||
let slice = self.run_notmuch([
|
||||
"show",
|
||||
"--include-html=false",
|
||||
"--entire-thread=false",
|
||||
"--body=false",
|
||||
"--format=json",
|
||||
// Arbitrary limit to prevent too much work
|
||||
"--limit=1000",
|
||||
"is:unread",
|
||||
])?;
|
||||
// Notmuch returns JSON with invalid unicode. So we lossy convert it to a string here and
|
||||
// use that for parsing in rust.
|
||||
let s = String::from_utf8_lossy(&slice);
|
||||
let mut deserializer = serde_json::Deserializer::from_str(&s);
|
||||
deserializer.disable_recursion_limit();
|
||||
let ts: ThreadSet = serde::de::Deserialize::deserialize(&mut deserializer)?;
|
||||
deserializer.end()?;
|
||||
let mut r = HashMap::new();
|
||||
for t in ts.0 {
|
||||
for tn in t.0 {
|
||||
let Some(msg) = tn.0 else {
|
||||
continue;
|
||||
};
|
||||
let mut addrs = vec![];
|
||||
let hdr = msg.headers.to;
|
||||
if let Some(to) = hdr {
|
||||
addrs.push(to);
|
||||
};
|
||||
let hdr = msg.headers.cc;
|
||||
if let Some(cc) = hdr {
|
||||
addrs.push(cc);
|
||||
};
|
||||
for recipient in addrs {
|
||||
mailparse::addrparse(&recipient)?
|
||||
.into_inner()
|
||||
.iter()
|
||||
.for_each(|a| {
|
||||
let mailparse::MailAddr::Single(si) = a else {
|
||||
return;
|
||||
};
|
||||
let addr = &si.addr;
|
||||
if addr == "couchmoney@gmail.com" || addr.ends_with("@xinu.tv") {
|
||||
*r.entry(addr.clone()).or_default() += 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn run_notmuch<I, S>(&self, args: I) -> Result<Vec<u8>, NotmuchError>
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
|
||||
Reference in New Issue
Block a user