From e6b3a5b5a9b54e054ea4dd23d15afdca7c4fa6ac Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Sun, 23 Feb 2025 09:37:09 -0800 Subject: [PATCH] notmuch & server: plumb Delivered-To and X-Original-To headers --- notmuch/src/lib.rs | 17 +++++++++++++++++ server/src/graphql.rs | 4 ++++ server/src/lib.rs | 14 +++++++++++++- server/src/nm.rs | 4 ++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/notmuch/src/lib.rs b/notmuch/src/lib.rs index cdb93bb..08241b8 100644 --- a/notmuch/src/lib.rs +++ b/notmuch/src/lib.rs @@ -271,6 +271,12 @@ pub struct Headers { #[serde(skip_serializing_if = "Option::is_none")] pub bcc: Option, #[serde(skip_serializing_if = "Option::is_none")] + #[serde(alias = "Delivered-To")] + pub delivered_to: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(alias = "X-Original-To")] + pub x_original_to: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub reply_to: Option, pub date: String, } @@ -635,10 +641,21 @@ impl Notmuch { let Some(msg) = &tn.0 else { return Ok(()); }; + info!("msg.headers {:#?}", msg.headers); let mut addrs = vec![]; let hdr = &msg.headers.to; if let Some(to) = hdr { addrs.push(to); + } else { + let hdr = &msg.headers.x_original_to; + if let Some(to) = hdr { + addrs.push(to); + } else { + let hdr = &msg.headers.delivered_to; + if let Some(to) = hdr { + addrs.push(to); + }; + }; }; let hdr = &msg.headers.cc; if let Some(cc) = hdr { diff --git a/server/src/graphql.rs b/server/src/graphql.rs index 28d6575..79c8a96 100644 --- a/server/src/graphql.rs +++ b/server/src/graphql.rs @@ -95,6 +95,10 @@ pub struct Message { pub to: Vec, // All CC headers found in email pub cc: Vec, + // X-Original-To header found in email + pub x_original_to: Option, + // Delivered-To header found in email + pub delivered_to: Option, // First Subject header found in email pub subject: Option, // Parsed Date header, if found and valid diff --git a/server/src/lib.rs b/server/src/lib.rs index 22703eb..7a49ba1 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -773,7 +773,19 @@ impl Query { for uid in &self.uids { parts.push(uid.clone()); } - parts.extend(self.remainder.clone()); + for r in &self.remainder { + // Rewrite "to:" to include ExtraTo:. ExtraTo: is configured in + // notmuch-config to index Delivered-To and X-Original-To headers. + if r.starts_with("to:") { + parts.push("(".to_string()); + parts.push(r.to_string()); + parts.push("OR".to_string()); + parts.push(r.replace("to:", "ExtraTo:")); + parts.push(")".to_string()); + } else { + parts.push(r.to_string()); + } + } parts.join(" ") } } diff --git a/server/src/nm.rs b/server/src/nm.rs index 0c28ac7..a9fe62d 100644 --- a/server/src/nm.rs +++ b/server/src/nm.rs @@ -196,6 +196,8 @@ pub async fn thread( let to = email_addresses(&path, &m, "to")?; let cc = email_addresses(&path, &m, "cc")?; + let delivered_to = email_addresses(&path, &m, "delivered-to")?.pop(); + let x_original_to = email_addresses(&path, &m, "x-original-to")?.pop(); let subject = m.headers.get_first_value("subject"); let timestamp = m .headers @@ -315,6 +317,8 @@ pub async fn thread( body, path, attachments, + delivered_to, + x_original_to, }); } messages.reverse();