diff --git a/deltachat-repl/src/cmdline.rs b/deltachat-repl/src/cmdline.rs index 3c58e6584..244403100 100644 --- a/deltachat-repl/src/cmdline.rs +++ b/deltachat-repl/src/cmdline.rs @@ -8,6 +8,7 @@ use std::time::Duration; use anyhow::{bail, ensure, Result}; use deltachat::chat::{self, Chat, ChatId, ChatItem, ChatVisibility, MuteDuration}; use deltachat::chatlist::*; +use deltachat::config; use deltachat::constants::*; use deltachat::contact::*; use deltachat::context::*; @@ -24,7 +25,6 @@ use deltachat::reaction::send_reaction; use deltachat::receive_imf::*; use deltachat::sql; use deltachat::tools::*; -use deltachat::config; use tokio::fs; /// Reset database tables. diff --git a/src/configure.rs b/src/configure.rs index e92a31616..16b4fd557 100644 --- a/src/configure.rs +++ b/src/configure.rs @@ -29,9 +29,10 @@ use crate::log::warn; pub use crate::login_param::EnteredLoginParam; use crate::login_param::{EnteredCertificateChecks, TransportListEntry}; use crate::net::proxy::ProxyConfig; -use crate::provider::{Protocol, Socket}; +use crate::provider::{self, Protocol, Socket}; use crate::qr::{login_param_from_account_qr, login_param_from_login_qr}; use crate::smtp::Smtp; +use crate::sync::Sync::Nosync; use crate::tools::time; use crate::transport::{ ConfiguredCertificateChecks, ConfiguredLoginParam, ConfiguredServerLoginParam, @@ -352,6 +353,7 @@ impl Context { }; self.set_config_internal(Config::NotifyAboutWrongPw, Some("1")) .await?; + apply_legacy_domain_config_defaults(self, ¶m.addr).await?; Ok(()) } @@ -392,6 +394,24 @@ impl Context { } } +/// Applies a few select non-default config values that used to come from provider database. +async fn apply_legacy_domain_config_defaults(context: &Context, addr: &str) -> Result<()> { + let settings = provider::legacy_settings_for_addr(addr); + + if settings.disable_mdns && !context.config_exists(Config::MdnsEnabled).await? { + context + .set_config_ex(Nosync, Config::MdnsEnabled, Some("0")) + .await?; + } + + if settings.worse_media_quality && !context.config_exists(Config::MediaQuality).await? { + context + .set_config_ex(Nosync, Config::MediaQuality, Some("1")) + .await?; + } + Ok(()) +} + /// Retrieves data from autoconfig /// to transform user-entered login parameters into complete configuration. async fn get_configured_param( @@ -427,7 +447,13 @@ async fn get_configured_param( && param.smtp.user.is_empty() { // no advanced parameters entered by the user: do Autoconfig - param_autoconfig = get_autoconfig(ctx, param, ¶m_domain).await; + // except for a few known legacy-domain overrides. + let legacy_servers = provider::legacy_settings_for_addr(¶m.addr).autoconfig_servers; + param_autoconfig = if legacy_servers.is_some() { + legacy_servers + } else { + get_autoconfig(ctx, param, ¶m_domain).await + }; } else { param_autoconfig = None; } diff --git a/src/context.rs b/src/context.rs index b434dd8a3..d053cc9aa 100644 --- a/src/context.rs +++ b/src/context.rs @@ -574,6 +574,12 @@ impl Context { /// Returns maximum number of recipients allowed in a single SMTP send. pub(crate) async fn get_max_smtp_rcpt_to(&self) -> Result { + if let Ok(addr) = self.get_primary_self_addr().await + && let Some(limit) = crate::provider::legacy_settings_for_addr(&addr).max_smtp_rcpt_to + { + return Ok(limit); + } + let is_chatmail = self.is_chatmail().await?; Ok(match is_chatmail { true => constants::DEFAULT_CHATMAIL_MAX_SMTP_RCPT_TO, diff --git a/src/provider.rs b/src/provider.rs index b12d827ec..00c79b5b7 100644 --- a/src/provider.rs +++ b/src/provider.rs @@ -1,7 +1,10 @@ //! Provider types. +use deltachat_contact_tools::EmailAddress; use serde::{Deserialize, Serialize}; +use crate::configure::server_params::ServerParams; + /// Server protocol. #[derive(Debug, Display, PartialEq, Eq, Copy, Clone, FromPrimitive, ToPrimitive)] #[repr(u8)] @@ -53,3 +56,121 @@ pub enum UsernamePattern { /// Part of address before `@` is used as username. Emaillocalpart = 2, } + +/// Returns true if `domain` is `suffix` itself or a subdomain of it. +fn is_exact_or_subdomain(domain: &str, suffix: &str) -> bool { + domain == suffix || domain.ends_with(&format!(".{suffix}")) +} + +/// Non-default settings that used to be looked up in provider.db for a few domains. +#[derive(Debug, Clone, PartialEq, Default)] +pub(crate) struct LegacyProviderSettings { + /// Servers to use instead of autoconfig, if any. + pub autoconfig_servers: Option>, + + /// Maximum number of recipients allowed in a single SMTP send, if limited. + pub max_smtp_rcpt_to: Option, + + /// Whether to disable strict TLS certificate checks by default. + pub disable_strict_tls: bool, + + /// Whether to disable local network contact discovery (mDNS) by default. + pub disable_mdns: bool, + + /// Whether to default to worse media quality (for slow/expensive connections). + pub worse_media_quality: bool, +} + +/// Returns hard-coded legacy settings for the domain of `addr`. +/// +/// Provider.db lookup was removed, but a handful of domains still need these overrides, +/// so they are hard-coded here instead. +pub(crate) fn legacy_settings_for_addr(addr: &str) -> LegacyProviderSettings { + let Ok(email) = EmailAddress::new(addr) else { + return LegacyProviderSettings::default(); + }; + let domain = email.domain.to_ascii_lowercase(); + + match domain.as_str() { + "nauta.cu" => LegacyProviderSettings { + autoconfig_servers: Some(vec![ + ServerParams { + protocol: Protocol::Imap, + socket: Socket::Starttls, + hostname: "imap.nauta.cu".to_string(), + port: 143, + username: String::new(), + }, + ServerParams { + protocol: Protocol::Smtp, + socket: Socket::Starttls, + hostname: "smtp.nauta.cu".to_string(), + port: 25, + username: String::new(), + }, + ]), + max_smtp_rcpt_to: Some(20), + disable_strict_tls: true, + worse_media_quality: true, + ..Default::default() + }, + _ if is_exact_or_subdomain(&domain, "hermes.radio") + || domain.ends_with(".aco-connexion.org") => + { + LegacyProviderSettings { + disable_strict_tls: true, + disable_mdns: true, + ..Default::default() + } + } + _ => LegacyProviderSettings { + autoconfig_servers: None, + max_smtp_rcpt_to: None, + disable_strict_tls: false, + disable_mdns: false, + worse_media_quality: false, + }, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_legacy_domain_overrides() { + let nauta = legacy_settings_for_addr("alice@nauta.cu"); + assert_eq!(nauta.max_smtp_rcpt_to, Some(20)); + assert!(nauta.disable_strict_tls); + assert!(nauta.worse_media_quality); + let servers = nauta.autoconfig_servers.unwrap(); + assert_eq!(servers.len(), 2); + assert_eq!(servers[0].hostname, "imap.nauta.cu"); + assert_eq!(servers[1].hostname, "smtp.nauta.cu"); + + let hermes = legacy_settings_for_addr("alice@foo.hermes.radio"); + assert!(hermes.disable_strict_tls); + assert!(hermes.disable_mdns); + // hermes.radio itself (not just its subdomains) is also a valid provider domain. + assert!(legacy_settings_for_addr("alice@hermes.radio").disable_strict_tls); + + let aco = legacy_settings_for_addr("alice@foo.aco-connexion.org"); + assert!(aco.disable_strict_tls); + assert!(aco.disable_mdns); + // Unlike hermes.radio, aco-connexion.org itself is not a valid provider domain, + // only its subdomains are (matching the original provider.db entries). + let not_aco = legacy_settings_for_addr("alice@aco-connexion.org"); + assert_eq!(not_aco.autoconfig_servers, None); + assert_eq!(not_aco.max_smtp_rcpt_to, None); + assert!(!not_aco.disable_strict_tls); + assert!(!not_aco.disable_mdns); + assert!(!not_aco.worse_media_quality); + + let unknown = legacy_settings_for_addr("alice@example.org"); + assert_eq!(unknown.autoconfig_servers, None); + assert_eq!(unknown.max_smtp_rcpt_to, None); + assert!(!unknown.disable_strict_tls); + assert!(!unknown.disable_mdns); + assert!(!unknown.worse_media_quality); + } +} diff --git a/src/transport.rs b/src/transport.rs index 96d6bc6c9..951604013 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -461,9 +461,18 @@ impl ConfiguredLoginParam { } pub(crate) fn strict_tls(&self, connected_through_proxy: bool) -> bool { + let disable_strict_tls = + crate::provider::legacy_settings_for_addr(&self.addr).disable_strict_tls; match self.certificate_checks { - ConfiguredCertificateChecks::OldAutomatic => connected_through_proxy, - ConfiguredCertificateChecks::Automatic | ConfiguredCertificateChecks::Strict => true, + ConfiguredCertificateChecks::OldAutomatic => { + if disable_strict_tls { + false + } else { + connected_through_proxy + } + } + ConfiguredCertificateChecks::Automatic => !disable_strict_tls, + ConfiguredCertificateChecks::Strict => true, ConfiguredCertificateChecks::AcceptInvalidCertificates | ConfiguredCertificateChecks::AcceptInvalidCertificates2 => false, }