diff --git a/CHANGELOG.md b/CHANGELOG.md index 010209ccc..f9d8b965e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ ### Changes +- introduce multiple self addresses with the "configured" address always + being the primary one. - Further improve finding the correct server after logging in #3208 - `get_connectivity_html()` returns HTML as non-scalable #3213 - add update-serial to `DC_EVENT_WEBXDC_STATUS_UPDATE` #3215 diff --git a/src/imap.rs b/src/imap.rs index 323c0ec37..a303a29f9 100644 --- a/src/imap.rs +++ b/src/imap.rs @@ -1207,25 +1207,8 @@ impl Imap { .as_mut() .context("IMAP No Connection established")?; - // TODO probably requires a test if want to keep it as is: - let self_addrs = context - .get_all_self_addrs() - .await - .context("get_all_recipients() can't get self addrs")?; - - if self_addrs.is_empty() { - bail!("get_all_recipients(): No self addresses"); - } - - let from_part = self_addrs - .iter() - .map(|a| format!(" FROM {}", a)) - .collect::(); - let mut search_command = " OR".repeat(self_addrs.len() - 1); - search_command.push_str(&from_part); - let uids = session - .uid_search(search_command.trim()) + .uid_search(get_imap_self_sent_search_command(context).await?) .await? .into_iter() .collect(); @@ -2186,6 +2169,18 @@ async fn get_modseq(context: &Context, folder: &str) -> Result { .unwrap_or(0)) } +/// Compute the imap search expression for all self-sent mails (for all self addresses) +pub async fn get_imap_self_sent_search_command(context: &Context) -> Result { + // See https://www.rfc-editor.org/rfc/rfc3501#section-6.4.4 for syntax of SEARCH and OR + let mut search_command = format!("FROM {}", context.get_primary_self_addr().await?); + + for item in context.get_secondary_self_addrs().await? { + search_command = format!("OR ({}) (FROM {})", search_command, item); + } + + Ok(search_command) +} + /// Deprecated, use get_uid_next() and get_uidvalidity() pub async fn get_config_last_seen_uid(context: &Context, folder: &str) -> Result<(u32, u32)> { let key = format!("imap.mailbox.{}", folder); @@ -2554,4 +2549,27 @@ mod tests { } Ok(()) } + + #[async_std::test] + async fn test_get_imap_search_command() -> Result<()> { + let t = TestContext::new_alice().await; + assert_eq!( + get_imap_self_sent_search_command(&t.ctx).await?, + "FROM alice@example.org" + ); + + t.ctx.set_primary_self_addr("alice@another.com").await?; + assert_eq!( + get_imap_self_sent_search_command(&t.ctx).await?, + "OR (FROM alice@another.com) (FROM alice@example.org)" + ); + + t.ctx.set_primary_self_addr("alice@third.com").await?; + assert_eq!( + get_imap_self_sent_search_command(&t.ctx).await?, + "OR (OR (FROM alice@third.com) (FROM alice@another.com)) (FROM alice@example.org)" + ); + + Ok(()) + } }