Allow setting SSL options per domain and verify_certificate by default

This is a complete overhaul of the Domain settings system.
This commit is contained in:
the-djmaze 2022-11-11 13:45:40 +01:00
parent d76ba3abc9
commit cc1d0a6e38
45 changed files with 688 additions and 645 deletions

View file

@ -12,24 +12,49 @@ import { DomainAdminStore } from 'Stores/Admin/Domain';
import { AskPopupView } from 'View/Popup/Ask';
const domainToParams = oDomain => ({
Name: oDomain.name(),
IncHost: oDomain.imapHost(),
IncPort: oDomain.imapPort(),
IncSecure: oDomain.imapSecure(),
UseSieve: oDomain.useSieve() ? 1 : 0,
SieveHost: oDomain.sieveHost(),
SievePort: oDomain.sievePort(),
SieveSecure: oDomain.sieveSecure(),
OutHost: oDomain.smtpHost(),
OutPort: oDomain.smtpPort(),
OutSecure: oDomain.smtpSecure(),
OutAuth: oDomain.smtpAuth() ? 1 : 0,
OutUsePhpMail: oDomain.smtpPhpMail() ? 1 : 0
});
const
capitalize = string => string.charAt(0).toUpperCase() + string.slice(1),
domainToParams = oDomain => ({
Name: oDomain.name(),
IMAP: {
host: oDomain.imapHost(),
port: oDomain.imapPort(),
secure: pInt(oDomain.imapType()),
shortLogin: !!oDomain.imapShortLogin(),
ssl: {
verify_peer: !!oDomain.imapSslVerify_peer(),
verify_peer_name: !!oDomain.imapSslVerify_peer(),
allow_self_signed: !!oDomain.imapSslAllow_self_signed()
}
},
SMTP: {
host: oDomain.smtpHost(),
port: oDomain.smtpPort(),
secure: pInt(oDomain.smtpType()),
shortLogin: !!oDomain.smtpShortLogin(),
ssl: {
verify_peer: !!oDomain.smtpSslVerify_peer(),
verify_peer_name: !!oDomain.smtpSslVerify_peer(),
allow_self_signed: !!oDomain.smtpSslAllow_self_signed()
},
setSender: !!oDomain.smtpSetSender(),
useAuth: !!oDomain.smtpUseAuth(),
usePhpMail: !!oDomain.smtpUsePhpMail()
},
Sieve: {
enabled: !!oDomain.sieveEnabled(),
host: oDomain.sieveHost(),
port: oDomain.sievePort(),
secure: pInt(oDomain.sieveType()),
shortLogin: !!oDomain.imapShortLogin(),
ssl: {
verify_peer: !!oDomain.imapSslVerify_peer(),
verify_peer_name: !!oDomain.imapSslVerify_peer(),
allow_self_signed: !!oDomain.imapSslAllow_self_signed()
}
},
whiteList: oDomain.whiteList()
});
export class DomainPopupView extends AbstractViewPopup {
constructor() {
@ -82,14 +107,14 @@ export class DomainPopupView extends AbstractViewPopup {
},
domainIsComputed: () => {
const usePhpMail = this.smtpPhpMail(),
useSieve = this.useSieve();
const usePhpMail = this.smtpUsePhpMail(),
sieveEnabled = this.sieveEnabled();
return (
this.name() &&
this.imapHost() &&
this.imapPort() &&
(useSieve ? this.sieveHost() && this.sievePort() : true) &&
(sieveEnabled ? this.sieveHost() && this.sievePort() : true) &&
((this.smtpHost() && this.smtpPort()) || usePhpMail)
);
},
@ -113,7 +138,7 @@ export class DomainPopupView extends AbstractViewPopup {
smtpHostFocus: value => value && this.imapHost() && !this.smtpHost()
&& this.smtpHost(this.imapHost().replace(/imap/gi, 'smtp')),
imapSecure: value => {
imapType: value => {
if (this.enableSmartPorts()) {
const port = pInt(this.imapPort());
switch (pInt(value)) {
@ -133,7 +158,7 @@ export class DomainPopupView extends AbstractViewPopup {
}
},
smtpSecure: value => {
smtpType: value => {
if (this.enableSmartPorts()) {
const port = pInt(this.smtpPort());
switch (pInt(value)) {
@ -169,14 +194,7 @@ export class DomainPopupView extends AbstractViewPopup {
Remote.request('AdminDomainSave',
this.onDomainCreateOrSaveResponse.bind(this),
Object.assign(domainToParams(this), {
Create: this.edit() ? 0 : 1,
IncShortLogin: this.imapShortLogin() ? 1 : 0,
OutShortLogin: this.smtpShortLogin() ? 1 : 0,
OutSetSender: this.smtpSetSender() ? 1 : 0,
WhiteList: this.whiteList()
Create: this.edit() ? 0 : 1
})
);
}
@ -188,8 +206,10 @@ export class DomainPopupView extends AbstractViewPopup {
if (credentials) {
this.testing(true);
const params = domainToParams(this);
params.username = credentials.username;
params.password = credentials.password;
params.auth = {
user: credentials.username,
pass: credentials.password
};
Remote.request('AdminDomainTest',
(iError, oData) => {
this.testing(false);
@ -250,7 +270,23 @@ export class DomainPopupView extends AbstractViewPopup {
if (oDomain) {
this.enableSmartPorts(false);
this.edit(true);
forEachObjectEntry(oDomain, (key, value) => this[key]?.(value));
forEachObjectEntry(oDomain, (key, value) => {
if ('IMAP' === key || 'SMTP' === key || 'Sieve' === key) {
key = key.toLowerCase();
forEachObjectEntry(value, (skey, value) => {
skey = capitalize(skey);
if ('Ssl' == skey) {
forEachObjectEntry(value, (sslkey, value) => {
this[key + skey + capitalize(sslkey)]?.(value);
});
} else {
this[key + skey]?.(value);
}
});
} else {
this[key]?.(value);
}
});
this.enableSmartPorts(true);
}
}
@ -265,21 +301,27 @@ export class DomainPopupView extends AbstractViewPopup {
imapHost: '',
imapPort: 143,
imapSecure: 0,
imapType: 0,
imapShortLogin: false,
// SSL
imapSslVerify_peer: false,
imapSslAllow_self_signed: false,
useSieve: false,
sieveEnabled: false,
sieveHost: '',
sievePort: 4190,
sieveSecure: 0,
sieveType: 0,
smtpHost: '',
smtpPort: 25,
smtpSecure: 0,
smtpType: 0,
smtpShortLogin: false,
smtpAuth: true,
smtpUseAuth: true,
smtpSetSender: false,
smtpPhpMail: false,
smtpUsePhpMail: false,
// SSL
smtpSslVerify_peer: false,
smtpSslAllow_self_signed: false,
whiteList: '',
aliasName: ''

View file

@ -1,18 +1,50 @@
{
"imapHost": "localhost",
"imapPort": 143,
"imapSecure": 0,
"imapShortLogin": false,
"useSieve": false,
"sieveHost": "localhost",
"sievePort": 4190,
"sieveSecure": 0,
"smtpHost": "localhost",
"smtpPort": 25,
"smtpSecure": 0,
"smtpShortLogin": false,
"smtpAuth": true,
"smtpSetSender": false,
"smtpPhpMail": false,
"name": "*",
"IMAP": {
"host": "localhost",
"port": 143,
"secure": 0,
"shortLogin": false,
"ssl": {
"verify_peer": false,
"verify_peer_name": false,
"allow_self_signed": false,
"SNI_enabled": true,
"disable_compression": true,
"security_level": 1
}
},
"SMTP": {
"host": "localhost",
"port": 25,
"secure": 0,
"shortLogin": false,
"ssl": {
"verify_peer": false,
"verify_peer_name": false,
"allow_self_signed": false,
"SNI_enabled": true,
"disable_compression": true,
"security_level": 1
},
"useAuth": false,
"setSender": false,
"usePhpMail": false
},
"Sieve": {
"host": "localhost",
"port": 4190,
"secure": 0,
"shortLogin": false,
"ssl": {
"verify_peer": false,
"verify_peer_name": false,
"allow_self_signed": false,
"SNI_enabled": true,
"disable_compression": true,
"security_level": 1
},
"enabled": true
},
"whiteList": ""
}

View file

@ -120,15 +120,15 @@ class ImapClient extends \MailSo\Net\NetClient
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Imap\Exceptions\*
*/
public function Login(array $aCredentials) : self
public function Login(Settings $oSettings) : self
{
if (!empty($aCredentials['ProxyAuthUser']) && !empty($aCredentials['ProxyAuthPassword'])) {
$sLogin = \MailSo\Base\Utils::IdnToAscii(\MailSo\Base\Utils::Trim($aCredentials['ProxyAuthUser']));
$sPassword = $aCredentials['ProxyAuthPassword'];
$sProxyAuthUser = $aCredentials['Login'];
if (!empty($oSettings->ProxyAuthUser) && !empty($oSettings->ProxyAuthPassword)) {
$sLogin = \MailSo\Base\Utils::IdnToAscii(\MailSo\Base\Utils::Trim($oSettings->ProxyAuthUser));
$sPassword = $oSettings->ProxyAuthPassword;
$sProxyAuthUser = $oSettings->Login;
} else {
$sLogin = \MailSo\Base\Utils::IdnToAscii(\MailSo\Base\Utils::Trim($aCredentials['Login']));
$sPassword = $aCredentials['Password'];
$sLogin = \MailSo\Base\Utils::IdnToAscii(\MailSo\Base\Utils::Trim($oSettings->Login));
$sPassword = $oSettings->Password;
$sProxyAuthUser = '';
}
@ -142,7 +142,7 @@ class ImapClient extends \MailSo\Net\NetClient
$this->sLogginedUser = $sLogin;
$type = $this->IsSupported('LOGINDISABLED') ? '' : 'LOGIN'; // RFC3501 6.2.3
foreach ($aCredentials['SASLMechanisms'] as $sasl_type) {
foreach ($oSettings->SASLMechanisms as $sasl_type) {
if ($this->IsSupported("AUTH={$sasl_type}") && \SnappyMail\SASL::isSupported($sasl_type)) {
$type = $sasl_type;
break;
@ -151,7 +151,7 @@ class ImapClient extends \MailSo\Net\NetClient
if (!$type) {
if (!$this->Encrypted() && $this->IsSupported('STARTTLS')) {
$this->StartTLS();
return $this->Login($aCredentials);
return $this->Login($oSettings);
}
throw new \MailSo\RuntimeException('No supported SASL mechanism found, remote server wants: '
. \implode(', ', \array_filter($this->Capability() ?: [], function($var){

View file

@ -0,0 +1,34 @@
<?php
/*
* This file is part of MailSo.
*
* (c) 2022 DJMaze
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MailSo\Imap;
/**
* @category MailSo
* @package Net
*/
class Settings extends \MailSo\Net\ConnectSettings
{
public int $port = 143;
/*
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return \array_merge(
parent::jsonSerialize(),
[
// '@Object' => 'Object/ImapSettings',
]
);
}
*/
}

View file

@ -15,66 +15,58 @@ namespace MailSo\Net;
* @category MailSo
* @package Net
*/
class ConnectSettings
class ConnectSettings implements \JsonSerializable
{
public
$host,
public string $host;
$port,
public int $port;
// none, TLS, STARTTLS
$type = \MailSo\Net\Enumerations\ConnectionSecurityType::AUTO_DETECT,
// none, TLS, STARTTLS
public int $type = Enumerations\ConnectionSecurityType::AUTO_DETECT;
// https://www.php.net/context.ssl
$ssl = [
// 'peer_name' => '',
// 'peer_fingerprint' => '', // string | array
'verify_peer' => true,
'verify_peer_name' => true,
'allow_self_signed' => false,
// 'cafile' => '',
// 'capath' => '',
public SSLContext $ssl;
// 'ciphers' => 'HIGH:!SSLv2:!SSLv3',
'SNI_enabled' => true,
'disable_compression' => true,
'security_level' => 1,
// Authentication settings use by all child classes
public bool $useAuth = true;
public bool $shortLogin = false;
public array $SASLMechanisms = [];
public string $Login = '';
public string $Password = '';
public string $ProxyAuthUser = '';
public string $ProxyAuthPassword = '';
// 'local_cert' => '',
// 'local_pk' => '',
// 'passphrase' => '',
// 'verify_depth' => 0,
// 'capture_peer_cert' => false,
// 'capture_peer_cert_chain' => false,
];
function __construct()
public function __construct()
{
// TODO: This should be moved to \RainLoop\Model\Domain
$oConfig = \RainLoop\API::Config();
$this->ssl['verify_peer'] = !!$oConfig->Get('ssl', 'verify_certificate', false);
$this->ssl['verify_peer_name'] = !!$oConfig->Get('ssl', 'verify_certificate', false);
$this->ssl['allow_self_signed'] = !!$oConfig->Get('ssl', 'allow_self_signed', true);
$this->ssl['security_level'] = (int) $oConfig->Get('ssl', 'security_level', 1);
// $this->ssl['local_cert'] = (string) $oConfig->Get('ssl', 'client_cert', '');
// $this->ssl['cafile'] = (string) $oConfig->Get('ssl', 'cafile', '');
// $this->ssl['capath'] = (string) $oConfig->Get('ssl', 'capath', '');
$this->ssl = new SSLContext;
}
public static function Host() : string
{
return \SnappyMail\IDN::toAscii($this->host);
}
public static function fromArray(array $aSettings) : self
{
$object = new self;
$object->host = $aSettings['Host'];
$object->port = $aSettings['Port'];
$object->type = $aSettings['Secure'];
$object->ssl['verify_peer'] = !empty($aSettings['VerifySsl']);
$object->ssl['verify_peer_name'] = !empty($aSettings['VerifySsl']);
$object->ssl['allow_self_signed'] = !empty($aSettings['AllowSelfSigned']);
if (!empty($aSettings['ClientCert'])) {
$object->ssl['local_cert'] = $aSettings['ClientCert'];
}
$object = new static;
$object->host = $aSettings['host'];
$object->port = $aSettings['port'];
$object->type = $aSettings['secure'];
$object->shortLogin = !empty($aSettings['shortLogin']);
$object->ssl = SSLContext::fromArray($aSettings['ssl'] ?? []);
return $object;
}
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return array(
// '@Object' => 'Object/ConnectSettings',
'host' => $this->host,
'port' => $this->port,
'secure' => $this->type,
'shortLogin' => $this->shortLogin,
'ssl' => $this->ssl
);
}
}

View file

@ -162,13 +162,9 @@ abstract class NetClient
$this->iStartConnectTime = \microtime(true);
$this->writeLog('Start connection to "'.$this->sConnectedHost.':'.$this->iConnectedPort.'"');
$aStreamContextSettings = array(
'ssl' => $oSettings->ssl
);
\MailSo\Hooks::Run('Net.NetClient.StreamContextSettings/Filter', array(&$aStreamContextSettings));
$rStreamContext = \stream_context_create($aStreamContextSettings);
$rStreamContext = \stream_context_create(array(
'ssl' => $oSettings->ssl->jsonSerialize()
));
\set_error_handler(array($this, 'capturePhpErrorWithException'));

View file

@ -0,0 +1,73 @@
<?php
/*
* This file is part of MailSo.
*
* (c) 2022 DJMaze
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.php.net/context.ssl
*/
namespace MailSo\Net;
/**
* @category MailSo
* @package Net
*/
class SSLContext implements \JsonSerializable
{
// public string $peer_name = '';
// public string $peer_fingerprint = '';
public bool $verify_peer = true;
public bool $verify_peer_name = true;
public bool $allow_self_signed = false;
public string $cafile = '';
public string $capath = '';
// public string $ciphers = 'HIGH:!SSLv2:!SSLv3';
public bool $SNI_enabled = true;
public bool $disable_compression = true;
public int $security_level = 1;
public string $local_cert = '';
// public string $local_pk = '';
// public string $passphrase = '';
// public int $verify_depth = 0;
// public bool $capture_peer_cert = false;
// public bool $capture_peer_cert_chain = false;
public function __construct()
{
$oConfig = \RainLoop\API::Config();
$this->verify_peer = !!$oConfig->Get('ssl', 'verify_certificate', true);
$this->verify_peer_name = !!$oConfig->Get('ssl', 'verify_certificate', true);
$this->allow_self_signed = !!$oConfig->Get('ssl', 'allow_self_signed', false);
$this->cafile = \trim($oConfig->Get('ssl', 'cafile', ''));
$this->capath = \trim($oConfig->Get('ssl', 'capath', ''));
$this->disable_compression = !!$oConfig->Get('ssl', 'disable_compression', true);
$this->security_level = (int) $oConfig->Get('ssl', 'security_level', 1);
$this->local_cert = \trim($oConfig->Get('ssl', 'local_cert', ''));
}
public static function fromArray(array $settings) : self
{
$object = new static;
foreach ($settings as $key => $value) {
$object->$key = $value;
}
return $object;
}
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
$aResult = \get_object_vars($this);
// $aResult['@Object'] = 'Object/SSLContext';
return \array_filter(
$aResult,
function($var){return !\is_string($var) || \strlen($var);}
);
}
}

View file

@ -100,10 +100,10 @@ class ManageSieveClient extends \MailSo\Net\NetClient
* @throws \MailSo\Net\Exceptions\*
* @throws \MailSo\Sieve\Exceptions\*
*/
public function Login(array $aCredentials) : self
public function Login(Settings $oSettings) : self
{
$sLogin = $aCredentials['Login'];
$sPassword = $aCredentials['Password'];
$sLogin = $oSettings->Login;
$sPassword = $oSettings->Password;
$sLoginAuthKey = '';
if (!\strlen($sLogin) || !\strlen($sPassword))
{
@ -113,8 +113,8 @@ class ManageSieveClient extends \MailSo\Net\NetClient
}
$type = '';
\array_push($aCredentials['SASLMechanisms'], 'PLAIN', 'LOGIN');
foreach ($aCredentials['SASLMechanisms'] as $sasl_type) {
\array_push($oSettings->SASLMechanisms, 'PLAIN', 'LOGIN');
foreach ($oSettings->SASLMechanisms as $sasl_type) {
if ($this->IsAuthSupported($sasl_type) && \SnappyMail\SASL::isSupported($sasl_type)) {
$type = $sasl_type;
break;
@ -124,7 +124,7 @@ class ManageSieveClient extends \MailSo\Net\NetClient
if (!$type) {
if (!$this->Encrypted() && $this->IsSupported('STARTTLS')) {
$this->StartTLS();
return $this->Login($aCredentials);
return $this->Login($oSettings);
}
$this->writeLogException(
new \MailSo\Sieve\Exceptions\LoginException,
@ -154,7 +154,7 @@ class ManageSieveClient extends \MailSo\Net\NetClient
$sAuth = $SASL->authenticate($sLogin, $sPassword, $sLoginAuthKey);
$this->oLogger && $this->oLogger->AddSecret($sAuth);
if ($aCredentials['InitialAuthPlain']) {
if ($oSettings->initialAuthPlain) {
$this->sendRaw("AUTHENTICATE \"{$type}\" \"{$sAuth}\"");
} else {
$this->sendRaw("AUTHENTICATE \"{$type}\" {".\strlen($sAuth).'+}');

View file

@ -0,0 +1,52 @@
<?php
/*
* This file is part of MailSo.
*
* (c) 2022 DJMaze
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MailSo\Sieve;
/**
* @category MailSo
* @package Net
*/
class Settings extends \MailSo\Net\ConnectSettings
{
public int $port = 4190;
public bool $enabled = false;
public bool $initialAuthPlain = false;
public function __construct()
{
parent::__construct();
$oConfig = \RainLoop\API::Config();
$this->initialAuthPlain = !!$oConfig->Get('labs', 'sieve_auth_plain_initial', true);
}
public static function fromArray(array $aSettings) : self
{
$object = parent::fromArray($aSettings);
$object->enabled = !empty($aSettings['enabled']);
return $object;
}
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return \array_merge(
parent::jsonSerialize(),
[
// '@Object' => 'Object/SmtpSettings',
'enabled' => $this->enabled
]
);
}
}

View file

@ -0,0 +1,51 @@
<?php
/*
* This file is part of MailSo.
*
* (c) 2022 DJMaze
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace MailSo\Smtp;
/**
* @category MailSo
* @package Net
*/
class Settings extends \MailSo\Net\ConnectSettings
{
public int $port = 25;
public bool $usePhpMail = false;
public bool $setSender = false;
public string $Ehlo;
public static function fromArray(array $aSettings) : self
{
$object = parent::fromArray($aSettings);
$object->useAuth = !empty($aSettings['useAuth']);
$object->setSender = !empty($aSettings['setSender']);
$object->usePhpMail = !empty($aSettings['usePhpMail']);
return $object;
}
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return \array_merge(
parent::jsonSerialize(),
[
// '@Object' => 'Object/SmtpSettings',
'useAuth' => $this->useAuth,
'setSender' => $this->setSender,
'usePhpMail' => $this->usePhpMail
]
);
}
}

View file

@ -137,16 +137,16 @@ class SmtpClient extends \MailSo\Net\NetClient
* @throws \MailSo\Net\*
* @throws \MailSo\Smtp\Exceptions\*
*/
public function Login(array $aCredentials) : self
public function Login(Settings $oSettings) : self
{
$sLogin = \MailSo\Base\Utils::IdnToAscii(\MailSo\Base\Utils::Trim($aCredentials['Login']));
$sPassword = $aCredentials['Password'];
$sLogin = \MailSo\Base\Utils::IdnToAscii(\MailSo\Base\Utils::Trim($oSettings->Login));
$sPassword = $oSettings->Password;
$type = '';
// https://github.com/the-djmaze/snappymail/pull/423
// $aCredentials['SASLMechanisms'][] = 'LOGIN';
\array_unshift($aCredentials['SASLMechanisms'], 'LOGIN');
foreach ($aCredentials['SASLMechanisms'] as $sasl_type) {
// $oSettings->SASLMechanisms[] = 'LOGIN';
\array_unshift($oSettings->SASLMechanisms, 'LOGIN');
foreach ($oSettings->SASLMechanisms as $sasl_type) {
if ($this->IsAuthSupported($sasl_type) && \SnappyMail\SASL::isSupported($sasl_type)) {
$type = $sasl_type;
break;
@ -156,7 +156,7 @@ class SmtpClient extends \MailSo\Net\NetClient
if (!$type) {
if (!$this->Encrypted() && $this->IsSupported('STARTTLS')) {
$this->StartTLS();
return $this->Login($aCredentials);
return $this->Login($oSettings);
}
\trigger_error("SMTP {$this->GetConnectedHost()} no supported AUTH options. Disable login");
$this->writeLogException(

View file

@ -269,35 +269,21 @@ class ActionsAdmin extends Actions
$oDomain = $this->DomainProvider()->LoadOrCreateNewFromAction($this, 'test.example.com');
if ($oDomain)
{
$aAuth = $this->GetActionParam('auth');
try
{
$oImapClient = new \MailSo\Imap\ImapClient();
$oImapClient->SetLogger($this->Logger());
$oImapClient->SetTimeOuts($iConnectionTimeout);
$iTime = \microtime(true);
$oSettings = \MailSo\Net\ConnectSettings::fromArray($oDomain->ImapSettings());
$oSettings = $oDomain->ImapSettings();
$oImapClient->Connect($oSettings);
$sUsername = $this->GetActionParam('username', '');
if ($sUsername) {
$aSASLMechanisms = [];
$oConfig = $this->Config();
if ($oConfig->Get('labs', 'sasl_allow_scram_sha', false)) {
// https://github.com/the-djmaze/snappymail/issues/182
\array_push($aSASLMechanisms, 'SCRAM-SHA3-512', 'SCRAM-SHA-512', 'SCRAM-SHA-256', 'SCRAM-SHA-1');
}
if ($oConfig->Get('labs', 'sasl_allow_cram_md5', false)) {
$aSASLMechanisms[] = 'CRAM-MD5';
}
if ($oConfig->Get('labs', 'sasl_allow_plain', true)) {
$aSASLMechanisms[] = 'PLAIN';
}
$oImapClient->Login([
'Login' => $sUsername,
'Password' => $this->GetActionParam('password', ''),
'SASLMechanisms' => $aSASLMechanisms
]);
if (!empty($aAuth['user'])) {
$oSettings->Login = $aAuth['user'];
$oSettings->Password = $aAuth['pass'];
$oImapClient->Login($oSettings);
}
$oImapClient->Disconnect();
@ -334,10 +320,15 @@ class ActionsAdmin extends Actions
$oSmtpClient->SetLogger($this->Logger());
$oSmtpClient->SetTimeOuts($iConnectionTimeout);
$iTime = \microtime(true);
$oSettings = \MailSo\Net\ConnectSettings::fromArray($oDomain->SmtpSettings());
$oSettings = $oDomain->SmtpSettings();
$oSmtpClient->Connect($oSettings, \MailSo\Smtp\SmtpClient::EhloHelper());
if (!empty($aAuth['user'])) {
$oSettings->Login = $aAuth['user'];
$oSettings->Password = $aAuth['pass'];
$oSmtpClient->Login($oSettings);
}
$oSmtpClient->Disconnect();
$bSmtpResult = true;
}
@ -365,10 +356,15 @@ class ActionsAdmin extends Actions
$oSieveClient->SetLogger($this->Logger());
$oSieveClient->SetTimeOuts($iConnectionTimeout);
$iTime = \microtime(true);
$oSettings = \MailSo\Net\ConnectSettings::fromArray($oDomain->SieveSettings());
$oSettings = $oDomain->SieveSettings();
$oSieveClient->Connect($oSettings);
if (!empty($aAuth['user'])) {
$oSettings->Login = $aAuth['user'];
$oSettings->Password = $aAuth['pass'];
$oSieveClient->Login($oSettings);
}
$oSieveClient->Disconnect();
$bSieveResult = true;
}

View file

@ -112,33 +112,12 @@ abstract class Api
\MailSo\Config::$BoundaryPrefix =
\trim(static::Config()->Get('labs', 'boundary_prefix', ''));
$sSslCafile = static::Config()->Get('ssl', 'cafile', '');
$sSslCapath = static::Config()->Get('ssl', 'capath', '');
Utils::$CookieDefaultPath = static::Config()->Get('labs', 'cookie_default_path', '');
Utils::$CookieSameSite = static::Config()->Get('security', 'cookie_samesite', 'Strict');
Utils::$CookieSecure = isset($_SERVER['HTTPS'])
|| 'None' == Utils::$CookieSameSite
|| !!static::Config()->Get('labs', 'cookie_default_secure', false);
if (!empty($sSslCafile) || !empty($sSslCapath))
{
\MailSo\Hooks::Add('Net.NetClient.StreamContextSettings/Filter', function ($aStreamContextSettings) use ($sSslCafile, $sSslCapath) {
if (isset($aStreamContextSettings['ssl']) && \is_array($aStreamContextSettings['ssl']))
{
if (empty($aStreamContextSettings['ssl']['cafile']) && !empty($sSslCafile))
{
$aStreamContextSettings['ssl']['cafile'] = $sSslCafile;
}
if (empty($aStreamContextSettings['ssl']['capath']) && !empty($sSslCapath))
{
$aStreamContextSettings['ssl']['capath'] = $sSslCapath;
}
}
});
}
\MailSo\Config::$CheckNewMessages = !!static::Config()->Get('labs', 'check_new_messages', true);
}
}

View file

@ -218,12 +218,13 @@ Default is "site=same-origin;site=none"')
),
'ssl' => array(
'verify_certificate' => array(false, 'Require verification of SSL certificate used.'),
'allow_self_signed' => array(true, 'Allow self-signed certificates. Requires verify_certificate.'),
'security_level' => array(1, 'https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html'),
'cafile' => array('', 'Location of Certificate Authority file on local filesystem (/etc/ssl/certs/ca-certificates.crt)'),
'capath' => array('', 'capath must be a correctly hashed certificate directory. (/etc/ssl/certs/)'),
'client_cert' => array('', 'Location of client certificate file (pem format with private key) on local filesystem'),
'verify_certificate' => array(true, 'Require verification of SSL certificate used.'),
'allow_self_signed' => array(false, 'Allow self-signed certificates. Requires verify_certificate.'),
'security_level' => array(1, 'https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html'),
'cafile' => array('', 'Location of Certificate Authority file on local filesystem (/etc/ssl/certs/ca-certificates.crt)'),
'capath' => array('', 'capath must be a correctly hashed certificate directory. (/etc/ssl/certs/)'),
'local_cert' => array('', 'Location of client certificate file (pem format with private key) on local filesystem'),
'disable_compression' => array(true, 'This can help mitigate the CRIME attack vector.')
),
'capa' => array(

View file

@ -222,75 +222,48 @@ abstract class Account implements \JsonSerializable
$oImapClient->__FORCE_SELECT_ON_EXAMINE__ = !!$oConfig->Get('imap', 'use_force_selection');
$oImapClient->__DISABLE_METADATA = !!$oConfig->Get('imap', 'disable_metadata');
$aCredentials = \array_merge(
$this->Domain()->ImapSettings(),
array(
'Login' => $this->IncLogin(),
'VerifySsl' => !!$oConfig->Get('ssl', 'verify_certificate', false),
'AllowSelfSigned' => !!$oConfig->Get('ssl', 'allow_self_signed', true),
'ClientCert' => \trim($oConfig->Get('ssl', 'client_cert', ''))
)
);
$oSettings = $this->Domain()->ImapSettings();
$oSettings->Login = $this->IncLogin();
$oPlugins->RunHook('imap.before-connect', array($this, $oImapClient, &$aCredentials));
if ($aCredentials['UseConnect']) {
$oSettings = \MailSo\Net\ConnectSettings::fromArray($aCredentials);
$oImapClient->Connect($oSettings);
}
$oPlugins->RunHook('imap.after-connect', array($this, $oImapClient, $aCredentials));
$oPlugins->RunHook('imap.before-connect', array($this, $oImapClient, $oSettings));
$oImapClient->Connect($oSettings);
$oPlugins->RunHook('imap.after-connect', array($this, $oImapClient, $oSettings));
return $this->netClientLogin($oImapClient, $oConfig, $oPlugins, $aCredentials);
return $this->netClientLogin($oImapClient, $oPlugins, $oSettings);
}
public function SmtpConnectAndLoginHelper(\RainLoop\Plugins\Manager $oPlugins, \MailSo\Smtp\SmtpClient $oSmtpClient, \RainLoop\Config\Application $oConfig, bool &$bUsePhpMail = false) : bool
{
$aCredentials = \array_merge(
$this->Domain()->SmtpSettings(),
array(
'UseConnect' => !$bUsePhpMail,
'UsePhpMail' => $bUsePhpMail,
'Login' => $this->OutLogin(),
'VerifySsl' => !!$oConfig->Get('ssl', 'verify_certificate', false),
'AllowSelfSigned' => !!$oConfig->Get('ssl', 'allow_self_signed', true)
)
);
$oSettings = $this->Domain()->SmtpSettings();
$oSettings->Login = $this->OutLogin();
$oSettings->usePhpMail = $bUsePhpMail;
$oSettings->Ehlo = \MailSo\Smtp\SmtpClient::EhloHelper();
$oPlugins->RunHook('smtp.before-connect', array($this, $oSmtpClient, &$aCredentials));
$bUsePhpMail = $aCredentials['UsePhpMail'];
$aCredentials['UseAuth'] = $aCredentials['UseAuth'] && !$aCredentials['UsePhpMail'];
$oPlugins->RunHook('smtp.before-connect', array($this, $oSmtpClient, $oSettings));
$bUsePhpMail = $oSettings->usePhpMail;
$oSettings->useAuth = $oSettings->useAuth && !$oSettings->usePhpMail;
if ($aCredentials['UseConnect'] && !$aCredentials['UsePhpMail']) {
$oSettings = \MailSo\Net\ConnectSettings::fromArray($aCredentials);
$oSmtpClient->Connect($oSettings, $aCredentials['Ehlo']);
if (!$oSettings->usePhpMail) {
$oSmtpClient->Connect($oSettings, $oSettings->Ehlo);
}
$oPlugins->RunHook('smtp.after-connect', array($this, $oSmtpClient, $aCredentials));
$oPlugins->RunHook('smtp.after-connect', array($this, $oSmtpClient, $oSettings));
return $this->netClientLogin($oSmtpClient, $oConfig, $oPlugins, $aCredentials);
return $this->netClientLogin($oSmtpClient, $oPlugins, $oSettings);
}
public function SieveConnectAndLoginHelper(\RainLoop\Plugins\Manager $oPlugins, \MailSo\Sieve\ManageSieveClient $oSieveClient, \RainLoop\Config\Application $oConfig)
{
$aCredentials = \array_merge(
$this->Domain()->SieveSettings(),
array(
'Login' => $this->IncLogin(),
'VerifySsl' => !!$oConfig->Get('ssl', 'verify_certificate', false),
'AllowSelfSigned' => !!$oConfig->Get('ssl', 'allow_self_signed', true),
'InitialAuthPlain' => !!$oConfig->Get('labs', 'sieve_auth_plain_initial', true)
)
);
$oSettings = $this->Domain()->SieveSettings();
$oSettings->Login = $this->IncLogin();
$oPlugins->RunHook('sieve.before-connect', array($this, $oSieveClient, &$aCredentials));
if ($aCredentials['UseConnect']) {
$oSettings = \MailSo\Net\ConnectSettings::fromArray($aCredentials);
$oSieveClient->Connect($oSettings);
}
$oPlugins->RunHook('sieve.after-connect', array($this, $oSieveClient, $aCredentials));
$oPlugins->RunHook('sieve.before-connect', array($this, $oSieveClient, $oSettings));
$oSieveClient->Connect($oSettings);
$oPlugins->RunHook('sieve.after-connect', array($this, $oSieveClient, $oSettings));
return $this->netClientLogin($oSieveClient, $oConfig, $oPlugins, $aCredentials);
return $this->netClientLogin($oSieveClient, $oPlugins, $oSettings);
}
private function netClientLogin(\MailSo\Net\NetClient $oClient, \RainLoop\Config\Application $oConfig, \RainLoop\Plugins\Manager $oPlugins, array $aCredentials) : bool
private function netClientLogin(\MailSo\Net\NetClient $oClient, \RainLoop\Plugins\Manager $oPlugins, \MailSo\Net\ConnectSettings $oSettings) : bool
{
/*
$encrypted = !empty(\stream_get_meta_data($oClient->ConnectionResource())['crypto']);
@ -301,35 +274,15 @@ abstract class Account implements \JsonSerializable
[cipher_version] => TLSv1.3
)
*/
/**
* TODO: move these to Admin -> Domains -> per Domain management?
*/
$aSASLMechanisms = [];
if ($oConfig->Get('labs', 'sasl_allow_scram_sha', false)) {
// https://github.com/the-djmaze/snappymail/issues/182
\array_push($aSASLMechanisms, 'SCRAM-SHA3-512', 'SCRAM-SHA-512', 'SCRAM-SHA-256', 'SCRAM-SHA-1');
}
if ($oConfig->Get('labs', 'sasl_allow_cram_md5', false)) {
$aSASLMechanisms[] = 'CRAM-MD5';
}
if ($oConfig->Get('labs', 'sasl_allow_plain', true)) {
$aSASLMechanisms[] = 'PLAIN';
}
$aCredentials = \array_merge(
$aCredentials,
array(
'Password' => $this->Password(),
'ProxyAuthUser' => $this->ProxyAuthUser(),
'ProxyAuthPassword' => $this->ProxyAuthPassword(),
'SASLMechanisms' => $aSASLMechanisms
)
);
$oSettings->Password = $this->Password();
$oSettings->ProxyAuthUser = $this->ProxyAuthUser();
$oSettings->ProxyAuthPassword = $this->ProxyAuthPassword();
$client_name = \strtolower($oClient->getLogName());
$oPlugins->RunHook("{$client_name}.before-login", array($this, $oClient, &$aCredentials));
$bResult = $aCredentials['UseAuth'] && $oClient->Login($aCredentials);
$oPlugins->RunHook("{$client_name}.after-login", array($this, $oClient, $bResult, $aCredentials));
$oPlugins->RunHook("{$client_name}.before-login", array($this, $oClient, $oSettings));
$bResult = !$oSettings->useAuth || $oClient->Login($oSettings);
$oPlugins->RunHook("{$client_name}.after-login", array($this, $oClient, $bResult, $oSettings));
return $bResult;
}

View file

@ -4,193 +4,81 @@ namespace RainLoop\Model;
use MailSo\Net\Enumerations\ConnectionSecurityType;
// \SnappyMail\IDN::toAscii(
// \SnappyMail\IDN::toUtf8(
class Domain implements \JsonSerializable
{
/**
* @var string
*/
private $sName;
private string $Name;
/**
* @var string
*/
private $sIncHost;
private \MailSo\Imap\Settings $IMAP;
/**
* @var int
*/
private $iIncPort;
private \MailSo\Smtp\Settings $SMTP;
/**
* @var int
*/
private $iIncSecure;
private \MailSo\Sieve\Settings $Sieve;
/**
* @var bool
*/
private $bIncShortLogin;
private string $whiteList = '';
/**
* @var string
*/
private $sOutHost;
/**
* @var int
*/
private $iOutPort;
/**
* @var int
*/
private $iOutSecure;
/**
* @var bool
*/
private $bOutShortLogin;
/**
* @var bool
*/
private $bOutAuth;
/**
* @var bool
*/
private $bOutSetSender;
/**
* @var bool
*/
private $bOutUsePhpMail;
/**
* @var bool
*/
private $bUseSieve;
/**
* @var string
*/
private $sSieveHost;
/**
* @var int
*/
private $iSievePort;
/**
* @var int
*/
private $iSieveSecure;
/**
* @var string
*/
private $sWhiteList;
/**
* @var string
*/
private $sAliasName = '';
private string $aliasName = '';
function __construct(string $sName)
{
$this->sName = $sName;
$this->Name = $sName;
$this->IMAP = new \MailSo\Imap\Settings;
$this->SMTP = new \MailSo\Smtp\Settings;
$this->Sieve = new \MailSo\Sieve\Settings;
}
/**
* See ToIniString() for valid values
* Used by old ToIniString()
*/
public static function fromIniArray(string $sName, array $aDomain) : ?self
{
$oDomain = null;
if (\strlen($sName) && \strlen($aDomain['imap_host']) && \strlen($aDomain['imap_port']))
{
if (\strlen($sName) && \strlen($aDomain['imap_host'])) {
$oDomain = new self($sName);
$oDomain->sIncHost = (string) $aDomain['imap_host'];
$oDomain->iIncPort = (int) $aDomain['imap_port'];
$oDomain->iIncSecure = self::StrConnectionSecurityTypeToCons(empty($aDomain['imap_secure']) ? '' : $aDomain['imap_secure']);
$oDomain->bIncShortLogin = !empty($aDomain['imap_short_login']);
$oDomain->IMAP->host = \SnappyMail\IDN::toUtf8($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->bUseSieve = !empty($aDomain['sieve_use']);
$oDomain->sSieveHost = empty($aDomain['sieve_host']) ? '' : (string) $aDomain['sieve_host'];
$oDomain->iSievePort = empty($aDomain['sieve_port']) ? 4190 : (int) $aDomain['sieve_port'];
$oDomain->iSieveSecure = self::StrConnectionSecurityTypeToCons(empty($aDomain['sieve_secure']) ? '' : $aDomain['sieve_secure']);
$oDomain->Sieve->enabled = !empty($aDomain['sieve_use']);
$oDomain->Sieve->host = \SnappyMail\IDN::toUtf8($aDomain['sieve_host']);
$oDomain->Sieve->port = (int) ($aDomain['sieve_port'] ?? 4190);;
$oDomain->Sieve->type = self::StrConnectionSecurityTypeToCons($aDomain['sieve_secure'] ?? '');
$oDomain->sOutHost = empty($aDomain['smtp_host']) ? '' : (string) $aDomain['smtp_host'];
$oDomain->iOutPort = empty($aDomain['smtp_port']) ? 25 : (int) $aDomain['smtp_port'];
$oDomain->iOutSecure = self::StrConnectionSecurityTypeToCons(empty($aDomain['smtp_secure']) ? '' : $aDomain['smtp_secure']);
$oDomain->bOutShortLogin = !empty($aDomain['smtp_short_login']);
$oDomain->bOutAuth = !empty($aDomain['smtp_auth']);
$oDomain->bOutSetSender = !empty($aDomain['smtp_set_sender']);
$oDomain->bOutUsePhpMail = !empty($aDomain['smtp_php_mail']);
$oDomain->SMTP->host = \SnappyMail\IDN::toUtf8($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']);
$oDomain->SMTP->useAuth = !empty($aDomain['smtp_auth']);
$oDomain->SMTP->setSender = !empty($aDomain['smtp_set_sender']);
$oDomain->SMTP->usePhpMail = !empty($aDomain['smtp_php_mail']);
$oDomain->sWhiteList = (string) ($aDomain['white_list'] ?? '');
$oDomain->whiteList = \trim($aDomain['white_list'] ?? '');
$oDomain->Normalize();
}
return $oDomain;
}
private function encodeIniString(string $sStr) : string
{
return str_replace('"', '\\"', $sStr);
}
public function Normalize()
{
$this->sIncHost = \trim($this->sIncHost);
$this->sSieveHost = \trim($this->sSieveHost);
$this->sOutHost = \trim($this->sOutHost);
$this->sWhiteList = \trim($this->sWhiteList);
if ($this->iIncPort <= 0)
{
$this->iIncPort = 143;
}
if ($this->iSievePort <= 0)
{
$this->iSievePort = 4190;
}
if ($this->iOutPort <= 0)
{
$this->iOutPort = 25;
}
}
public function ToIniString() : string
{
$this->Normalize();
return \implode("\n", array(
'imap_host = "'.$this->encodeIniString($this->sIncHost).'"',
'imap_port = '.$this->iIncPort,
'imap_secure = "'.self::ConstConnectionSecurityTypeToStr($this->iIncSecure).'"',
'imap_short_login = '.($this->bIncShortLogin ? 'On' : 'Off'),
'sieve_use = '.($this->bUseSieve ? 'On' : 'Off'),
'sieve_host = "'.$this->encodeIniString($this->sSieveHost).'"',
'sieve_port = '.$this->iSievePort,
'sieve_secure = "'.self::ConstConnectionSecurityTypeToStr($this->iSieveSecure).'"',
'smtp_host = "'.$this->encodeIniString($this->sOutHost).'"',
'smtp_port = '.$this->iOutPort,
'smtp_secure = "'.self::ConstConnectionSecurityTypeToStr($this->iOutSecure).'"',
'smtp_short_login = '.($this->bOutShortLogin ? 'On' : 'Off'),
'smtp_auth = '.($this->bOutAuth ? 'On' : 'Off'),
'smtp_set_sender = '.($this->bOutSetSender ? 'On' : 'Off'),
'smtp_php_mail = '.($this->bOutUsePhpMail ? 'On' : 'Off'),
'white_list = "'.$this->encodeIniString($this->sWhiteList).'"'
));
$this->IMAP->host = \trim($this->IMAP->host);
$this->Sieve->host = \trim($this->Sieve->host);
$this->SMTP->host = \trim($this->SMTP->host);
$this->whiteList = \trim($this->whiteList);
}
/**
* Use by old fromIniArray()
*/
public static function StrConnectionSecurityTypeToCons(string $sType) : int
{
$iSecurityType = ConnectionSecurityType::NONE;
switch (strtoupper($sType))
switch (\strtoupper($sType))
{
case 'SSL':
$iSecurityType = ConnectionSecurityType::SSL;
@ -202,22 +90,6 @@ class Domain implements \JsonSerializable
return $iSecurityType;
}
public static function ConstConnectionSecurityTypeToStr(int $iSecurityType) : string
{
$sType = 'None';
switch ($iSecurityType)
{
case ConnectionSecurityType::SSL:
$sType = 'SSL';
break;
case ConnectionSecurityType::STARTTLS:
$sType = 'TLS';
break;
}
return $sType;
}
/**
* deprecated
*/
@ -228,87 +100,89 @@ class Domain implements \JsonSerializable
bool $bOutAuth, bool $bOutSetSender, bool $bOutUsePhpMail,
string $sWhiteList = '') : self
{
$this->sIncHost = $sIncHost;
$this->iIncPort = $iIncPort;
$this->iIncSecure = $iIncSecure;
$this->bIncShortLogin = $bIncShortLogin;
$this->IMAP->host = $sIncHost;
$this->IMAP->port = $iIncPort;
$this->IMAP->type = $iIncSecure;
$this->IMAP->shortLogin = $bIncShortLogin;
$this->bUseSieve = $bUseSieve;
$this->sSieveHost = $sSieveHost;
$this->iSievePort = $iSievePort;
$this->iSieveSecure = $iSieveSecure;
$this->SMTP->host = $sOutHost;
$this->SMTP->port = $iOutPort;
$this->SMTP->type = $iOutSecure;
$this->SMTP->shortLogin = $bOutShortLogin;
$this->SMTP->useAuth = $bOutAuth;
$this->SMTP->setSender = $bOutSetSender;
$this->SMTP->usePhpMail = $bOutUsePhpMail;
$this->sOutHost = $sOutHost;
$this->iOutPort = $iOutPort;
$this->iOutSecure = $iOutSecure;
$this->bOutShortLogin = $bOutShortLogin;
$this->bOutAuth = $bOutAuth;
$this->bOutSetSender = $bOutSetSender;
$this->bOutUsePhpMail = $bOutUsePhpMail;
$this->Sieve->enabled = $bUseSieve;
$this->Sieve->host = $sSieveHost;
$this->Sieve->port = $iSievePort;
$this->Sieve->type = $iSieveSecure;
$this->sWhiteList = \trim($sWhiteList);
$this->whiteList = \trim($sWhiteList);
$this->Normalize();
return $this;
}
public function Name() : string
{
return $this->sName;
return $this->Name;
}
public function IncHost() : string
{
return $this->sIncHost;
return $this->IMAP->host;
}
public function IncPort() : int
{
return $this->iIncPort;
return $this->IMAP->port;
}
public function IncShortLogin() : bool
{
return $this->bIncShortLogin;
return $this->IMAP->shortLogin;
}
public function UseSieve() : bool
{
return $this->bUseSieve;
return $this->Sieve->enabled;
}
public function OutHost() : string
{
return $this->sOutHost;
return $this->SMTP->host;
}
public function OutPort() : int
{
return $this->iOutPort;
return $this->SMTP->port;
}
public function OutShortLogin() : bool
{
return $this->bOutShortLogin;
return $this->SMTP->shortLogin;
}
public function OutSetSender() : bool
{
return $this->bOutSetSender;
return $this->SMTP->setSender;
}
public function OutUsePhpMail() : bool
{
return $this->bOutUsePhpMail;
return $this->SMTP->usePhpMail;
}
public function SetAliasName(string $sAliasName) : void
{
$this->sAliasName = $sAliasName;
$this->aliasName = $sAliasName;
}
public function ValidateWhiteList(string $sEmail, string $sLogin = '') : bool
{
$sW = \trim($this->sWhiteList);
$sW = \trim($this->whiteList);
if (\strlen($sW))
{
$sEmail = \MailSo\Base\Utils::IdnToUtf8($sEmail, true);
@ -324,39 +198,36 @@ class Domain implements \JsonSerializable
return true;
}
public function ImapSettings() : array
public function ImapSettings() : \MailSo\Imap\Settings
{
return array(
'UseConnect' => true,
'UseAuth' => true,
'Host' => $this->sIncHost,
'Port' => $this->iIncPort,
'Secure' => $this->iIncSecure,
);
return static::mergeGlobalSettings($this->IMAP);
}
public function SmtpSettings() : array
public function SmtpSettings() : \MailSo\Smtp\Settings
{
return array(
'UseConnect' => !$this->bOutUsePhpMail,
'UseAuth' => $this->bOutAuth,
'Host' => $this->sOutHost,
'Port' => $this->iOutPort,
'Secure' => $this->iOutSecure,
'Ehlo' => \MailSo\Smtp\SmtpClient::EhloHelper(),
'UsePhpMail' => $this->bOutUsePhpMail
);
return static::mergeGlobalSettings($this->SMTP);
}
public function SieveSettings() : array
public function SieveSettings() : \MailSo\Sieve\Settings
{
return array(
'UseConnect' => true,
'UseAuth' => true,
'Host' => $this->sSieveHost,
'Port' => $this->iSievePort,
'Secure' => $this->iSieveSecure
);
return static::mergeGlobalSettings($this->Sieve);
}
private static function mergeGlobalSettings(\MailSo\Net\ConnectSettings $oSettings) : \MailSo\Net\ConnectSettings
{
$oConfig = \RainLoop\API::Config();
if ($oConfig->Get('labs', 'sasl_allow_scram_sha', false)) {
// https://github.com/the-djmaze/snappymail/issues/182
\array_push($oSettings->SASLMechanisms, 'SCRAM-SHA3-512', 'SCRAM-SHA-512', 'SCRAM-SHA-256', 'SCRAM-SHA-1');
}
if ($oConfig->Get('labs', 'sasl_allow_cram_md5', false)) {
$oSettings->SASLMechanisms[] = 'CRAM-MD5';
}
if ($oConfig->Get('labs', 'sasl_allow_plain', true)) {
$oSettings->SASLMechanisms[] = 'PLAIN';
}
return $oSettings;
}
/**
@ -364,30 +235,39 @@ class Domain implements \JsonSerializable
*/
public static function fromArray(string $sName, array $aDomain) : ?self
{
$oDomain = null;
if (\strlen($sName) && \strlen($aDomain['imapHost'])) {
$oDomain = new self($sName);
$oDomain->sIncHost = \SnappyMail\IDN::toAscii($aDomain['imapHost']);
$oDomain->iIncPort = (int) $aDomain['imapPort'];
$oDomain->iIncSecure = (int) $aDomain['imapSecure'];
$oDomain->bIncShortLogin = !empty($aDomain['imapShortLogin']);
$oDomain->bUseSieve = !empty($aDomain['useSieve']);
$oDomain->sSieveHost = \SnappyMail\IDN::toAscii($aDomain['sieveHost']);
$oDomain->iSievePort = (int) $aDomain['sievePort'];
$oDomain->iSieveSecure = (int) $aDomain['sieveSecure'];
$oDomain->sOutHost = \SnappyMail\IDN::toAscii($aDomain['smtpHost']);
$oDomain->iOutPort = (int) $aDomain['smtpPort'];
$oDomain->iOutSecure = (int) $aDomain['smtpSecure'];
$oDomain->bOutShortLogin = !empty($aDomain['smtpShortLogin']);
$oDomain->bOutAuth = !empty($aDomain['smtpAuth']);
$oDomain->bOutSetSender = !empty($aDomain['smtpSetSender']);
$oDomain->bOutUsePhpMail = !empty($aDomain['smtpPhpMail']);
$oDomain->sWhiteList = (string) $aDomain['whiteList'];
if (!\strlen($sName)) {
return null;
}
$oDomain = new self($sName);
if (!empty($aDomain['IMAP'])) {
$oDomain->IMAP = \MailSo\Imap\Settings::fromArray($aDomain['IMAP']);
$oDomain->SMTP = \MailSo\Smtp\Settings::fromArray($aDomain['SMTP']);
$oDomain->Sieve = \MailSo\Sieve\Settings::fromArray($aDomain['Sieve']);
$oDomain->whiteList = (string) $aDomain['whiteList'];
} else if (\strlen($aDomain['imapHost'])) {
$oDomain->IMAP->host = $aDomain['imapHost'];
$oDomain->IMAP->port = (int) $aDomain['imapPort'];
$oDomain->IMAP->type = (int) $aDomain['imapSecure'];
$oDomain->IMAP->shortLogin = !empty($aDomain['imapShortLogin']);
$oDomain->Sieve->enabled = !empty($aDomain['useSieve']);
$oDomain->Sieve->host = $aDomain['sieveHost'];
$oDomain->Sieve->port = (int) $aDomain['sievePort'];
$oDomain->Sieve->type = (int) $aDomain['sieveSecure'];
$oDomain->SMTP->host = $aDomain['smtpHost'];
$oDomain->SMTP->port = (int) $aDomain['smtpPort'];
$oDomain->SMTP->type = (int) $aDomain['smtpSecure'];
$oDomain->SMTP->shortLogin = !empty($aDomain['smtpShortLogin']);
$oDomain->SMTP->useAuth = !empty($aDomain['smtpAuth']);
$oDomain->SMTP->setSender = !empty($aDomain['smtpSetSender']);
$oDomain->SMTP->usePhpMail = !empty($aDomain['smtpPhpMail']);
$oDomain->whiteList = (string) $aDomain['whiteList'];
} else {
return null;
}
$oDomain->Normalize();
return $oDomain;
}
@ -396,26 +276,14 @@ class Domain implements \JsonSerializable
{
$aResult = array(
// '@Object' => 'Object/Domain',
'name' => \SnappyMail\IDN::toUtf8($this->sName),
'imapHost' => \SnappyMail\IDN::toUtf8($this->sIncHost),
'imapPort' => $this->iIncPort,
'imapSecure' => $this->iIncSecure,
'imapShortLogin' => $this->bIncShortLogin,
'useSieve' => $this->bUseSieve,
'sieveHost' => \SnappyMail\IDN::toUtf8($this->sSieveHost),
'sievePort' => $this->iSievePort,
'sieveSecure' => $this->iSieveSecure,
'smtpHost' => \SnappyMail\IDN::toUtf8($this->sOutHost),
'smtpPort' => $this->iOutPort,
'smtpSecure' => $this->iOutSecure,
'smtpShortLogin' => $this->bOutShortLogin,
'smtpAuth' => $this->bOutAuth,
'smtpSetSender' => $this->bOutSetSender,
'smtpPhpMail' => $this->bOutUsePhpMail,
'whiteList' => $this->sWhiteList
'name' => $this->Name,
'IMAP' => $this->IMAP,
'SMTP' => $this->SMTP,
'Sieve' => $this->Sieve,
'whiteList' => $this->whiteList
);
if ($this->sAliasName) {
$aResult['aliasName'] = $this->sAliasName;
if ($this->aliasName) {
$aResult['aliasName'] = $this->aliasName;
}
return $aResult;
}

View file

@ -66,22 +66,10 @@ class Domain extends AbstractProvider
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::DomainAlreadyExists);
}
return \RainLoop\Model\Domain::fromArray($sNameForTest ?: $sName, [
'imapHost' => $oActions->GetActionParam('IncHost', ''),
'imapPort' => $oActions->GetActionParam('IncPort', 143),
'imapSecure' => $oActions->GetActionParam('IncSecure', \MailSo\Net\Enumerations\ConnectionSecurityType::NONE),
'imapShortLogin' => $oActions->GetActionParam('IncShortLogin', 0),
'useSieve' => $oActions->GetActionParam('UseSieve', 0),
'sieveHost' => $oActions->GetActionParam('SieveHost', ''),
'sievePort' => $oActions->GetActionParam('SievePort', 4190),
'sieveSecure' => $oActions->GetActionParam('SieveSecure', \MailSo\Net\Enumerations\ConnectionSecurityType::NONE),
'smtpHost' => $oActions->GetActionParam('OutHost', ''),
'smtpPort' => $oActions->GetActionParam('OutPort', 25),
'smtpSecure' => $oActions->GetActionParam('OutSecure', \MailSo\Net\Enumerations\ConnectionSecurityType::NONE),
'smtpShortLogin' => $oActions->GetActionParam('OutShortLogin', 0),
'smtpAuth' => $oActions->GetActionParam('OutAuth', 1),
'smtpSetSender' => $oActions->GetActionParam('OutSetSender', 0),
'smtpPhpMail' => $oActions->GetActionParam('OutUsePhpMail', 0),
'whiteList' => $oActions->GetActionParam('WhiteList', '')
'IMAP' => $oActions->GetActionParam('IMAP'),
'SMTP' => $oActions->GetActionParam('SMTP'),
'Sieve' => $oActions->GetActionParam('Sieve'),
'whiteList' => $oActions->GetActionParam('whiteList')
]);
}
return null;

View file

@ -135,7 +135,6 @@ class DefaultDomain implements DomainInterface
$this->oCacher->Delete(static::wildcardDomainsCacheKey());
}
// \RainLoop\Utils::saveFile($this->sDomainPath.'/'.$sRealFileName.'.ini', $oDomain->ToIniString());
\RainLoop\Utils::saveFile($this->sDomainPath.'/'.$sRealFileName.'.json', \json_encode($oDomain, \JSON_PRETTY_PRINT));
return true;

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Současné heslo",
"LABEL_NEW_PASSWORD": "Nové heslo",
"LABEL_REPEAT_PASSWORD": "Znovu",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Vyžadovat ověření SSL certifikátu (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Vyžadovat ověření SSL certifikátu",
"LABEL_ALLOW_SELF_SIGNED": "Povolit self-signed certifikáty"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "unstable",
"WARNING": "Varování!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Nuværende adgangskode",
"LABEL_NEW_PASSWORD": "Ny adgangskode",
"LABEL_REPEAT_PASSWORD": "Gentag",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Kræv verifikation af brugt SSL certifikat (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Kræv verifikation af brugt SSL certifikat",
"LABEL_ALLOW_SELF_SIGNED": "Tillad selvsignerede certifikater"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "ustabil",
"WARNING": "Advarsel!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Aktuelles Passwort",
"LABEL_NEW_PASSWORD": "Neues Passwort",
"LABEL_REPEAT_PASSWORD": "Wiederholen",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Verlangen, dass das verwendete SSL-Zertifikat signiert ist (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Verlangen, dass das verwendete SSL-Zertifikat signiert ist",
"LABEL_ALLOW_SELF_SIGNED": "Selbst-signierte Zertifikate erlauben"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "Beta",
"UNSTABLE": "Nicht stabil",
"WARNING": "Warnung!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Current password",
"LABEL_NEW_PASSWORD": "New password",
"LABEL_REPEAT_PASSWORD": "Repeat",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Require verification of SSL certificate used (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Require verification of SSL certificate",
"LABEL_ALLOW_SELF_SIGNED": "Allow self signed certificates"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "unstable",
"WARNING": "Warning!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Contraseña actual",
"LABEL_NEW_PASSWORD": "Nueva contraseña",
"LABEL_REPEAT_PASSWORD": "Re-ingresar",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Requerir verificación del certificado SSL (IMAP \/ SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Requerir verificación del certificado SSL",
"LABEL_ALLOW_SELF_SIGNED": "Permitir certificados auto-firmados"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "inestable",
"WARNING": "¡Atención!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "گذرواژه فعلی",
"LABEL_NEW_PASSWORD": "گذرواژه جدید",
"LABEL_REPEAT_PASSWORD": "تکرار",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "به بررسی گواهینامه SSL نیاز داشته باشد (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "به بررسی گواهینامه SSL نیاز داشته باشد",
"LABEL_ALLOW_SELF_SIGNED": "به گواهی‌نامه‌هایی که توسط خودشان امضاء شده‌اند اجازه بده"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "آزمایشی",
"UNSTABLE": "ناپایدار",
"WARNING": "هشدار!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Nykyinen salasana",
"LABEL_NEW_PASSWORD": "Uusi salasana",
"LABEL_REPEAT_PASSWORD": "Toista",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Vaadi SSL sertifikaatin varmistus (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Vaadi SSL sertifikaatin varmistus",
"LABEL_ALLOW_SELF_SIGNED": "Salli itse-allekirjoitetut sertifikaatit"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "epävakaa",
"WARNING": "Varoitus!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Mot de passe actuel",
"LABEL_NEW_PASSWORD": "Nouveau mot de passe",
"LABEL_REPEAT_PASSWORD": "Répéter",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "S'assurer qu'un certificat SSL (IMAP\/SMTP) est utilisé",
"LABEL_REQUIRE_VERIFICATION": "S'assurer qu'un certificat SSL est utilisé",
"LABEL_ALLOW_SELF_SIGNED": "Autoriser les certificats auto-signés"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "bêta",
"UNSTABLE": "instable",
"WARNING": "ATTENTION !"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Jelenlegi jelszó",
"LABEL_NEW_PASSWORD": "Új jelszó",
"LABEL_REPEAT_PASSWORD": "Újra",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "A használt (IMAP\/SMTP) tanúsítvány ellenőrzés megkövetelése",
"LABEL_REQUIRE_VERIFICATION": "A használt tanúsítvány ellenőrzés megkövetelése",
"LABEL_ALLOW_SELF_SIGNED": "Saját aláírt tanúsítványok engedélyezése"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "béta",
"UNSTABLE": "instabil",
"WARNING": "Figyelmeztetés!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Password saat ini",
"LABEL_NEW_PASSWORD": "Password baru",
"LABEL_REPEAT_PASSWORD": "Ulangi",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Diperlukan verifikasi sertifikat SSL dengan (IMAP\/SMTP) ",
"LABEL_REQUIRE_VERIFICATION": "Diperlukan verifikasi sertifikat SSL dengan",
"LABEL_ALLOW_SELF_SIGNED": "Izinkan sertifikat yang dibuat sendiri"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "Tidak stabil",
"WARNING": "Peringatan!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Current password",
"LABEL_NEW_PASSWORD": "New password",
"LABEL_REPEAT_PASSWORD": "Repeat",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Require verification of SSL certificate used (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Require verification of SSL certificate used",
"LABEL_ALLOW_SELF_SIGNED": "Allow self signed certificates"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "unstable",
"WARNING": "Warning!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "現在のパスワード",
"LABEL_NEW_PASSWORD": "新しいパスワード",
"LABEL_REPEAT_PASSWORD": "再入力",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "(IMAP\/SMTP)のSSL証明書の検証を有効にする",
"LABEL_REQUIRE_VERIFICATION": "のSSL証明書の検証を有効にする",
"LABEL_ALLOW_SELF_SIGNED": "自己署名証明書を使う"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "unstable",
"WARNING": "警告!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Dabartinis slaptažodis",
"LABEL_NEW_PASSWORD": "Naujas slaptažodis",
"LABEL_REPEAT_PASSWORD": "Pakartokite",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Reikalauti SSL sertifikato (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Reikalauti SSL sertifikato",
"LABEL_ALLOW_SELF_SIGNED": "Leisti pačių sukurtus sertifikatus"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "nestabilus",
"WARNING": "Dėmesio!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Gjeldende passord",
"LABEL_NEW_PASSWORD": "Nytt passord",
"LABEL_REPEAT_PASSWORD": "Gjenta",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Krev bekreftelse av SSL-sertifikat (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Krev bekreftelse av SSL-sertifikat",
"LABEL_ALLOW_SELF_SIGNED": "Tillat selvutstedt sertifikat"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "ustabil",
"WARNING": "Advarsel!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Huidig wachtwoord",
"LABEL_NEW_PASSWORD": "Nieuw wachtwoord",
"LABEL_REPEAT_PASSWORD": "Herhaal nieuw wachtwoord",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Verificatie van SSL certificaten (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Verificatie van SSL certificaten",
"LABEL_ALLOW_SELF_SIGNED": "Sta zelf ondertekende certificaten toe"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "bèta",
"UNSTABLE": "onstabiel",
"WARNING": "Waarschuwing!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Bieżące hasło",
"LABEL_NEW_PASSWORD": "Nowe hasło",
"LABEL_REPEAT_PASSWORD": "Powtórz hasło",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Wymagaj weryfikacji używanego certyfikatu SSL (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Wymagaj weryfikacji używanego certyfikatu SSL",
"LABEL_ALLOW_SELF_SIGNED": "Zezwól na certyfikaty z podpisem własnym"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "Beta",
"UNSTABLE": "Niestabilne",
"WARNING": "Ostrzeżenie!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Senha atual",
"LABEL_NEW_PASSWORD": "Nova senha",
"LABEL_REPEAT_PASSWORD": "Confirmar nova senha",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Exigir verificação do certificado SSL (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Exigir verificação do certificado SSL",
"LABEL_ALLOW_SELF_SIGNED": "Permitir certificados auto-assinados"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "instável",
"WARNING": "Aviso!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Palavra-passe atual",
"LABEL_NEW_PASSWORD": "Nova palavra-passe",
"LABEL_REPEAT_PASSWORD": "Repetir",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Obrigar a verificação dos certificados SSL utilizados (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Obrigar a verificação dos certificados SSL utilizados",
"LABEL_ALLOW_SELF_SIGNED": "Permitir certificados autoassinados"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "instável",
"WARNING": "Aviso!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Palavra-passe atual",
"LABEL_NEW_PASSWORD": "Nova palavra-passe",
"LABEL_REPEAT_PASSWORD": "Repetir",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Obrigar a verificação dos certificados SSL utilizados (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Obrigar a verificação dos certificados SSL utilizados",
"LABEL_ALLOW_SELF_SIGNED": "Permitir certificados autoassinados"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "instável",
"WARNING": "Aviso!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Текущий пароль",
"LABEL_NEW_PASSWORD": "Новый пароль",
"LABEL_REPEAT_PASSWORD": "Повторить пароль",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Требовать проверку SSL сертификата для IMAP и SMTP",
"LABEL_REQUIRE_VERIFICATION": "Требовать проверку SSL сертификата для",
"LABEL_ALLOW_SELF_SIGNED": "Разрешить cамоподписанные сертификаты"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "unstable",
"WARNING": "Внимание!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Súčasné heslo",
"LABEL_NEW_PASSWORD": "Nové heslo",
"LABEL_REPEAT_PASSWORD": "Opakovať",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Require verification of SSL certificate used (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Require verification of SSL certificate used",
"LABEL_ALLOW_SELF_SIGNED": "Allow self signed certificates"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "nestabilné",
"WARNING": "Upozornenie!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Trenutno geslo",
"LABEL_NEW_PASSWORD": "Novo geslo",
"LABEL_REPEAT_PASSWORD": "Ponovno",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Obvezno overjanje uporabljenega SSL certifikata (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Obvezno overjanje uporabljenega SSL certifikata",
"LABEL_ALLOW_SELF_SIGNED": "Dovoli samopodpisane certifikate"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "nestabilno",
"WARNING": "Pozor!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Nuvarande lösenord",
"LABEL_NEW_PASSWORD": "Nytt lösenord",
"LABEL_REPEAT_PASSWORD": "Upprepa",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "Kräver verifiering av SSL-certifikat som används (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Kräver verifiering av SSL-certifikat som används",
"LABEL_ALLOW_SELF_SIGNED": "Låt självsignerade certifikat"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "beta",
"UNSTABLE": "instabil",
"WARNING": "Varning!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "Mật khẩu hiện tại",
"LABEL_NEW_PASSWORD": "Mật khẩu mới",
"LABEL_REPEAT_PASSWORD": "Lập lại mật khẩu",
"LEGEND_SSL": "Chứng chỉ số SSL",
"LABEL_REQUIRE_VERIFICATION": "Yêu cầu xác minh chứng chỉ SSL được dùng (IMAP\/SMTP)",
"LABEL_REQUIRE_VERIFICATION": "Yêu cầu xác minh chứng chỉ SSL được dùng",
"LABEL_ALLOW_SELF_SIGNED": "Cho phép chứng chỉ tự ký"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "đang thử nghiệm",
"UNSTABLE": "chưa ổn định",
"WARNING": "Cảnh báo!"
},
"ERRORS": {

View file

@ -88,8 +88,7 @@
"LABEL_CURRENT_PASSWORD": "当前密码",
"LABEL_NEW_PASSWORD": "新密码",
"LABEL_REPEAT_PASSWORD": "重复输入新密码",
"LEGEND_SSL": "SSL",
"LABEL_REQUIRE_VERIFICATION": "要求验证 SSL 证书IMAP\/SMTP",
"LABEL_REQUIRE_VERIFICATION": "要求验证 SSL 证书",
"LABEL_ALLOW_SELF_SIGNED": "允许自签名证书"
},
"TAB_PACKAGES": {
@ -158,7 +157,6 @@
},
"HINTS": {
"BETA": "测试版本",
"UNSTABLE": "不稳定版本",
"WARNING": "警告"
},
"ERRORS": {

View file

@ -58,7 +58,7 @@
</div>
</form>
<div class="form-horizontal">
<div class="legend" data-i18n="TAB_SECURITY/LEGEND_SSL"></div>
<div class="legend">SSL/TLS</div>
<div class="control-group">
<div>
<div data-bind="component: {
@ -69,7 +69,6 @@
inline: true
}
}"></div>
<span style="color:red"> (<span data-i18n="HINTS/UNSTABLE"></span>)</span>
<br>
<div data-bind="component: {
name: 'Checkbox',

View file

@ -8,7 +8,7 @@
<span data-i18n="POPUPS_DOMAIN/LABEL_NAME"></span>
<span style="opacity:0.7"> (<span data-i18n="POPUPS_DOMAIN/NAME_HELPER"></span>)</span>
<br>
<input type="text" class="span4" autofocus="" autocomplete="off" autocorrect="off" autocapitalize="off"
<input name="Name" type="text" class="span4" autofocus="" autocomplete="off" autocorrect="off" autocapitalize="off"
data-bind="textInput: name">
<div class="alert-error" data-bind="visible: savingError, text: savingError"></div>
</div>
@ -18,8 +18,8 @@
<div class="form-horizontal domain-form">
<div class="tabs">
<input type="radio" name="helptabs" id="tab-help1" checked>
<label for="tab-help1" role="tab" tabindex="0"
<input type="radio" name="tabs" id="tab-imap" checked>
<label for="tab-imap" role="tab" tabindex="0"
data-bind="css: { 'testing-done': testingDone, 'testing-error': testingImapError }, tooltipErrorTip: testingImapErrorDesc"
data-i18n="POPUPS_DOMAIN/LABEL_IMAP"></label>
<div class="tab-content" role="tabpanel" aria-hidden="false">
@ -27,13 +27,13 @@
<div class="span3">
<span data-i18n="POPUPS_DOMAIN/LABEL_SERVER"></span>
<br>
<input type="text" class="span3" autocomplete="off" autocorrect="off" autocapitalize="off"
<input name="IMAP[host]" type="text" class="span3" autocomplete="off" autocorrect="off" autocapitalize="off"
data-bind="textInput: imapHost, hasfocus: imapHostFocus">
</div>
<div class="span2">
<span data-i18n="POPUPS_DOMAIN/LABEL_SECURE"></span>
<br>
<select class="span2" data-bind="value: imapSecure">
<select name="IMAP[type]" class="span2" data-bind="value: imapType">
<option value="0" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_NONE"></option>
<option value="1" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_SSL"></option>
<option value="2" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_STARTTLS"></option>
@ -42,7 +42,7 @@
<div class="span2">
<span data-i18n="POPUPS_DOMAIN/LABEL_PORT"></span>
<br>
<input type="number" autocomplete="off" autocorrect="off" autocapitalize="off"
<input name="IMAP[port]" type="number" autocomplete="off" autocorrect="off" autocapitalize="off"
style="width:6em" data-bind="textInput: imapPort">
</div>
</div>
@ -56,25 +56,44 @@
}
}"></div>
<span style="opacity:0.7"> (user@domain.com → user)</span>
<h4>SSL/TLS</h4>
<div data-bind="component: {
name: 'Checkbox',
params: {
value: imapSslVerify_peer,
label: 'TAB_SECURITY/LABEL_REQUIRE_VERIFICATION',
inline: true
}
}"></div>
<br>
<div data-bind="component: {
name: 'Checkbox',
params: {
enable: imapSslVerify_peer,
value: imapSslAllow_self_signed,
label: 'TAB_SECURITY/LABEL_ALLOW_SELF_SIGNED'
}
}"></div>
</div>
<input type="radio" name="helptabs" id="tab-help2">
<label for="tab-help2" role="tab" tabindex="0"
<input type="radio" name="tabs" id="tab-smtp">
<label for="tab-smtp" role="tab" tabindex="0"
data-bind="css: { 'testing-done': testingDone, 'testing-error': testingSmtpError }, tooltipErrorTip: testingSmtpErrorDesc"
data-i18n="POPUPS_DOMAIN/LABEL_SMTP"></label>
<div class="tab-content" role="tabpanel" aria-hidden="true">
<div data-bind="visible: !smtpPhpMail()">
<div data-bind="visible: !smtpUsePhpMail()">
<div class="row">
<div class="span3">
<span data-i18n="POPUPS_DOMAIN/LABEL_SERVER"></span>
<br>
<input type="text" class="span3" autocomplete="off" autocorrect="off" autocapitalize="off"
<input name="SMTP[host]" type="text" class="span3" autocomplete="off" autocorrect="off" autocapitalize="off"
data-bind="textInput: smtpHost, hasfocus: smtpHostFocus">
</div>
<div class="span2">
<span data-i18n="POPUPS_DOMAIN/LABEL_SECURE"></span>
<br>
<select class="span2" data-bind="value: smtpSecure">
<select name="SMTP[type]" class="span2" data-bind="value: smtpType">
<option value="0" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_NONE"></option>
<option value="1" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_SSL"></option>
<option value="2" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_STARTTLS"></option>
@ -83,7 +102,7 @@
<div class="span2">
<span data-i18n="POPUPS_DOMAIN/LABEL_PORT"></span>
<br>
<input type="number" autocomplete="off" autocorrect="off" autocapitalize="off"
<input name="SMTP[port]" type="number" autocomplete="off" autocorrect="off" autocapitalize="off"
style="width:6em" data-bind="textInput: smtpPort">
</div>
</div>
@ -101,7 +120,7 @@
name: 'Checkbox',
params: {
label: 'POPUPS_DOMAIN/LABEL_USE_AUTH',
value: smtpAuth
value: smtpUseAuth
}
}"></div>
<br>
@ -119,15 +138,34 @@
name: 'Checkbox',
params: {
label: 'POPUPS_DOMAIN/LABEL_USE_PHP_MAIL',
value: smtpPhpMail,
value: smtpUsePhpMail,
inline: true
}
}"></div>
<span style="color:red"> (<span data-i18n="HINTS/BETA"></span>)</span>
<h4>SSL/TLS</h4>
<div data-bind="component: {
name: 'Checkbox',
params: {
value: smtpSslVerify_peer,
label: 'TAB_SECURITY/LABEL_REQUIRE_VERIFICATION',
inline: true
}
}"></div>
<br>
<div data-bind="component: {
name: 'Checkbox',
params: {
enable: smtpSslVerify_peer,
value: smtpSslAllow_self_signed,
label: 'TAB_SECURITY/LABEL_ALLOW_SELF_SIGNED'
}
}"></div>
</div>
<input type="radio" name="helptabs" id="tab-help3">
<label for="tab-help3" role="tab" tabindex="0"
<input type="radio" name="tabs" id="tab-sieve">
<label for="tab-sieve" role="tab" tabindex="0"
data-bind="css: { 'testing-done': testingDone, 'testing-error': testingSieveError }, tooltipErrorTip: testingSieveErrorDesc">
<i class="icon-filter"></i>
<span data-i18n="POPUPS_DOMAIN/LABEL_SIEVE"></span>
@ -138,29 +176,29 @@
name: 'Checkbox',
params: {
label: 'POPUPS_DOMAIN/LABEL_ALLOW_SIEVE_SCRIPTS',
value: useSieve
value: sieveEnabled
}
}"></div>
</div>
<div data-bind="visible: useSieve">
<div data-bind="visible: sieveEnabled">
<div class="row">
<div class="span3">
<span data-i18n="POPUPS_DOMAIN/LABEL_SERVER"></span>
<br>
<input type="text" class="span3" autocomplete="off" autocorrect="off" autocapitalize="off"
<input name="Sieve[host]" type="text" class="span3" autocomplete="off" autocorrect="off" autocapitalize="off"
data-bind="textInput: sieveHost, hasfocus: sieveHostFocus">
</div>
<div class="span2">
<span data-i18n="POPUPS_DOMAIN/LABEL_SECURE"></span>
<br>
<select class="span2" data-bind="value: sieveSecure">
<select name="Sieve[type]" class="span2" data-bind="value: sieveType">
<option value="0" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_NONE"></option>
<option value="1" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_SSL"></option>
<option value="2" data-i18n="POPUPS_DOMAIN/SECURE_OPTION_STARTTLS"></option>
</select>
</div>
<div class="span2">
<span data-i18n="POPUPS_DOMAIN/LABEL_PORT"></span>
<span name="Sieve[port]" data-i18n="POPUPS_DOMAIN/LABEL_PORT"></span>
<br>
<input type="number" autocomplete="off" autocorrect="off" autocapitalize="off"
style="width:6em" data-bind="textInput: sievePort">
@ -169,8 +207,8 @@
</div>
</div>
<input type="radio" name="helptabs" id="tab-help4">
<label for="tab-help4" role="tab" tabindex="0" data-icon="👥" data-i18n="POPUPS_DOMAIN/BUTTON_WHITE_LIST"></label>
<input type="radio" name="tabs" id="tab-whitelist">
<label for="tab-whitelist" role="tab" tabindex="0" data-icon="👥" data-i18n="POPUPS_DOMAIN/BUTTON_WHITE_LIST"></label>
<div class="tab-content" role="tabpanel" aria-hidden="true">
<div class="alert" data-i18n="POPUPS_DOMAIN/WHITE_LIST_ALERT"></div>
<textarea class="input-xxlarge" style="width: 100%" rows="8" data-bind="value: whiteList" tabindex="-1"></textarea>