From 4e5b41f150c32e1f8ff1e0346bde44defd98dfc2 Mon Sep 17 00:00:00 2001 From: link2xt Date: Mon, 25 Sep 2023 14:03:09 +0000 Subject: [PATCH] fix: require valid email addresses in dc_provider_new_from_email[_with_dns]() --- deltachat-ffi/src/lib.rs | 16 +++++++++++++--- src/provider.rs | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index ba33b9637..8025620ef 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -4531,7 +4531,14 @@ pub unsafe extern "C" fn dc_provider_new_from_email( let ctx = &*context; - match block_on(provider::get_provider_info(ctx, addr.as_str(), true)) { + match block_on(provider::get_provider_info_by_addr( + ctx, + addr.as_str(), + true, + )) + .log_err(ctx) + .unwrap_or_default() + { Some(provider) => provider, None => ptr::null_mut(), } @@ -4558,11 +4565,14 @@ pub unsafe extern "C" fn dc_provider_new_from_email_with_dns( match socks5_enabled { Ok(socks5_enabled) => { - match block_on(provider::get_provider_info( + match block_on(provider::get_provider_info_by_addr( ctx, addr.as_str(), socks5_enabled, - )) { + )) + .log_err(ctx) + .unwrap_or_default() + { Some(provider) => provider, None => ptr::null_mut(), } diff --git a/src/provider.rs b/src/provider.rs index 9a8a438ca..fe7073ebe 100644 --- a/src/provider.rs +++ b/src/provider.rs @@ -8,6 +8,7 @@ use trust_dns_resolver::{config, AsyncResolver, TokioAsyncResolver}; use crate::config::Config; use crate::context::Context; use crate::provider::data::{PROVIDER_DATA, PROVIDER_IDS}; +use crate::tools::EmailAddress; /// Provider status according to manual testing. #[derive(Debug, Display, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)] @@ -175,21 +176,30 @@ fn get_resolver() -> Result { Ok(resolver) } +/// Returns provider for the given an e-mail address. +/// +/// Returns an error if provided address is not valid. +pub async fn get_provider_info_by_addr( + context: &Context, + addr: &str, + skip_mx: bool, +) -> Result> { + let addr = EmailAddress::new(addr)?; + + let provider = get_provider_info(context, &addr.domain, skip_mx).await; + Ok(provider) +} + /// Returns provider for the given domain. /// /// This function looks up domain in offline database first. If not /// found, it queries MX record for the domain and looks up offline /// database for MX domains. -/// -/// For compatibility, email address can be passed to this function -/// instead of the domain. pub async fn get_provider_info( context: &Context, domain: &str, skip_mx: bool, ) -> Option<&'static Provider> { - let domain = domain.rsplit('@').next()?; - if let Some(provider) = get_provider_by_domain(domain) { return Some(provider); } @@ -314,15 +324,25 @@ mod tests { let t = TestContext::new().await; assert!(get_provider_info(&t, "", false).await.is_none()); assert!(get_provider_info(&t, "google.com", false).await.unwrap().id == "gmail"); + assert!(get_provider_info(&t, "example@google.com", false) + .await + .is_none()); + } - // get_provider_info() accepts email addresses for backwards compatibility + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_get_provider_info_by_addr() -> Result<()> { + let t = TestContext::new().await; + assert!(get_provider_info_by_addr(&t, "google.com", false) + .await + .is_err()); assert!( - get_provider_info(&t, "example@google.com", false) - .await + get_provider_info_by_addr(&t, "example@google.com", false) + .await? .unwrap() .id == "gmail" ); + Ok(()) } #[test]