diff --git a/l10n/de_DE.js b/l10n/de_DE.js
index 958651a744b5a3ac716a21f58ff94610e1fa6cff..c0f8c7b21de7bff1868bbd65262b06d3a690ccb9 100644
--- a/l10n/de_DE.js
+++ b/l10n/de_DE.js
@@ -38,6 +38,7 @@ OC.L10N.register(
"The email could not be verified. Please try again later.": "Die E-Mail konnte nicht verifiziert werden. Bitte versuchen Sie es später noch einmal.",
"The email address is disposable. Please provide another recovery address." : "Die E-Mail-Adresse ist eine Wegwerfadresse. Bitte geben Sie eine andere Wiederherstellungsadresse an.",
"The email address is not deliverable. Please provide another recovery address.": "Die E-Mail Adresse ist nicht zustellbar. Bitte geben Sie eine andere Wiederherstellungsadresse an.",
- "Murena Workspace will be back fully soon! Please read this guide to know more.": "Murena Workspace wird bald wieder vollständig verfügbar sein! Bitte lesen Sie diesen Leitfaden, um mehr zu erfahren."
+ "Murena Workspace will be back fully soon! Please read this guide to know more.": "Murena Workspace wird bald wieder vollständig verfügbar sein! Bitte lesen Sie diesen Leitfaden, um mehr zu erfahren.",
+ "This email address in invalid, please use another one.":"Diese E-Mail-Adresse ist ungültig, bitte verwenden Sie eine andere."
},
"nplurals=2; plural=n != 1;");
diff --git a/l10n/de_DE.json b/l10n/de_DE.json
index 79b0c2f83d77723e8e9800f00774beb8610f92d7..ee6e86a28d467802a5dda7f5bf972185399abcc9 100644
--- a/l10n/de_DE.json
+++ b/l10n/de_DE.json
@@ -36,6 +36,7 @@
"The email could not be verified. Please try again later.": "Die E-Mail konnte nicht verifiziert werden. Bitte versuchen Sie es später noch einmal.",
"The email address is disposable. Please provide another recovery address." : "Die E-Mail-Adresse ist eine Wegwerfadresse. Bitte geben Sie eine andere Wiederherstellungsadresse an.",
"The email address is not deliverable. Please provide another recovery address.": "Die E-Mail Adresse ist nicht zustellbar. Bitte geben Sie eine andere Wiederherstellungsadresse an.",
- "Murena Workspace will be back fully soon! Please read this guide to know more.": "Murena Workspace wird bald wieder vollständig verfügbar sein! Bitte lesen Sie diesen Leitfaden, um mehr zu erfahren."
+ "Murena Workspace will be back fully soon! Please read this guide to know more.": "Murena Workspace wird bald wieder vollständig verfügbar sein! Bitte lesen Sie diesen Leitfaden, um mehr zu erfahren.",
+ "This email address in invalid, please use another one.":"Diese E-Mail-Adresse ist ungültig, bitte verwenden Sie eine andere."
},"pluralForm" :"nplurals=2; plural=n != 1;"
}
\ No newline at end of file
diff --git a/l10n/es.js b/l10n/es.js
index 618b8a408acf3c97dce60593f94d3bd081e0f2b7..5478cf692f48ec20ea34ec3217b66cd944efafa3 100644
--- a/l10n/es.js
+++ b/l10n/es.js
@@ -38,6 +38,7 @@ OC.L10N.register(
"The email could not be verified. Please try again later.": "No se ha podido verificar el correo electrónico. Inténtelo de nuevo más tarde.",
"The email address is disposable. Please provide another recovery address." : "La dirección de correo electrónico es desechable. Por favor, proporcione otra dirección de recuperación.",
"The email address is not deliverable. Please provide another recovery address.": "La dirección de correo electrónico no se puede entregar. Por favor, proporcione otra dirección de recuperación.",
- "Murena Workspace will be back fully soon! Please read this guide to know more.": "¡Murena Workspace estará de vuelta al 100% pronto! Por favor lee esta guía para saber más."
+ "Murena Workspace will be back fully soon! Please read this guide to know more.": "¡Murena Workspace estará de vuelta al 100% pronto! Por favor lee esta guía para saber más.",
+ "This email address in invalid, please use another one.":"Esta dirección de correo electrónico no es válida, por favor utiliza otra."
},
"nplurals=2; plural=n != 1;");
diff --git a/l10n/es.json b/l10n/es.json
index fd067414bd301b9a18e9a236cde902f2c24c9a01..79d25d7c5a5261ecd32cc65c88f6547f4ba7a2b8 100644
--- a/l10n/es.json
+++ b/l10n/es.json
@@ -36,6 +36,7 @@
"The email could not be verified. Please try again later.": "No se ha podido verificar el correo electrónico. Inténtelo de nuevo más tarde.",
"The email address is disposable. Please provide another recovery address." : "La dirección de correo electrónico es desechable. Por favor, proporcione otra dirección de recuperación.",
"The email address is not deliverable. Please provide another recovery address.": "La dirección de correo electrónico no se puede entregar. Por favor, proporcione otra dirección de recuperación.",
- "Murena Workspace will be back fully soon! Please read this guide to know more.": "¡Murena Workspace estará de vuelta al 100% pronto! Por favor lee esta guía para saber más."
+ "Murena Workspace will be back fully soon! Please read this guide to know more.": "¡Murena Workspace estará de vuelta al 100% pronto! Por favor lee esta guía para saber más.",
+ "This email address in invalid, please use another one.":"Esta dirección de correo electrónico no es válida, por favor utiliza otra."
},"pluralForm" :"nplurals=2; plural=n != 1;"
}
\ No newline at end of file
diff --git a/l10n/fr.js b/l10n/fr.js
index 9124408a6bd8f9b52196ea6e99d83b8e61d98c51..1754bcfbb487813afb76da93f3b3fb6101203534 100644
--- a/l10n/fr.js
+++ b/l10n/fr.js
@@ -38,6 +38,7 @@ OC.L10N.register(
"The email could not be verified. Please try again later.": "L'e-mail n'a pas pu être vérifié. Veuillez réessayer plus tard.",
"The email address is disposable. Please provide another recovery address." : "L'adresse électronique est jetable. Veuillez fournir une autre adresse de récupération.",
"The email address is not deliverable. Please provide another recovery address.": "L'adresse électronique ne peut être délivrée. Veuillez fournir une autre adresse de recouvrement.",
- "Murena Workspace will be back fully soon! Please read this guide to know more.": "Murena Workspace sera bientôt complètement de retour ! Veuillez lire ce guide pour en savoir plus."
+ "Murena Workspace will be back fully soon! Please read this guide to know more.": "Murena Workspace sera bientôt complètement de retour ! Veuillez lire ce guide pour en savoir plus.",
+ "This email address in invalid, please use another one.":"Cette adresse e-mail est invalide, veuillez en utiliser une autre."
},
"nplurals=2; plural=n > 1;");
diff --git a/l10n/fr.json b/l10n/fr.json
index 15b667e5c313821385dfe673d3b20e244cf7b0c4..ccb69996e42b6bdf942e1e16c3ec0e51a93d7210 100644
--- a/l10n/fr.json
+++ b/l10n/fr.json
@@ -36,6 +36,7 @@
"The email could not be verified. Please try again later.": "L'e-mail n'a pas pu être vérifié. Veuillez réessayer plus tard.",
"The email address is disposable. Please provide another recovery address." : "L'adresse électronique est jetable. Veuillez fournir une autre adresse de récupération.",
"The email address is not deliverable. Please provide another recovery address.": "L'adresse électronique ne peut être délivrée. Veuillez fournir une autre adresse de recouvrement.",
- "Murena Workspace will be back fully soon! Please read this guide to know more.": "Murena Workspace sera bientôt complètement de retour ! Veuillez lire ce guide pour en savoir plus."
+ "Murena Workspace will be back fully soon! Please read this guide to know more.": "Murena Workspace sera bientôt complètement de retour ! Veuillez lire ce guide pour en savoir plus.",
+ "This email address in invalid, please use another one.":"Cette adresse e-mail est invalide, veuillez en utiliser une autre."
},"pluralForm" :"nplurals=2; plural=n > 1;"
}
\ No newline at end of file
diff --git a/l10n/it.js b/l10n/it.js
index 35888db14663072841ff2d4deb16d741913fc270..1ed39f1bf7c4acd17f6e0ecacda1be0e7c53861b 100644
--- a/l10n/it.js
+++ b/l10n/it.js
@@ -38,6 +38,7 @@ OC.L10N.register(
"The email could not be verified. Please try again later.": "Non è stato possibile verificare l'e-mail. Si prega di riprovare più tardi.",
"The email address is disposable. Please provide another recovery address." : "L'indirizzo e-mail è monouso. Si prega di fornire un altro indirizzo di recupero.",
"The email address is not deliverable. Please provide another recovery address.": "The email address is not deliverable. Please provide another recovery address.",
- "Murena Workspace will be back fully soon! Please read this guide to know more.": "Murena Workspace tornerà presto completamente operativo! Si prega di leggere questa guida per saperne di più."
+ "Murena Workspace will be back fully soon! Please read this guide to know more.": "Murena Workspace tornerà presto completamente operativo! Si prega di leggere questa guida per saperne di più.",
+ "This email address in invalid, please use another one.":"Questo indirizzo email non è valido, per favore usane un altro."
},
"nplurals=2; plural=n != 1;");
diff --git a/l10n/it.json b/l10n/it.json
index 5f0c7def02c7d0efee07b9ec8c94539c71137382..21e38a034ae1afd521fe3b2d6d5e33708e435e1c 100644
--- a/l10n/it.json
+++ b/l10n/it.json
@@ -36,6 +36,7 @@
"The email could not be verified. Please try again later.": "Non è stato possibile verificare l'e-mail. Si prega di riprovare più tardi.",
"The email address is disposable. Please provide another recovery address." : "L'indirizzo e-mail è monouso. Si prega di fornire un altro indirizzo di recupero.",
"The email address is not deliverable. Please provide another recovery address.": "The email address is not deliverable. Please provide another recovery address.",
- "Murena Workspace will be back fully soon! Please read this guide to know more.": "Murena Workspace tornerà presto completamente operativo! Si prega di leggere questa guida per saperne di più."
+ "Murena Workspace will be back fully soon! Please read this guide to know more.": "Murena Workspace tornerà presto completamente operativo! Si prega di leggere questa guida per saperne di più.",
+ "This email address in invalid, please use another one.":"Questo indirizzo email non è valido, per favore usane un altro."
},"pluralForm" :"nplurals=2; plural=n != 1;"
}
\ No newline at end of file
diff --git a/lib/Db/ConfigMapper.php b/lib/Db/ConfigMapper.php
new file mode 100644
index 0000000000000000000000000000000000000000..62671745567de7aa2b9426e37f47cca1e204ec7d
--- /dev/null
+++ b/lib/Db/ConfigMapper.php
@@ -0,0 +1,31 @@
+connection = $connection;
+ $this->appName = $appName;
+ }
+
+
+ public function getUsersByRecoveryEmail(string $pattern) : array {
+ $qb = $this->connection->getQueryBuilder();
+ $qb->select('userid')
+ ->from("preferences")->where('`configvalue` like :pattern AND (`configkey` = "unverified-recovery-email" OR `configkey` = "recovery-email") AND `appid` = :appname ')
+ ->setParameter('pattern', $pattern)
+ ->setParameter('appname', $this->appName);
+ $result = $qb->execute();
+ $userIDs = [];
+ while ($row = $result->fetch()) {
+ $userIDs[] = $row['userid'];
+ }
+ return $userIDs;
+ }
+}
diff --git a/lib/Service/RecoveryEmailService.php b/lib/Service/RecoveryEmailService.php
index e4532ff28eafad6f7210287777a6441704d44ab9..ef139b4005aae396444a2a48c4bf86c402abb86f 100644
--- a/lib/Service/RecoveryEmailService.php
+++ b/lib/Service/RecoveryEmailService.php
@@ -11,6 +11,7 @@ use OCA\EmailRecovery\Exception\MurenaDomainDisallowedException;
use OCA\EmailRecovery\Exception\RecoveryEmailAlreadyFoundException;
use OCA\EmailRecovery\Exception\SameRecoveryEmailAsEmailException;
use OCA\EmailRecovery\Exception\TooManyVerificationAttemptsException;
+use OCA\EmailRecovery\Db\ConfigMapper;
use OCP\Defaults;
use OCP\IConfig;
use OCP\IL10N;
@@ -40,6 +41,7 @@ class RecoveryEmailService {
private ICacheFactory $cacheFactory;
private CurlService $curl;
private IClientService $httpClientService;
+ private ConfigMapper $configMapper;
private array $apiConfig;
protected const TOKEN_LIFETIME = 60 * 30; // 30 minutes
private const ATTEMPT_KEY = "recovery_email_attempts";
@@ -53,7 +55,7 @@ class RecoveryEmailService {
private IL10N $l;
private ISession $session;
- public function __construct(string $appName, ILogger $logger, IConfig $config, ISession $session, IUserManager $userManager, IMailer $mailer, IFactory $l10nFactory, IURLGenerator $urlGenerator, Defaults $themingDefaults, IVerificationToken $verificationToken, CurlService $curlService, DomainService $domainService, IL10N $l, ICacheFactory $cacheFactory, IClientService $httpClientService) {
+ public function __construct(string $appName, ILogger $logger, IConfig $config, ISession $session, IUserManager $userManager, IMailer $mailer, IFactory $l10nFactory, IURLGenerator $urlGenerator, Defaults $themingDefaults, IVerificationToken $verificationToken, CurlService $curlService, DomainService $domainService, IL10N $l, ICacheFactory $cacheFactory, IClientService $httpClientService, ConfigMapper $configMapper) {
$this->logger = $logger;
$this->config = $config;
$this->appName = $appName;
@@ -70,6 +72,7 @@ class RecoveryEmailService {
$this->l = $l;
$this->cacheFactory = $cacheFactory; // Initialize the cache factory
$this->cache = $this->cacheFactory->createDistributed(self::CACHE_KEY); // Initialize the cache
+ $this->configMapper = $configMapper;
$commonServiceURL = $this->config->getSystemValue('common_services_url', '');
if (!empty($commonServiceURL)) {
@@ -180,6 +183,11 @@ class RecoveryEmailService {
$this->logger->info("User ID $username's requested recovery email address is already taken");
throw new RecoveryEmailAlreadyFoundException($l->t('Recovery email address is already taken.'));
}
+
+ if (!$this->isAliasedRecoveryEmailValid($username, $recoveryEmail)) {
+ $this->logger->info("User ID $username's requested recovery extended email address is already taken");
+ throw new RecoveryEmailAlreadyFoundException($l->t('This email address in invalid, please use another one.'));
+ }
if ($this->isRecoveryEmailDomainDisallowed($recoveryEmail)) {
$this->logger->info("User ID $username's requested recovery email address is disallowed.");
@@ -341,6 +349,46 @@ class RecoveryEmailService {
return false;
}
+ private function getUsernameAndDomain(string $email) : ?array {
+ if ($email === null || empty($email)) {
+ return null;
+ }
+ $email = strtolower($email);
+ $emailParts = explode('@', $email);
+ $mailUsernameParts = explode('+', $emailParts[0]);
+ $mailUsername = $mailUsernameParts[0];
+ $mailDomain = $emailParts[1];
+ return [$mailUsername, $mailDomain];
+ }
+
+ public function isAliasedRecoveryEmailValid(string $username, string $recoveryEmail): bool {
+ if (!str_contains($recoveryEmail, '+')) {
+ return true;
+ }
+ $recoveryEmailParts = $this->getUsernameAndDomain($recoveryEmail);
+ $emailAliasLimit = (int) $this->config->getSystemValue('recovery_email_alias_limit', 5);
+ if ($emailAliasLimit === -1) {
+ return true;
+ }
+ $recoveryEmailregex = $recoveryEmailParts[0]."+%@".$recoveryEmailParts[1];
+ $currentRecoveryEmail = $this->getRecoveryEmail($username);
+ $currentUnverifiedRecoveryEmail = $this->getUnverifiedRecoveryEmail($username);
+ $currentRecoveryEmailParts = $this->getUsernameAndDomain($currentRecoveryEmail);
+ $currentUnverifiedRecoveryEmailParts = $this->getUsernameAndDomain($currentUnverifiedRecoveryEmail);
+
+ if ($currentRecoveryEmailParts !== null && $currentRecoveryEmailParts[0] === $recoveryEmailParts[0] && $currentRecoveryEmailParts[1] === $recoveryEmailParts[1]
+ || $currentUnverifiedRecoveryEmailParts !== null && $currentUnverifiedRecoveryEmailParts[0] === $recoveryEmailParts[0] && $currentUnverifiedRecoveryEmailParts[1] === $recoveryEmailParts[1]) {
+ return true;
+ }
+
+ $usersWithEmailRecovery = $this->configMapper->getUsersByRecoveryEmail($recoveryEmailregex);
+ if (count($usersWithEmailRecovery) > $emailAliasLimit) {
+ return false;
+ }
+
+ return true;
+ }
+
public function updateRecoveryEmail(string $username, string $recoveryEmail) : void {
$this->setUnverifiedRecoveryEmail($username, $recoveryEmail);
$this->setRecoveryEmail($username, '');