web & server: add support for email photos

This commit is contained in:
2025-01-14 12:05:03 -08:00
parent f27f0deb38
commit 5a997e61da
7 changed files with 255 additions and 45 deletions

View File

@@ -237,6 +237,7 @@ impl Body {
pub struct Email {
pub name: Option<String>,
pub addr: Option<String>,
pub photo_url: Option<String>,
}
impl fmt::Display for Email {
@@ -422,6 +423,7 @@ impl QueryRoot {
}
let mut connection = Connection::new(has_previous_page, has_next_page);
// Set starting offset as the value from cursor to preserve state if no results from a corpus survived the truncation
let mut newsreader_offset =
after.as_ref().map(|sc| sc.newsreader_offset).unwrap_or(0);
let mut notmuch_offset = after.as_ref().map(|sc| sc.notmuch_offset).unwrap_or(0);
@@ -487,7 +489,7 @@ impl QueryRoot {
if newsreader::is_newsreader_thread(&thread_id) {
Ok(newsreader::thread(config, pool, thread_id).await?)
} else {
Ok(nm::thread(nm, thread_id, debug_content_tree).await?)
Ok(nm::thread(nm, pool, thread_id, debug_content_tree).await?)
}
}
}

View File

@@ -9,6 +9,8 @@ use log::{error, info, warn};
use mailparse::{parse_content_type, parse_mail, MailHeader, MailHeaderMap, ParsedMail};
use memmap::MmapOptions;
use notmuch::Notmuch;
use rocket::http::uri::error::PathError;
use sqlx::PgPool;
use tracing::instrument;
use crate::{
@@ -147,6 +149,7 @@ pub fn tags(nm: &Notmuch, needs_unread: bool) -> Result<Vec<Tag>, ServerError> {
#[instrument(name="nm::thread", skip_all, fields(thread_id=thread_id))]
pub async fn thread(
nm: &Notmuch,
pool: &PgPool,
thread_id: String,
debug_content_tree: bool,
) -> Result<Thread, ServerError> {
@@ -159,7 +162,7 @@ pub async fn thread(
let mmap = unsafe { MmapOptions::new().map(&file)? };
let m = parse_mail(&mmap)?;
let from = email_addresses(&path, &m, "from")?;
let from = match from.len() {
let mut from = match from.len() {
0 => None,
1 => from.into_iter().next(),
_ => {
@@ -171,6 +174,16 @@ pub async fn thread(
from.into_iter().next()
}
};
match from.as_mut() {
Some(from) => {
if let Some(addr) = from.addr.as_mut() {
let photo_url = photo_url_for_email_address(&pool, &addr).await?;
from.photo_url = photo_url;
}
}
_ => (),
}
let to = email_addresses(&path, &m, "to")?;
let cc = email_addresses(&path, &m, "cc")?;
let subject = m.headers.get_first_value("subject");
@@ -329,6 +342,7 @@ fn email_addresses(
mailparse::MailAddr::Single(s) => addrs.push(Email {
name: s.display_name,
addr: Some(s.addr),
photo_url: None,
}), //println!("Single: {s}"),
}
}
@@ -343,12 +357,14 @@ fn email_addresses(
addrs.push(Email {
name: Some(name.to_string()),
addr: Some(addr.to_string()),
photo_url: None,
});
}
} else {
addrs.push(Email {
name: Some(v),
addr: None,
photo_url: None,
});
}
}
@@ -877,3 +893,24 @@ pub async fn set_read_status<'ctx>(
}
Ok(true)
}
async fn photo_url_for_email_address(
pool: &PgPool,
addr: &str,
) -> Result<Option<String>, ServerError> {
let row = sqlx::query!(
r#"
SELECT
url
FROM email_photo ep
JOIN email_address ea
ON ep.id = ea.email_photo_id
WHERE
address = $1
"#,
addr
)
.fetch_optional(pool)
.await?;
Ok(row.map(|r| r.url))
}