mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-11-03 19:08:50 +03:00
Improved handling of Internationalized Domain Names in punycode
This commit is contained in:
parent
fd54796710
commit
696a2bbd3c
45 changed files with 661 additions and 236 deletions
|
|
@ -409,13 +409,27 @@ abstract class Utils
|
|||
return \trim($sValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use getEmailAddressLocalPart
|
||||
*/
|
||||
public static function GetAccountNameFromEmail(string $sEmail) : string
|
||||
{
|
||||
return static::getEmailAddressLocalPart($sEmail);
|
||||
}
|
||||
public static function getEmailAddressLocalPart(string $sEmail) : string
|
||||
{
|
||||
$iPos = \strrpos($sEmail, '@');
|
||||
return (false === $iPos) ? $sEmail : \substr($sEmail, 0, $iPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use getEmailAddressDomain
|
||||
*/
|
||||
public static function GetDomainFromEmail(string $sEmail) : string
|
||||
{
|
||||
return static::getEmailAddressDomain($sEmail);
|
||||
}
|
||||
public static function getEmailAddressDomain(string $sEmail) : string
|
||||
{
|
||||
$iPos = \strrpos($sEmail, '@');
|
||||
return (false === $iPos) ? '' : \substr($sEmail, $iPos + 1);
|
||||
|
|
@ -676,10 +690,12 @@ abstract class Utils
|
|||
}
|
||||
|
||||
/**
|
||||
* Converts xn--du8h.snappymail.eu to 📧.snappymail.eu
|
||||
* @deprecated
|
||||
*/
|
||||
public static function IdnToUtf8(string $sStr) : string
|
||||
{
|
||||
$trace = \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1];
|
||||
\trigger_error("Deprecated function IdnToAscii called at {$trace['file']}#{$trace['line']}", \E_USER_DEPRECATED);
|
||||
if (\preg_match('/(^|\.|@)xn--/i', $sStr)) {
|
||||
try
|
||||
{
|
||||
|
|
@ -691,10 +707,12 @@ abstract class Utils
|
|||
}
|
||||
|
||||
/**
|
||||
* Converts 📧.snappymail.eu to xn--du8h.snappymail.eu
|
||||
* @deprecated
|
||||
*/
|
||||
public static function IdnToAscii(string $sStr, bool $bLowerCase = false) : string
|
||||
{
|
||||
$trace = \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1];
|
||||
\trigger_error("Deprecated function IdnToAscii called at {$trace['file']}#{$trace['line']}", \E_USER_DEPRECATED);
|
||||
$aParts = \explode('@', $sStr);
|
||||
$sDomain = \array_pop($aParts);
|
||||
if (\strlen($sDomain) && \preg_match('/[^\x20-\x7E]/', $sDomain)) {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
public function Hash() : string
|
||||
{
|
||||
return \md5('ImapClientHash/'.
|
||||
$this->Settings->Login . '@' .
|
||||
$this->Settings->username . '@' .
|
||||
$this->Settings->host . ':' .
|
||||
$this->Settings->port
|
||||
);
|
||||
|
|
@ -110,8 +110,8 @@ class ImapClient extends \MailSo\Net\NetClient
|
|||
return $this;
|
||||
}
|
||||
|
||||
$sLogin = \MailSo\Base\Utils::IdnToAscii(\MailSo\Base\Utils::Trim($oSettings->Login));
|
||||
$sPassword = $oSettings->Password;
|
||||
$sLogin = $oSettings->username;
|
||||
$sPassword = $oSettings->passphrase;
|
||||
|
||||
if (!\strlen($sLogin) || !\strlen($sPassword)) {
|
||||
$this->writeLogException(new \UnexpectedValueException, \LOG_ERR);
|
||||
|
|
|
|||
|
|
@ -17,8 +17,14 @@ namespace MailSo\Mime;
|
|||
*/
|
||||
class Email implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* display-name https://datatracker.ietf.org/doc/html/rfc2822#section-3.4
|
||||
*/
|
||||
private string $sDisplayName;
|
||||
|
||||
/**
|
||||
* addr-spec https://datatracker.ietf.org/doc/html/rfc2822#section-3.4.1
|
||||
*/
|
||||
private string $sEmail;
|
||||
|
||||
private string $sDkimStatus = Enumerations\DkimStatus::NONE;
|
||||
|
|
@ -32,8 +38,7 @@ class Email implements \JsonSerializable
|
|||
throw new \ValueError;
|
||||
}
|
||||
|
||||
$this->sEmail = \MailSo\Base\Utils::IdnToAscii(
|
||||
\MailSo\Base\Utils::Trim($sEmail), true);
|
||||
$this->sEmail = \SnappyMail\IDN::emailToAscii(\MailSo\Base\Utils::Trim($sEmail));
|
||||
|
||||
$this->sDisplayName = \MailSo\Base\Utils::Trim($sDisplayName);
|
||||
}
|
||||
|
|
@ -156,7 +161,7 @@ class Email implements \JsonSerializable
|
|||
|
||||
public function GetEmail(bool $bIdn = false) : string
|
||||
{
|
||||
return $bIdn ? \MailSo\Base\Utils::IdnToUtf8($this->sEmail) : $this->sEmail;
|
||||
return $bIdn ? \SnappyMail\IDN::emailToUtf8($this->sEmail) : $this->sEmail;
|
||||
}
|
||||
|
||||
public function GetDisplayName() : string
|
||||
|
|
@ -164,14 +169,14 @@ class Email implements \JsonSerializable
|
|||
return $this->sDisplayName;
|
||||
}
|
||||
|
||||
public function GetAccountName() : string
|
||||
public function getLocalPart() : string
|
||||
{
|
||||
return \MailSo\Base\Utils::GetAccountNameFromEmail($this->GetEmail(false));
|
||||
return \MailSo\Base\Utils::getEmailAddressLocalPart($this->sEmail);
|
||||
}
|
||||
|
||||
public function GetDomain(bool $bIdn = false) : string
|
||||
{
|
||||
return \MailSo\Base\Utils::GetDomainFromEmail($this->GetEmail($bIdn));
|
||||
return \MailSo\Base\Utils::getEmailAddressDomain($this->GetEmail($bIdn));
|
||||
}
|
||||
|
||||
public function SetDkimStatus(string $sDkimStatus)
|
||||
|
|
|
|||
|
|
@ -48,8 +48,9 @@ class ConnectSettings implements \JsonSerializable
|
|||
'PLAIN',
|
||||
'LOGIN'
|
||||
];
|
||||
public string $Login = '';
|
||||
private ?SensitiveString $Password = null;
|
||||
|
||||
private string $username = '';
|
||||
private ?SensitiveString $passphrase = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
|
@ -58,21 +59,27 @@ class ConnectSettings implements \JsonSerializable
|
|||
|
||||
public function __get(string $name)
|
||||
{
|
||||
if ('Password' === $name) {
|
||||
return $this->Password ? $this->Password->getValue() : '';
|
||||
$name = \strtolower($name);
|
||||
if ('passphrase' === $name || 'password' === $name) {
|
||||
return $this->passphrase ? $this->passphrase->getValue() : '';
|
||||
}
|
||||
if ('username' === $name || 'login' === $name) {
|
||||
return $this->username;
|
||||
}
|
||||
}
|
||||
|
||||
public function __set(string $name, $value)
|
||||
{
|
||||
if ('Password' === $name) {
|
||||
$this->Password = \is_string($value) ? new SensitiveString($value) : $value;
|
||||
public function __set(string $name,
|
||||
#[\SensitiveParameter]
|
||||
$value
|
||||
) {
|
||||
$name = \strtolower($name);
|
||||
if ('passphrase' === $name || 'password' === $name) {
|
||||
$this->passphrase = \is_string($value) ? new SensitiveString($value) : $value;
|
||||
}
|
||||
if ('username' === $name || 'login' === $name) {
|
||||
$this->username = \SnappyMail\IDN::emailToAscii($value);
|
||||
// $this->username = \SnappyMail\IDN::emailToAscii(\MailSo\Base\Utils::Trim($value));
|
||||
}
|
||||
}
|
||||
|
||||
public static function Host() : string
|
||||
{
|
||||
return \idn_to_ascii($this->host);
|
||||
}
|
||||
|
||||
public static function fromArray(array $aSettings) : self
|
||||
|
|
|
|||
|
|
@ -87,8 +87,8 @@ class SieveClient extends \MailSo\Net\NetClient
|
|||
return $this;
|
||||
}
|
||||
|
||||
$sLogin = $oSettings->Login;
|
||||
$sPassword = $oSettings->Password;
|
||||
$sLogin = $oSettings->username;
|
||||
$sPassword = $oSettings->passphrase;
|
||||
$sLoginAuthKey = '';
|
||||
if (!\strlen($sLogin) || !\strlen($sPassword)) {
|
||||
$this->writeLogException(new \InvalidArgumentException, \LOG_ERR);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
namespace MailSo\Smtp;
|
||||
|
||||
use MailSo\Net\Enumerations\ConnectionSecurityType;
|
||||
use SnappyMail\IDN;
|
||||
|
||||
/**
|
||||
* @category MailSo
|
||||
|
|
@ -127,8 +128,8 @@ class SmtpClient extends \MailSo\Net\NetClient
|
|||
return $this;
|
||||
}
|
||||
|
||||
$sLogin = \MailSo\Base\Utils::IdnToAscii(\MailSo\Base\Utils::Trim($oSettings->Login));
|
||||
$sPassword = $oSettings->Password;
|
||||
$sLogin = $oSettings->username;
|
||||
$sPassword = $oSettings->passphrase;
|
||||
|
||||
$type = '';
|
||||
foreach ($oSettings->SASLMechanisms as $sasl_type) {
|
||||
|
|
@ -227,9 +228,13 @@ class SmtpClient extends \MailSo\Net\NetClient
|
|||
*/
|
||||
public function MailFrom(string $sFrom, int $iSizeIfSupported = 0, bool $bDsn = false, bool $bRequireTLS = false) : self
|
||||
{
|
||||
$sFrom = \MailSo\Base\Utils::IdnToAscii(\MailSo\Base\Utils::Trim($sFrom), true);
|
||||
|
||||
// $sFrom = IDN::emailToAscii($sFrom);
|
||||
$sCmd = "FROM:<{$sFrom}>";
|
||||
// RFC 6531
|
||||
if ($this->hasCapability('SMTPUTF8')) {
|
||||
// $sFrom = IDN::emailToUtf8($sFrom);
|
||||
// $sCmd = "FROM:<{$sFrom}> SMTPUTF8";
|
||||
}
|
||||
|
||||
if (0 < $iSizeIfSupported && $this->hasCapability('SIZE')) {
|
||||
$sCmd .= ' SIZE='.$iSizeIfSupported;
|
||||
|
|
@ -243,18 +248,10 @@ class SmtpClient extends \MailSo\Net\NetClient
|
|||
// RFC 6152
|
||||
if ($this->hasCapability('8BITMIME')) {
|
||||
// $sCmd .= ' BODY=8BITMIME';
|
||||
// RFC 6531
|
||||
if ($this->hasCapability('SMTPUTF8')) {
|
||||
// $sCmd .= ' SMTPUTF8';
|
||||
}
|
||||
}
|
||||
// RFC 3030
|
||||
else if ($this->hasCapability('BINARYMIME')) {
|
||||
// $sCmd .= ' BODY=BINARYMIME';
|
||||
// RFC 6531
|
||||
if ($this->hasCapability('SMTPUTF8')) {
|
||||
// $sCmd .= ' SMTPUTF8';
|
||||
}
|
||||
}
|
||||
|
||||
// RFC 8689
|
||||
|
|
@ -281,7 +278,7 @@ class SmtpClient extends \MailSo\Net\NetClient
|
|||
$this->writeLogException(new \MailSo\RuntimeException('No sender reverse path has been supplied'), \LOG_ERR);
|
||||
}
|
||||
|
||||
$sTo = \MailSo\Base\Utils::IdnToAscii(\MailSo\Base\Utils::Trim($sTo), true);
|
||||
// $sTo = IDN::emailToAscii($sTo);
|
||||
|
||||
$sCmd = 'TO:<'.$sTo.'>';
|
||||
|
||||
|
|
@ -413,18 +410,16 @@ class SmtpClient extends \MailSo\Net\NetClient
|
|||
*/
|
||||
public function Vrfy(string $sUser) : self
|
||||
{
|
||||
$sUser = \MailSo\Base\Utils::Trim($sUser);
|
||||
/*
|
||||
// RFC 6531
|
||||
if ($this->hasCapability('SMTPUTF8')) {
|
||||
$this->sendRequestWithCheck('VRFY '
|
||||
. \MailSo\Base\Utils::IdnToUtf8(\MailSo\Base\Utils::Trim($sUser))
|
||||
. ' SMTPUTF8',
|
||||
$this->sendRequestWithCheck('VRFY ' . IDN::emailToUtf8($sUser) . ' SMTPUTF8',
|
||||
array(250, 251, 252),
|
||||
);
|
||||
} else {
|
||||
*/
|
||||
$this->sendRequestWithCheck(
|
||||
'VRFY ' . \MailSo\Base\Utils::IdnToAscii(\MailSo\Base\Utils::Trim($sUser)),
|
||||
$this->sendRequestWithCheck('VRFY ' . IDN::emailToAscii($sUser),
|
||||
array(250, 251, 252)
|
||||
);
|
||||
return $this;
|
||||
|
|
@ -442,16 +437,14 @@ class SmtpClient extends \MailSo\Net\NetClient
|
|||
/*
|
||||
public function Expn(string $sUser) : self
|
||||
{
|
||||
$sUser = \MailSo\Base\Utils::Trim($sUser);
|
||||
// RFC 6531
|
||||
if ($this->hasCapability('SMTPUTF8')) {
|
||||
$this->sendRequestWithCheck('EXPN '
|
||||
. \MailSo\Base\Utils::IdnToUtf8(\MailSo\Base\Utils::Trim($sUser))
|
||||
. ' SMTPUTF8',
|
||||
$this->sendRequestWithCheck('EXPN ' . IDN::emailToUtf8($sUser) . ' SMTPUTF8',
|
||||
array(250, 251, 252)
|
||||
);
|
||||
} else {
|
||||
$this->sendRequestWithCheck('EXPN '
|
||||
. \MailSo\Base\Utils::IdnToAscii(\MailSo\Base\Utils::Trim($sUser)),
|
||||
$this->sendRequestWithCheck('EXPN ' . IDN::emailToAscii($sUser),
|
||||
array(250, 251, 252),
|
||||
);
|
||||
return $this;
|
||||
|
|
|
|||
|
|
@ -326,10 +326,10 @@ class Actions
|
|||
$sEmail = $oAccount->Email();
|
||||
|
||||
$sLine = \str_replace('{user:email}', $sEmail, $sLine);
|
||||
$sLine = \str_replace('{user:login}', \MailSo\Base\Utils::GetAccountNameFromEmail($sEmail), $sLine);
|
||||
$sLine = \str_replace('{user:domain}', \MailSo\Base\Utils::GetDomainFromEmail($sEmail), $sLine);
|
||||
$sLine = \str_replace('{user:login}', \MailSo\Base\Utils::getEmailAddressLocalPart($sEmail), $sLine);
|
||||
$sLine = \str_replace('{user:domain}', \MailSo\Base\Utils::getEmailAddressDomain($sEmail), $sLine);
|
||||
$sLine = \str_replace('{user:domain-clear}',
|
||||
\MailSo\Base\Utils::GetClearDomainName(\MailSo\Base\Utils::GetDomainFromEmail($sEmail)),
|
||||
\MailSo\Base\Utils::GetClearDomainName(\MailSo\Base\Utils::getEmailAddressDomain($sEmail)),
|
||||
$sLine);
|
||||
}
|
||||
}
|
||||
|
|
@ -533,17 +533,17 @@ class Actions
|
|||
return $this->oPlugins;
|
||||
}
|
||||
|
||||
protected function LoggerAuthHelper(?Model\Account $oAccount, string $sLogin, bool $admin = false): void
|
||||
protected function LoggerAuthHelper(?Model\Account $oAccount, string $sLogin = '', bool $admin = false): void
|
||||
{
|
||||
if ($sLogin) {
|
||||
$sHost = $admin ? $this->Http()->GetHost(true, true) : \MailSo\Base\Utils::GetDomainFromEmail($sLogin);
|
||||
$sHost = $admin ? $this->Http()->GetHost(true, true) : \MailSo\Base\Utils::getEmailAddressDomain($sLogin);
|
||||
$aAdditionalParams = array(
|
||||
'{imap:login}' => $sLogin,
|
||||
'{imap:host}' => $sHost,
|
||||
'{smtp:login}' => $sLogin,
|
||||
'{smtp:host}' => $sHost,
|
||||
'{user:email}' => $sLogin,
|
||||
'{user:login}' => $admin ? $sLogin : \MailSo\Base\Utils::GetAccountNameFromEmail($sLogin),
|
||||
'{user:login}' => $admin ? $sLogin : \MailSo\Base\Utils::getEmailAddressLocalPart($sLogin),
|
||||
'{user:domain}' => $sHost,
|
||||
);
|
||||
} else {
|
||||
|
|
@ -605,43 +605,43 @@ class Actions
|
|||
} else {
|
||||
$oAccount = $this->getAccountFromToken(false);
|
||||
if ($oAccount) {
|
||||
$aResult = \array_merge($aResult, [
|
||||
'Auth' => true,
|
||||
'Email' => \MailSo\Base\Utils::IdnToUtf8($oAccount->Email()),
|
||||
'accountHash' => $oAccount->Hash(),
|
||||
'accountSignMe' => isset($_COOKIE[self::AUTH_SIGN_ME_TOKEN_KEY]),
|
||||
|
||||
'contactsAllowed' => $this->AddressBookProvider($oAccount)->IsActive(),
|
||||
|
||||
'allowSpellcheck' => $oConfig->Get('defaults', 'allow_spellcheck', false),
|
||||
'ViewHTML' => (bool) $oConfig->Get('defaults', 'view_html', true),
|
||||
'ViewImages' => $oConfig->Get('defaults', 'view_images', 'ask'),
|
||||
'ViewImagesWhitelist' => '',
|
||||
'RemoveColors' => (bool) $oConfig->Get('defaults', 'remove_colors', false),
|
||||
'AllowStyles' => false,
|
||||
'ListInlineAttachments' => false,
|
||||
'CollapseBlockquotes' => $oConfig->Get('defaults', 'collapse_blockquotes', true),
|
||||
'MaxBlockquotesLevel' => 0,
|
||||
'simpleAttachmentsList' => false,
|
||||
'listGrouped' => $oConfig->Get('defaults', 'mail_list_grouped', false),
|
||||
'MessagesPerPage' => (int) $oConfig->Get('webmail', 'messages_per_page', 25),
|
||||
'messageNewWindow' => false,
|
||||
'messageReadAuto' => true, // (bool) $oConfig->Get('webmail', 'message_read_auto', true),
|
||||
'MessageReadDelay' => (int) $oConfig->Get('webmail', 'message_read_delay', 5),
|
||||
'MsgDefaultAction' => (int) $oConfig->Get('defaults', 'msg_default_action', 1),
|
||||
'SoundNotification' => true,
|
||||
'NotificationSound' => 'new-mail',
|
||||
'DesktopNotifications' => true,
|
||||
'Layout' => (int) $oConfig->Get('defaults', 'view_layout', Enumerations\Layout::SIDE_PREVIEW),
|
||||
'EditorDefaultType' => \str_replace('Forced', '', $oConfig->Get('defaults', 'view_editor_type', '')),
|
||||
'editorWysiwyg' => 'Squire',
|
||||
'UseCheckboxesInList' => (bool) $oConfig->Get('defaults', 'view_use_checkboxes', true),
|
||||
'showNextMessage' => (bool) $oConfig->Get('defaults', 'view_show_next_message', false),
|
||||
'AutoLogout' => (int) $oConfig->Get('defaults', 'autologout', 30),
|
||||
'AllowDraftAutosave' => (bool) $oConfig->Get('defaults', 'allow_draft_autosave', true),
|
||||
'ContactsAutosave' => (bool) $oConfig->Get('defaults', 'contacts_autosave', true),
|
||||
'sieveAllowFileintoInbox' => (bool)$oConfig->Get('labs', 'sieve_allow_fileinto_inbox', false)
|
||||
]);
|
||||
$aResult = \array_merge(
|
||||
$aResult,
|
||||
[
|
||||
'Auth' => true,
|
||||
'accountSignMe' => isset($_COOKIE[self::AUTH_SIGN_ME_TOKEN_KEY]),
|
||||
'allowSpellcheck' => $oConfig->Get('defaults', 'allow_spellcheck', false),
|
||||
'ViewHTML' => (bool) $oConfig->Get('defaults', 'view_html', true),
|
||||
'ViewImages' => $oConfig->Get('defaults', 'view_images', 'ask'),
|
||||
'ViewImagesWhitelist' => '',
|
||||
'RemoveColors' => (bool) $oConfig->Get('defaults', 'remove_colors', false),
|
||||
'AllowStyles' => false,
|
||||
'ListInlineAttachments' => false,
|
||||
'CollapseBlockquotes' => $oConfig->Get('defaults', 'collapse_blockquotes', true),
|
||||
'MaxBlockquotesLevel' => 0,
|
||||
'simpleAttachmentsList' => false,
|
||||
'listGrouped' => $oConfig->Get('defaults', 'mail_list_grouped', false),
|
||||
'MessagesPerPage' => (int) $oConfig->Get('webmail', 'messages_per_page', 25),
|
||||
'messageNewWindow' => false,
|
||||
'messageReadAuto' => true, // (bool) $oConfig->Get('webmail', 'message_read_auto', true),
|
||||
'MessageReadDelay' => (int) $oConfig->Get('webmail', 'message_read_delay', 5),
|
||||
'MsgDefaultAction' => (int) $oConfig->Get('defaults', 'msg_default_action', 1),
|
||||
'SoundNotification' => true,
|
||||
'NotificationSound' => 'new-mail',
|
||||
'DesktopNotifications' => true,
|
||||
'Layout' => (int) $oConfig->Get('defaults', 'view_layout', Enumerations\Layout::SIDE_PREVIEW),
|
||||
'EditorDefaultType' => \str_replace('Forced', '', $oConfig->Get('defaults', 'view_editor_type', '')),
|
||||
'editorWysiwyg' => 'Squire',
|
||||
'UseCheckboxesInList' => (bool) $oConfig->Get('defaults', 'view_use_checkboxes', true),
|
||||
'showNextMessage' => (bool) $oConfig->Get('defaults', 'view_show_next_message', false),
|
||||
'AutoLogout' => (int) $oConfig->Get('defaults', 'autologout', 30),
|
||||
'AllowDraftAutosave' => (bool) $oConfig->Get('defaults', 'allow_draft_autosave', true),
|
||||
'ContactsAutosave' => (bool) $oConfig->Get('defaults', 'contacts_autosave', true),
|
||||
'sieveAllowFileintoInbox' => (bool)$oConfig->Get('labs', 'sieve_allow_fileinto_inbox', false)
|
||||
],
|
||||
// MainAccount or AdditionalAccount
|
||||
$this->getAccountData($oAccount)
|
||||
);
|
||||
|
||||
$aAttachmentsActions = array();
|
||||
if ($this->GetCapa(Capa::ATTACHMENTS_ACTIONS)) {
|
||||
|
|
@ -677,13 +677,10 @@ class Actions
|
|||
|
||||
$mMailToData = Utils::DecodeKeyValuesQ($sToken);
|
||||
if (!empty($mMailToData['MailTo']) && 'MailTo' === $mMailToData['MailTo'] && !empty($mMailToData['To'])) {
|
||||
$aResult['mailToEmail'] = \MailSo\Base\Utils::IdnToUtf8($mMailToData['To']);
|
||||
$aResult['mailToEmail'] = \SnappyMail\IDN::emailToUtf8($mMailToData['To']);
|
||||
}
|
||||
}
|
||||
|
||||
// MainAccount or AdditionalAccount
|
||||
$aResult = \array_merge($aResult, $this->getAccountData($oAccount));
|
||||
|
||||
// MainAccount
|
||||
$oSettings = $this->SettingsProvider()->Load($oAccount);
|
||||
if ($oSettings instanceof Settings) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ use RainLoop\Notifications;
|
|||
use RainLoop\Providers\Identities;
|
||||
use RainLoop\Providers\Storage\Enumerations\StorageType;
|
||||
use RainLoop\Utils;
|
||||
use SnappyMail\IDN;
|
||||
|
||||
trait Accounts
|
||||
{
|
||||
|
|
@ -85,7 +86,7 @@ trait Accounts
|
|||
$sName = \trim($this->GetActionParam('name', ''));
|
||||
$bNew = !empty($this->GetActionParam('new', 1));
|
||||
|
||||
$sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail, true);
|
||||
$sEmail = IDN::emailToAscii($sEmail);
|
||||
if ($bNew && ($oMainAccount->Email() === $sEmail || isset($aAccounts[$sEmail]))) {
|
||||
throw new ClientException(Notifications::AccountAlreadyExists);
|
||||
} else if (!$bNew && !isset($aAccounts[$sEmail])) {
|
||||
|
|
@ -109,7 +110,7 @@ trait Accounts
|
|||
|
||||
protected function loadAdditionalAccountImapClient(string $sEmail): \MailSo\Imap\ImapClient
|
||||
{
|
||||
$sEmail = \MailSo\Base\Utils::IdnToAscii(\trim($sEmail), true);
|
||||
$sEmail = IDN::emailToAscii($sEmail);
|
||||
if (!\strlen($sEmail)) {
|
||||
throw new ClientException(Notifications::AccountDoesNotExist);
|
||||
}
|
||||
|
|
@ -173,7 +174,7 @@ trait Accounts
|
|||
}
|
||||
|
||||
$sEmailToDelete = \trim($this->GetActionParam('emailToDelete', ''));
|
||||
$sEmailToDelete = \MailSo\Base\Utils::IdnToAscii($sEmailToDelete, true);
|
||||
$sEmailToDelete = IDN::emailToAscii($sEmailToDelete);
|
||||
|
||||
$aAccounts = $this->GetAccounts($oMainAccount);
|
||||
|
||||
|
|
@ -198,6 +199,7 @@ trait Accounts
|
|||
{
|
||||
$oConfig = $this->Config();
|
||||
$aResult = [
|
||||
// 'Email' => IDN::emailToUtf8($oAccount->Email()),
|
||||
'Email' => $oAccount->Email(),
|
||||
'accountHash' => $oAccount->Hash(),
|
||||
'mainEmail' => \RainLoop\Api::Actions()->getMainAccountFromToken()->Email(),
|
||||
|
|
@ -330,7 +332,7 @@ trait Accounts
|
|||
return $this->DefaultResponse(array(
|
||||
'Accounts' => \array_values(\array_map(function($value){
|
||||
return [
|
||||
'email' => \MailSo\Base\Utils::IdnToUtf8($value['email'] ?? $value[1]),
|
||||
'email' => IDN::emailToUtf8($value['email'] ?? $value[1]),
|
||||
'name' => $value['name'] ?? ''
|
||||
];
|
||||
},
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ trait AdminDomains
|
|||
$sLogin = '';
|
||||
$this->resolveLoginCredentials($sEmail, $oPassword, $sLogin);
|
||||
$oDomain = \str_contains($sEmail, '@')
|
||||
? $this->DomainProvider()->Load(\MailSo\Base\Utils::GetDomainFromEmail($sEmail), true)
|
||||
? $this->DomainProvider()->Load(\MailSo\Base\Utils::getEmailAddressDomain($sEmail), true)
|
||||
: null;
|
||||
return $this->DefaultResponse(array(
|
||||
'email' => $sEmail,
|
||||
|
|
@ -111,8 +111,8 @@ trait AdminDomains
|
|||
'connectCapa' => \array_values(\array_diff($oImapClient->Capabilities(), ['STARTTLS']))
|
||||
];
|
||||
if (!empty($aAuth['user'])) {
|
||||
$oSettings->Login = $aAuth['user'];
|
||||
$oSettings->Password = $aAuth['pass'];
|
||||
$oSettings->username = $aAuth['user'];
|
||||
$oSettings->passphrase = $aAuth['pass'];
|
||||
$oImapClient->Login($oSettings);
|
||||
$mImapResult['authCapa'] = \array_values(\array_unique(\array_map(function($n){
|
||||
return \str_starts_with($n, 'THREAD=') ? 'THREAD' : $n;
|
||||
|
|
@ -156,8 +156,8 @@ trait AdminDomains
|
|||
];
|
||||
|
||||
if (!empty($aAuth['user'])) {
|
||||
$oSettings->Login = $aAuth['user'];
|
||||
$oSettings->Password = $aAuth['pass'];
|
||||
$oSettings->username = $aAuth['user'];
|
||||
$oSettings->passphrase = $aAuth['pass'];
|
||||
$oSmtpClient->Login($oSettings);
|
||||
$mSmtpResult['authCapa'] = $oSmtpClient->Capability();
|
||||
}
|
||||
|
|
@ -192,8 +192,8 @@ trait AdminDomains
|
|||
];
|
||||
|
||||
if (!empty($aAuth['user'])) {
|
||||
$oSettings->Login = $aAuth['user'];
|
||||
$oSettings->Password = $aAuth['pass'];
|
||||
$oSettings->username = $aAuth['user'];
|
||||
$oSettings->passphrase = $aAuth['pass'];
|
||||
$oSieveClient->Login($oSettings);
|
||||
$mSieveResult['authCapa'] = $oSieveClient->Capability();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -762,8 +762,7 @@ trait Messages
|
|||
$this->Plugins()->RunHook('filter.smtp-from', array($oAccount, $oMessage, &$sFrom));
|
||||
|
||||
$aHiddenRcpt = array();
|
||||
if ($bAddHiddenRcpt)
|
||||
{
|
||||
if ($bAddHiddenRcpt) {
|
||||
$this->Plugins()->RunHook('filter.smtp-hidden-rcpt', array($oAccount, $oMessage, &$aHiddenRcpt));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,26 +154,23 @@ trait UserAuth
|
|||
$oMainAccount = $this->getMainAccountFromToken(false);
|
||||
if ($sEmail && $oMainAccount && $this->GetCapa(Capa::ADDITIONAL_ACCOUNTS)) {
|
||||
$oAccount = null;
|
||||
if ($oMainAccount->Email() === $sEmail) {
|
||||
$this->SetAdditionalAuthToken($oAccount);
|
||||
return true;
|
||||
}
|
||||
$sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail);
|
||||
$aAccounts = $this->GetAccounts($oMainAccount);
|
||||
if (!isset($aAccounts[$sEmail])) {
|
||||
throw new ClientException(Notifications::AccountDoesNotExist);
|
||||
}
|
||||
$oAccount = AdditionalAccount::NewInstanceFromTokenArray(
|
||||
$this, $aAccounts[$sEmail]
|
||||
);
|
||||
if (!$oAccount) {
|
||||
throw new ClientException(Notifications::AccountSwitchFailed);
|
||||
}
|
||||
|
||||
// Test the login
|
||||
$oImapClient = new \MailSo\Imap\ImapClient;
|
||||
$this->imapConnect($oAccount, false, $oImapClient);
|
||||
if ($oMainAccount->Email() !== $sEmail) {
|
||||
$sEmail = \SnappyMail\IDN::emailToAscii($sEmail);
|
||||
$aAccounts = $this->GetAccounts($oMainAccount);
|
||||
if (!isset($aAccounts[$sEmail])) {
|
||||
throw new ClientException(Notifications::AccountDoesNotExist);
|
||||
}
|
||||
$oAccount = AdditionalAccount::NewInstanceFromTokenArray(
|
||||
$this, $aAccounts[$sEmail]
|
||||
);
|
||||
if (!$oAccount) {
|
||||
throw new ClientException(Notifications::AccountSwitchFailed);
|
||||
}
|
||||
|
||||
// Test the login
|
||||
$oImapClient = new \MailSo\Imap\ImapClient;
|
||||
$this->imapConnect($oAccount, false, $oImapClient);
|
||||
}
|
||||
$this->SetAdditionalAuthToken($oAccount);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ abstract class Api
|
|||
public static function ClearUserData(string $sEmail) : bool
|
||||
{
|
||||
if (\strlen($sEmail)) {
|
||||
$sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail);
|
||||
$sEmail = \SnappyMail\IDN::emailToAscii($sEmail);
|
||||
|
||||
$oStorageProvider = static::Actions()->StorageProvider();
|
||||
if ($oStorageProvider && $oStorageProvider->IsActive()) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ abstract class Account implements \JsonSerializable
|
|||
|
||||
private string $sSmtpLogin = '';
|
||||
|
||||
private ?SensitiveString $sSmtpPassword = null;
|
||||
private ?SensitiveString $oSmtpPassword = null;
|
||||
|
||||
private Domain $oDomain;
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ abstract class Account implements \JsonSerializable
|
|||
public function IncLogin() : string
|
||||
{
|
||||
return $this->oDomain->ImapSettings()->shortLogin
|
||||
? \MailSo\Base\Utils::GetAccountNameFromEmail($this->sLogin)
|
||||
? \MailSo\Base\Utils::getEmailAddressLocalPart($this->sLogin)
|
||||
: $this->sLogin;
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ abstract class Account implements \JsonSerializable
|
|||
{
|
||||
$sSmtpLogin = $this->sSmtpLogin ?: $this->sLogin;
|
||||
return $this->oDomain->SmtpSettings()->shortLogin
|
||||
? \MailSo\Base\Utils::GetAccountNameFromEmail($sSmtpLogin)
|
||||
? \MailSo\Base\Utils::getEmailAddressLocalPart($sSmtpLogin)
|
||||
: $sSmtpLogin;
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ abstract class Account implements \JsonSerializable
|
|||
string $sPassword
|
||||
) : void
|
||||
{
|
||||
$this->sSmtpPassword = new SensitiveString($sPassword);
|
||||
$this->oSmtpPassword = new SensitiveString($sPassword);
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
|
|
@ -90,10 +90,10 @@ abstract class Account implements \JsonSerializable
|
|||
'pass' => $this->IncPassword(),
|
||||
'name' => $this->sName
|
||||
];
|
||||
if ($this->sSmtpLogin && $this->sSmtpPassword) {
|
||||
if ($this->sSmtpLogin && $this->oSmtpPassword) {
|
||||
$result['smtp'] = [
|
||||
'user' => $this->sSmtpLogin,
|
||||
'pass' => $this->sSmtpPassword->getValue()
|
||||
'pass' => $this->oSmtpPassword->getValue()
|
||||
];
|
||||
}
|
||||
return $result;
|
||||
|
|
@ -106,13 +106,13 @@ abstract class Account implements \JsonSerializable
|
|||
{
|
||||
$oAccount = null;
|
||||
if ($sEmail && $sLogin && \strlen($oPassword)) {
|
||||
$oDomain = $oActions->DomainProvider()->Load(\MailSo\Base\Utils::GetDomainFromEmail($sEmail), true);
|
||||
$oDomain = $oActions->DomainProvider()->Load(\MailSo\Base\Utils::getEmailAddressDomain($sEmail), true);
|
||||
if ($oDomain) {
|
||||
if ($oDomain->ValidateWhiteList($sEmail, $sLogin)) {
|
||||
$oAccount = new static;
|
||||
|
||||
$oAccount->sEmail = \MailSo\Base\Utils::IdnToAscii($sEmail, true);
|
||||
$oAccount->sLogin = \MailSo\Base\Utils::IdnToAscii($sLogin);
|
||||
$oAccount->sEmail = \SnappyMail\IDN::emailToAscii($sEmail);
|
||||
$oAccount->sLogin = \SnappyMail\IDN::emailToAscii($sLogin);
|
||||
$oAccount->SetPassword($oPassword);
|
||||
$oAccount->oDomain = $oDomain;
|
||||
|
||||
|
|
@ -143,18 +143,11 @@ abstract class Account implements \JsonSerializable
|
|||
if (empty($aAccount[0]) || 'account' != $aAccount[0] || 7 > \count($aAccount)) {
|
||||
return [];
|
||||
}
|
||||
$aResult = [
|
||||
return [
|
||||
'email' => $aAccount[1] ?: '',
|
||||
'login' => $aAccount[2] ?: '',
|
||||
'pass' => $aAccount[3] ?: ''
|
||||
];
|
||||
if ($aAccount[5] && $aAccount[6]) {
|
||||
$aResult['proxy'] = [
|
||||
'user' => $aAccount[5],
|
||||
'pass' => $aAccount[6]
|
||||
];
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
public static function NewInstanceFromTokenArray(
|
||||
|
|
@ -190,7 +183,7 @@ abstract class Account implements \JsonSerializable
|
|||
{
|
||||
$oSettings = $this->Domain()->ImapSettings();
|
||||
$oSettings->timeout = \max($oSettings->timeout, (int) $oConfig->Get('imap', 'timeout', $oSettings->timeout));
|
||||
$oSettings->Login = $this->IncLogin();
|
||||
$oSettings->username = $this->IncLogin();
|
||||
|
||||
$oSettings->expunge_all_on_delete |= !!$oConfig->Get('imap', 'use_expunge_all_on_delete', false);
|
||||
$oSettings->fast_simple_search = !(!$oSettings->fast_simple_search || !$oConfig->Get('imap', 'message_list_fast_simple_search', true));
|
||||
|
|
@ -207,14 +200,14 @@ abstract class Account implements \JsonSerializable
|
|||
$oImapClient->Connect($oSettings);
|
||||
$oPlugins->RunHook('imap.after-connect', array($this, $oImapClient, $oSettings));
|
||||
|
||||
$oSettings->Password = $this->oPassword;
|
||||
$oSettings->passphrase = $this->oPassword;
|
||||
return $this->netClientLogin($oImapClient, $oPlugins);
|
||||
}
|
||||
|
||||
public function SmtpConnectAndLogin(\RainLoop\Plugins\Manager $oPlugins, \MailSo\Smtp\SmtpClient $oSmtpClient) : bool
|
||||
{
|
||||
$oSettings = $this->Domain()->SmtpSettings();
|
||||
$oSettings->Login = $this->OutLogin();
|
||||
$oSettings->username = $this->OutLogin();
|
||||
$oSettings->Ehlo = \MailSo\Smtp\SmtpClient::EhloHelper();
|
||||
|
||||
$oSmtpClient->Settings = $oSettings;
|
||||
|
|
@ -227,18 +220,18 @@ abstract class Account implements \JsonSerializable
|
|||
$oSmtpClient->Connect($oSettings);
|
||||
$oPlugins->RunHook('smtp.after-connect', array($this, $oSmtpClient, $oSettings));
|
||||
/*
|
||||
if ($this->oDomain->OutAskCredentials() && !($this->sSmtpPassword && $this->sSmtpLogin)) {
|
||||
if ($this->oDomain->OutAskCredentials() && !($this->oSmtpPassword && $this->sSmtpLogin)) {
|
||||
throw new RequireCredentialsException
|
||||
}
|
||||
*/
|
||||
$oSettings->Password = $this->sSmtpPassword ?: $this->oPassword;
|
||||
$oSettings->passphrase = $this->oSmtpPassword ?: $this->oPassword;
|
||||
return $this->netClientLogin($oSmtpClient, $oPlugins);
|
||||
}
|
||||
|
||||
public function SieveConnectAndLogin(\RainLoop\Plugins\Manager $oPlugins, \MailSo\Sieve\SieveClient $oSieveClient, \RainLoop\Config\Application $oConfig)
|
||||
{
|
||||
$oSettings = $this->Domain()->SieveSettings();
|
||||
$oSettings->Login = $this->IncLogin();
|
||||
$oSettings->username = $this->IncLogin();
|
||||
|
||||
$oSieveClient->Settings = $oSettings;
|
||||
|
||||
|
|
@ -246,7 +239,7 @@ abstract class Account implements \JsonSerializable
|
|||
$oSieveClient->Connect($oSettings);
|
||||
$oPlugins->RunHook('sieve.after-connect', array($this, $oSieveClient, $oSettings));
|
||||
|
||||
$oSettings->Password = $this->oPassword;
|
||||
$oSettings->passphrase = $this->oPassword;
|
||||
return $this->netClientLogin($oSieveClient, $oPlugins);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class AdditionalAccount extends Account
|
|||
{
|
||||
public function ParentEmail() : string
|
||||
{
|
||||
return \trim(\MailSo\Base\Utils::IdnToAscii(\RainLoop\Api::Actions()->getMainAccountFromToken()->Email(), true));
|
||||
return \SnappyMail\IDN::emailToAscii(\RainLoop\Api::Actions()->getMainAccountFromToken()->Email());
|
||||
}
|
||||
|
||||
public function Hash() : string
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ class Domain implements \JsonSerializable
|
|||
if ($sW) {
|
||||
$sEmail = \mb_strtolower($sEmail);
|
||||
$sLogin = \mb_strtolower($sLogin);
|
||||
$sUserPart = \MailSo\Base\Utils::GetAccountNameFromEmail($sLogin ?: $sEmail);
|
||||
$sUserPart = \MailSo\Base\Utils::getEmailAddressLocalPart($sLogin ?: $sEmail);
|
||||
$sItem = \strtok($sW, " ;,\n");
|
||||
while (false !== $sItem) {
|
||||
$sItem = \mb_strtolower(\idn_to_ascii(\trim($sItem)));
|
||||
|
|
@ -192,17 +192,17 @@ class Domain implements \JsonSerializable
|
|||
if (\strlen($sName) && \strlen($aDomain['imap_host'])) {
|
||||
$oDomain = new self($sName);
|
||||
|
||||
$oDomain->IMAP->host = \idn_to_utf8($aDomain['imap_host']);
|
||||
$oDomain->IMAP->host = $aDomain['imap_host'];
|
||||
$oDomain->IMAP->port = (int) $aDomain['imap_port'];
|
||||
$oDomain->IMAP->type = self::StrConnectionSecurityTypeToCons($aDomain['imap_secure'] ?? '');
|
||||
$oDomain->IMAP->shortLogin = !empty($aDomain['imap_short_login']);
|
||||
|
||||
$oDomain->Sieve->enabled = !empty($aDomain['sieve_use']);
|
||||
$oDomain->Sieve->host = \idn_to_utf8($aDomain['sieve_host']);
|
||||
$oDomain->Sieve->host = $aDomain['sieve_host'];
|
||||
$oDomain->Sieve->port = (int) ($aDomain['sieve_port'] ?? 4190);;
|
||||
$oDomain->Sieve->type = self::StrConnectionSecurityTypeToCons($aDomain['sieve_secure'] ?? '');
|
||||
|
||||
$oDomain->SMTP->host = \idn_to_utf8($aDomain['smtp_host']);
|
||||
$oDomain->SMTP->host = $aDomain['smtp_host'];
|
||||
$oDomain->SMTP->port = (int) ($aDomain['smtp_port'] ?? 25);
|
||||
$oDomain->SMTP->type = self::StrConnectionSecurityTypeToCons($aDomain['smtp_secure'] ?? '');
|
||||
$oDomain->SMTP->shortLogin = !empty($aDomain['smtp_short_login']);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace RainLoop\Model;
|
||||
|
||||
use MailSo\Base\Utils;
|
||||
use SnappyMail\SensitiveString;
|
||||
|
||||
class Identity implements \JsonSerializable
|
||||
|
|
@ -102,7 +101,7 @@ class Identity implements \JsonSerializable
|
|||
if (!empty($aData['Email'])) {
|
||||
$this->sId = !empty($aData['Id']) ? $aData['Id'] : '';
|
||||
$this->sLabel = isset($aData['Label']) ? $aData['Label'] : '';
|
||||
$this->sEmail = $bJson ? Utils::IdnToAscii($aData['Email'], true) : $aData['Email'];
|
||||
$this->sEmail = $bJson ? \SnappyMail\IDN::emailToAscii($aData['Email']) : $aData['Email'];
|
||||
$this->sName = isset($aData['Name']) ? $aData['Name'] : '';
|
||||
$this->sReplyTo = !empty($aData['ReplyTo']) ? $aData['ReplyTo'] : '';
|
||||
$this->sBcc = !empty($aData['Bcc']) ? $aData['Bcc'] : '';
|
||||
|
|
@ -146,7 +145,7 @@ class Identity implements \JsonSerializable
|
|||
'@Object' => 'Object/Identity',
|
||||
'id' => $this->sId,
|
||||
'label' => $this->sLabel,
|
||||
'email' => Utils::IdnToUtf8($this->sEmail),
|
||||
'email' => \SnappyMail\IDN::emailToUtf8($this->sEmail),
|
||||
'name' => $this->sName,
|
||||
'replyTo' => $this->sReplyTo,
|
||||
'bcc' => $this->sBcc,
|
||||
|
|
|
|||
|
|
@ -1161,7 +1161,7 @@ class PdoAddressBook
|
|||
{
|
||||
static $aCache = array();
|
||||
|
||||
$sEmail = \MailSo\Base\Utils::IdnToAscii(\trim($sEmail), true);
|
||||
$sEmail = \SnappyMail\IDN::emailToAscii(\trim($sEmail));
|
||||
if (empty($sEmail)) {
|
||||
throw new \ValueError('Empty Email argument');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@ abstract class Autoconfig
|
|||
{
|
||||
public static function discover(string $emailaddress) : ?array
|
||||
{
|
||||
$domain = \MailSo\Base\Utils::GetDomainFromEmail($emailaddress);
|
||||
// $domain = \strtolower(\idn_to_ascii($domain));
|
||||
// $emailaddress = \SnappyMail\IDN::emailToAscii($emailaddress);
|
||||
$domain = \MailSo\Base\Utils::getEmailAddressDomain($emailaddress);
|
||||
$domain = \strtolower(\idn_to_ascii($domain));
|
||||
// First try
|
||||
$autoconfig = static::resolve($domain, $emailaddress);
|
||||
if ($autoconfig) {
|
||||
|
|
|
|||
|
|
@ -207,23 +207,20 @@ class DefaultDomain implements DomainInterface
|
|||
if ($bAlias) {
|
||||
if ($bIncludeAliases) {
|
||||
$aAliases[$sName] = array(
|
||||
'name' => \idn_to_utf8($sName),
|
||||
'punycode' => $sName,
|
||||
'name' => $sName,
|
||||
'disabled' => \in_array($sName, $aDisabledNames),
|
||||
'alias' => true
|
||||
);
|
||||
}
|
||||
} else if (false !== \strpos($sName, '*')) {
|
||||
$aWildCards[$sName] = array(
|
||||
'name' => \idn_to_utf8($sName),
|
||||
'punycode' => $sName,
|
||||
'name' => $sName,
|
||||
'disabled' => \in_array($sName, $aDisabledNames),
|
||||
'alias' => false
|
||||
);
|
||||
} else {
|
||||
$aResult[$sName] = array(
|
||||
'name' => \idn_to_utf8($sName),
|
||||
'punycode' => $sName,
|
||||
'name' => $sName,
|
||||
'disabled' => \in_array($sName, $aDisabledNames),
|
||||
'alias' => false
|
||||
);
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ abstract class IDN
|
|||
return static::uri($string, true);
|
||||
}
|
||||
if (\str_contains($string, '@')) {
|
||||
return static::emailAddress($string, true);
|
||||
return static::emailToAscii($string);
|
||||
}
|
||||
return \idn_to_ascii($string);
|
||||
}
|
||||
|
|
@ -24,21 +24,35 @@ abstract class IDN
|
|||
return static::uri($string, false);
|
||||
}
|
||||
if (\str_contains($string, '@')) {
|
||||
return static::emailAddress($string, false);
|
||||
return static::emailToUtf8($string);
|
||||
}
|
||||
return \idn_to_utf8($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts IDN domain part to lowercased punycode
|
||||
* Like: 'Smile😀@📧.SnappyMail.eu' to 'Smile😀@xn--du8h.snappymail.eu'
|
||||
* When the '@' is missing, it does nothing
|
||||
*/
|
||||
public static function emailToAscii(string $address) : string
|
||||
{
|
||||
return static::emailAddress($address, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts IDN domain part to unicode
|
||||
* Like: 'Smile😀@xn--du8h.SnappyMail.eu' to 'Smile😀@📧.SnappyMail.eu'
|
||||
* When the '@' is missing, it does nothing
|
||||
*/
|
||||
public static function emailToUtf8(string $address) : string
|
||||
{
|
||||
return static::emailAddress($address, false);
|
||||
}
|
||||
|
||||
private static function domain(string $domain, bool $toAscii) : string
|
||||
{
|
||||
// if ($toAscii && \preg_match('/[^\x20-\x7E]/', $domain)) {
|
||||
// if (!$toAscii && \preg_match('/(^|\\.)xn--/i', $domain)) {
|
||||
return $toAscii ? \strtolower(\idn_to_ascii($domain)) : \idn_to_utf8($domain);
|
||||
/*
|
||||
$domain = \explode('.', $domain);
|
||||
|
|
@ -53,7 +67,8 @@ abstract class IDN
|
|||
private static function emailAddress(string $address, bool $toAscii) : string
|
||||
{
|
||||
if (!\str_contains($address, '@')) {
|
||||
throw new \RuntimeException("Invalid email address: {$address}");
|
||||
// throw new \RuntimeException("Invalid email address: {$address}");
|
||||
return $address;
|
||||
}
|
||||
$local = \explode('@', $address);
|
||||
$domain = static::domain(\array_pop($local), $toAscii);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
<!-- ko foreach: accounts -->
|
||||
<li role="presentation">
|
||||
<a class="email-title" href="#" data-bind="click: $root.accountClick, text: name || email,
|
||||
<a class="email-title" href="#" data-bind="click: $root.accountClick, text: label(),
|
||||
attr: {title: email, 'data-unread': unreadEmails, 'data-icon': $root.accountEmail() === email ? '✔' : '👤'}"></a>
|
||||
</li>
|
||||
<!-- /ko -->
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue