web: add basic graphql view thread, no body support.

This commit is contained in:
2023-11-26 15:27:19 -08:00
parent 447a4a3387
commit 0ae72b63d0
5 changed files with 416 additions and 22 deletions

View File

@@ -7,8 +7,8 @@ use async_graphql::{
connection::{self, Connection, Edge},
Context, EmptyMutation, EmptySubscription, Error, FieldResult, Object, Schema, SimpleObject,
};
use log::info;
use mailparse::{addrparse, parse_mail, MailHeaderMap, ParsedMail};
use log::{info, warn};
use mailparse::{parse_mail, MailHeaderMap, ParsedMail};
use memmap::MmapOptions;
use notmuch::Notmuch;
use rayon::prelude::*;
@@ -39,6 +39,7 @@ pub struct ThreadSummary {
#[derive(Debug, SimpleObject)]
pub struct Thread {
subject: String,
messages: Vec<Message>,
}
@@ -174,13 +175,18 @@ impl QueryRoot {
let file = File::open(&path)?;
let mmap = unsafe { MmapOptions::new().map(&file)? };
let m = parse_mail(&mmap)?;
let from = if let Some(from) = m.headers.get_first_value("from") {
addrparse(&from)?.extract_single_info().map(|si| Email {
name: si.display_name,
addr: Some(si.addr),
})
} else {
None
let from = email_addresses(&path, &m, "from")?;
let from = match from.len() {
0 => None,
1 => from.into_iter().next(),
_ => {
warn!(
"Got {} from addresses in message, truncating: {:?}",
from.len(),
from
);
from.into_iter().next()
}
};
let to = email_addresses(&path, &m, "to")?;
let cc = email_addresses(&path, &m, "cc")?;
@@ -198,7 +204,15 @@ impl QueryRoot {
});
}
messages.reverse();
Ok(Thread { messages })
// Find the first subject that's set. After reversing the vec, this should be the oldest
// message.
let subject: String = messages
.iter()
.skip_while(|m| m.subject.is_none())
.next()
.and_then(|m| m.subject.clone())
.unwrap_or("(NO SUBJECT)".to_string());
Ok(Thread { subject, messages })
}
}
@@ -228,8 +242,8 @@ fn email_addresses(path: &str, m: &ParsedMail, header_name: &str) -> Result<Vec<
if v.matches('@').count() == 1 {
if v.matches('<').count() == 1 && v.ends_with('>') {
let idx = v.find('<').unwrap();
let addr = &v[idx + 1..v.len() - 1];
let name = &v[..idx];
let addr = &v[idx + 1..v.len() - 1].trim();
let name = &v[..idx].trim();
addrs.push(Email {
name: Some(name.to_string()),
addr: Some(addr.to_string()),