From 8171e3d61433d653abbaa4984c5c70bed9106aef Mon Sep 17 00:00:00 2001 From: Ginger Date: Thu, 23 Apr 2026 13:05:21 -0400 Subject: [PATCH] fix: Remove a user's existing email before adding a new one --- src/service/threepid/mod.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/service/threepid/mod.rs b/src/service/threepid/mod.rs index 50ea1413c..1d0654db5 100644 --- a/src/service/threepid/mod.rs +++ b/src/service/threepid/mod.rs @@ -25,6 +25,15 @@ pub struct Service { ratelimiter: DefaultKeyedRateLimiter
, } +pub enum EmailRequirement { + /// Users may change their email, but cannot remove it entirely. + Always, + /// Users may change or remove their email. + Optional, + /// SMTP is not configured. + Unavailable, +} + struct Data { localpart_email: Arc, email_localpart: Arc, @@ -64,6 +73,19 @@ impl Service { Quota::per_minute(nonzero!(10_u32)).allow_burst(nonzero!(2_u32)); const VALIDATION_URL_PATH: &str = "/_continuwuity/3pid/email/validate"; + /// Check if users are required to have an email address. + pub fn email_requirement(&self) -> EmailRequirement { + if let Some(smtp) = &self.services.config.smtp { + if smtp.require_email_for_registration || smtp.require_email_for_token_registration { + EmailRequirement::Always + } else { + EmailRequirement::Optional + } + } else { + EmailRequirement::Unavailable + } + } + /// Send a validation message to an email address. /// /// Returns the validation session ID on success. @@ -234,6 +256,9 @@ impl Service { | None => { // The supplied email is not already in use. + // Remove the user's existing email first. + let _ = self.disassociate_localpart_email(localpart).await; + let email: &str = email.as_ref(); self.db.localpart_email.insert(localpart, email); self.db.email_localpart.insert(email, localpart);