From 913d7a8b32f5ef282235d1ec229667659228f7a1 Mon Sep 17 00:00:00 2001 From: the-djmaze <3752035+the-djmaze@users.noreply.github.com> Date: Mon, 2 Nov 2026 03:13:39 +0100 Subject: [PATCH] Improceved IDN emailaddress handling --- .../0.0.0/app/libraries/MailSo/Mime/Email.php | 23 +++++++++++-------- .../libraries/RainLoop/Actions/Accounts.php | 7 +++--- .../RainLoop/Actions/AdminDomains.php | 2 +- .../libraries/RainLoop/Actions/Messages.php | 2 +- .../app/libraries/RainLoop/Actions/Pgp.php | 1 + .../app/libraries/RainLoop/Actions/SMime.php | 1 + .../libraries/RainLoop/Actions/UserAuth.php | 14 ++++++----- .../app/libraries/RainLoop/Model/Account.php | 10 ++++++++ .../Providers/AddressBook/PdoAddressBook.php | 6 ++--- 9 files changed, 42 insertions(+), 24 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Mime/Email.php b/snappymail/v/0.0.0/app/libraries/MailSo/Mime/Email.php index 246bc40c5..002820bf0 100644 --- a/snappymail/v/0.0.0/app/libraries/MailSo/Mime/Email.php +++ b/snappymail/v/0.0.0/app/libraries/MailSo/Mime/Email.php @@ -48,7 +48,7 @@ class Email implements \JsonSerializable /** * @throws \ValueError */ - public static function Parse(string $sEmailAddress) : self + public static function Parse(string $sEmailAddress): self { $sEmailAddress = Utils::Trim(Utils::DecodeHeaderValue($sEmailAddress)); if (!\strlen(\trim($sEmailAddress))) { @@ -153,32 +153,37 @@ class Email implements \JsonSerializable return new self($sEmail, $sName); } - public function GetEmail(bool $bUtf8 = false) : string + public function GetEmail(bool $bUtf8 = false): string { return $bUtf8 ? \SnappyMail\IDN::emailToUtf8($this->sEmail) : $this->sEmail; } - public function GetDisplayName() : string + public function GetEmailUtf8(): string + { + return \SnappyMail\IDN::emailToUtf8($this->sEmail); + } + + public function GetDisplayName(): string { return $this->sDisplayName; } - public function getLocalPart() : string + public function getLocalPart(): string { return Utils::getEmailAddressLocalPart($this->sEmail); } - public function GetDomain(bool $bIdn = false) : string + public function GetDomain(bool $bIdn = false): string { return Utils::getEmailAddressDomain($this->GetEmail($bIdn)); } - public function SetDkimStatus(string $sDkimStatus) + public function SetDkimStatus(string $sDkimStatus): void { $this->sDkimStatus = Enumerations\DkimStatus::normalizeValue($sDkimStatus); } - public function ToString(bool $bConvertSpecialsName = false, bool $bUtf8 = false) : string + public function ToString(bool $bConvertSpecialsName = false, bool $bUtf8 = false): string { $sReturn = ''; if (\strlen($this->sEmail)) { @@ -195,7 +200,7 @@ class Email implements \JsonSerializable return $sReturn; } - public function __toString() : string + public function __toString(): string { return $this->ToString(); } @@ -206,7 +211,7 @@ class Email implements \JsonSerializable return array( '@Object' => 'Object/Email', 'name' => Utils::Utf8Clear($this->sDisplayName), - 'email' => Utils::Utf8Clear($this->GetEmail(true)), + 'email' => Utils::Utf8Clear($this->GetEmailUtf8()), 'dkimStatus' => $this->sDkimStatus ); } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php index 4e78236e9..a15ba8307 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php @@ -81,7 +81,7 @@ trait Accounts $oMainAccount = $this->getMainAccountFromToken(); $aAccounts = $this->GetAccounts($oMainAccount); - $sEmail = \trim($this->GetActionParam('email', '')); + $sEmail = IDN::emailToAscii(\trim($this->GetActionParam('email', ''))); $oPassword = new \SnappyMail\SensitiveString($this->GetActionParam('password', '')); $bNew = !empty($this->GetActionParam('new', 1)); @@ -176,8 +176,7 @@ trait Accounts return $this->FalseResponse(); } - $sEmailToDelete = \trim($this->GetActionParam('emailToDelete', '')); - $sEmailToDelete = IDN::emailToAscii($sEmailToDelete); + $sEmailToDelete = IDN::emailToAscii(\trim($this->GetActionParam('emailToDelete', ''))); $aAccounts = $this->GetAccounts($oMainAccount); @@ -252,7 +251,7 @@ trait Accounts */ public function DoAccountSwitch(): array { - if ($this->switchAccount(\trim($this->GetActionParam('Email', '')))) { + if ($this->switchAccount(new \MailSo\Mime\Email($this->GetActionParam('Email', '')))) { $oAccount = $this->getAccountFromToken(); $aResult = $this->getAccountData($oAccount); // $this->Plugins()->InitAppData($bAdmin, $aResult, $oAccount); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/AdminDomains.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/AdminDomains.php index bb037054b..ad7c647b9 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/AdminDomains.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/AdminDomains.php @@ -64,7 +64,7 @@ trait AdminDomains public function DoAdminDomainMatch() : array { $sCredentials = $this->resolveLoginCredentials( - $this->GetActionParam('username'), + new \MailSo\Mime\Email($this->GetActionParam('username')), new \SnappyMail\SensitiveString('********') ); $sEmail = $sCredentials['email']; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php index 487cafb2d..d7453b2a3 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Messages.php @@ -335,7 +335,7 @@ trait Messages $oToCollection = $oMessage->GetTo(); if ($oToCollection) { foreach ($oToCollection as /* @var $oEmail \MailSo\Mime\Email */ $oEmail) { - $aArrayToFrec[$oEmail->GetEmail(true)] = $oEmail->ToString(false, true); + $aArrayToFrec[$oEmail->GetEmailUtf8()] = $oEmail->ToString(false, true); } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php index a87b6d1da..59dc6a13f 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Pgp.php @@ -198,6 +198,7 @@ trait Pgp $sKey = $this->GetActionParam('key', ''); $sKeyId = $this->GetActionParam('keyId', ''); $sEmail = $this->GetActionParam('email', ''); +// $sEmail = \SnappyMail\IDN::emailToAscii($this->GetActionParam('email', '')); if (!$sKey) { try { diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php index 124f3c974..b835126a8 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/SMime.php @@ -62,6 +62,7 @@ trait SMime $cert = new Certificate(); $cert->distinguishedName['commonName'] = $this->GetActionParam('name', '') ?: $oAccount->Name(); $cert->distinguishedName['emailAddress'] = $this->GetActionParam('email', '') ?: $oAccount->Email(); +// $cert->distinguishedName['emailAddress'] = \SnappyMail\IDN::emailToAscii($this->GetActionParam('email', '') ?: $oAccount->Email()); $result = $cert->createSelfSigned($oPassphrase, $this->GetActionParam('privateKey', '')); return $this->DefaultResponse($result ?: false); } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php index be26a590e..5dfb90577 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php @@ -2,6 +2,7 @@ namespace RainLoop\Actions; +use MailSo\Mime\Email; use RainLoop\Enumerations\Capa; use RainLoop\Notifications; use RainLoop\Utils; @@ -33,9 +34,9 @@ trait UserAuth /** * @throws \RainLoop\Exceptions\ClientException */ - protected function resolveLoginCredentials(string $sEmail, SensitiveString $oPassword): array + protected function resolveLoginCredentials(Email $oEmail, SensitiveString $oPassword): array { - $sEmail = \SnappyMail\IDN::emailToAscii(\MailSo\Base\Utils::Trim($sEmail)); + $sEmail = $oEmail->GetEmail(); $sNewEmail = $sEmail; $this->Plugins()->RunHook('login.credentials.step-1', array(&$sNewEmail)); @@ -139,9 +140,10 @@ trait UserAuth /** * @throws \RainLoop\Exceptions\ClientException */ +// public function LoginProcess(Email $sEmail, SensitiveString $oPassword, bool $bMainAccount = true): Account public function LoginProcess(string $sEmail, SensitiveString $oPassword, bool $bMainAccount = true): Account { - $aCredentials = $this->resolveLoginCredentials($sEmail, $oPassword); + $aCredentials = $this->resolveLoginCredentials(new Email($sEmail), $oPassword); if (!\str_contains($aCredentials['email'], '@') || !\strlen($oPassword)) { throw new ClientException(Notifications::InvalidInputArgument); @@ -184,14 +186,14 @@ trait UserAuth return $oAccount; } - public function switchAccount(string $sEmail) : bool + public function switchAccount(Email $oEmail): bool { + $sEmail = $oEmail->GetEmail(); $this->Http()->ServerNoCache(); $oMainAccount = $this->getMainAccountFromToken(false); if ($sEmail && $oMainAccount && $this->GetCapa(Capa::ADDITIONAL_ACCOUNTS)) { $oAccount = null; - if ($oMainAccount->Email() !== $sEmail) { - $sEmail = \SnappyMail\IDN::emailToAscii($sEmail); + if ($oMainAccount->EmailAscii() !== $sEmail) { $aAccounts = $this->GetAccounts($oMainAccount); if (!isset($aAccounts[$sEmail])) { throw new ClientException(Notifications::AccountDoesNotExist); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php index 792cf6030..cc8fb0a95 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Model/Account.php @@ -28,6 +28,16 @@ abstract class Account implements \JsonSerializable return $this->sEmail; } + public function EmailAscii(): string + { + return \SnappyMail\IDN::emailToAscii($this->sEmail); + } + + public function EmailUtf8(): string + { + return \SnappyMail\IDN::emailToUtf8($this->sEmail); + } + public function Name(): string { return $this->sName; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php index 00e2c18fd..ed0009b0d 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/AddressBook/PdoAddressBook.php @@ -1022,7 +1022,7 @@ class PdoAddressBook $aEmailsToCreate = \array_filter($aEmailsObjects, function ($oItem) use ($aExists, &$aEmailsToUpdate) { if ($oItem) { - $sEmail = \trim($oItem->GetEmail(true)); + $sEmail = $oItem->GetEmailUtf8(); if (\strlen($sEmail)) { $aEmailsToUpdate[] = $sEmail; return !\in_array(\mb_strtolower($sEmail), $aExists); @@ -1033,7 +1033,7 @@ class PdoAddressBook } else { foreach ($aEmailsObjects as $oItem) { if ($oItem) { - $sEmailUpdate = \trim($oItem->GetEmail(true)); + $sEmailUpdate = $oItem->GetEmailUtf8(); if (\strlen($sEmailUpdate)) { $aEmailsToUpdate[] = $sEmailUpdate; } @@ -1048,7 +1048,7 @@ class PdoAddressBook $oVCard = new VCard; $bValid = false; if ('' !== \trim($oEmail->GetEmail())) { - $oVCard->add('EMAIL', \trim($oEmail->GetEmail(true))); + $oVCard->add('EMAIL', $oEmail->GetEmailUtf8()); $bValid = true; } if ('' !== \trim($oEmail->GetDisplayName())) {