diff options
author | Christoph Wurst <christoph@winzerhof-wurst.at> | 2022-07-04 21:29:53 +0300 |
---|---|---|
committer | Christoph Wurst <christoph@winzerhof-wurst.at> | 2022-07-07 16:24:05 +0300 |
commit | 799ee0028d553d46af475bc0499cb1db44864e61 (patch) | |
tree | 007f17e8bbd35a822709a658695210891b3353b2 /lib | |
parent | 77544d3fe16dec880092e143d2b65eeafdc9fbc6 (diff) |
Split auto config and account creation
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Controller/AccountsController.php | 62 | ||||
-rw-r--r-- | lib/Controller/AutoConfigController.php | 89 | ||||
-rw-r--r-- | lib/Service/AutoConfig/AutoConfig.php | 59 | ||||
-rw-r--r-- | lib/Service/AutoConfig/Configuration.php | 59 | ||||
-rw-r--r-- | lib/Service/AutoConfig/ConfigurationDetector.php | 64 | ||||
-rw-r--r-- | lib/Service/AutoConfig/ImapConnectivityTester.php | 99 | ||||
-rw-r--r-- | lib/Service/AutoConfig/ImapConnector.php | 96 | ||||
-rw-r--r-- | lib/Service/AutoConfig/ImapServerDetector.php | 98 | ||||
-rw-r--r-- | lib/Service/AutoConfig/IspDb.php | 116 | ||||
-rw-r--r-- | lib/Service/AutoConfig/IspDbConfigurationDetector.php | 247 | ||||
-rw-r--r-- | lib/Service/AutoConfig/MxRecord.php | 14 | ||||
-rw-r--r-- | lib/Service/AutoConfig/ServerConfiguration.php | 59 | ||||
-rw-r--r-- | lib/Service/AutoConfig/SmtpConnectivityTester.php | 143 | ||||
-rw-r--r-- | lib/Service/AutoConfig/SmtpServerDetector.php | 103 | ||||
-rw-r--r-- | lib/Service/SetupService.php | 30 |
15 files changed, 301 insertions, 1037 deletions
diff --git a/lib/Controller/AccountsController.php b/lib/Controller/AccountsController.php index 745fcb6b3..3a20d7d81 100644 --- a/lib/Controller/AccountsController.php +++ b/lib/Controller/AccountsController.php @@ -29,7 +29,6 @@ declare(strict_types=1); namespace OCA\Mail\Controller; -use Exception; use Horde_Imap_Client; use OCA\Mail\Contracts\IMailManager; use OCA\Mail\Contracts\IMailTransmission; @@ -141,7 +140,6 @@ class AccountsController extends Controller { * @param int $id * @param string $accountName * @param string $emailAddress - * @param string $password * @param string $imapHost * @param int $imapPort * @param string $imapSslMode @@ -152,16 +150,13 @@ class AccountsController extends Controller { * @param string $smtpSslMode * @param string $smtpUser * @param string $smtpPassword - * @param bool $autoDetect * * @return JSONResponse * @throws ClientException */ public function update(int $id, - bool $autoDetect, string $accountName, string $emailAddress, - string $password = null, string $imapHost = null, int $imapPort = null, string $imapSslMode = null, @@ -179,28 +174,26 @@ class AccountsController extends Controller { return new JSONResponse([], Http::STATUS_BAD_REQUEST); } - $account = null; - $errorMessage = null; try { - if ($autoDetect) { - $account = $this->setup->createNewAutoConfiguredAccount($accountName, $emailAddress, $password); - } else { - $account = $this->setup->createNewAccount($accountName, $emailAddress, $imapHost, $imapPort, $imapSslMode, $imapUser, $imapPassword, $smtpHost, $smtpPort, $smtpSslMode, $smtpUser, $smtpPassword, $this->currentUserId, $id); - } - } catch (Exception $ex) { - $errorMessage = $ex->getMessage(); - } + return \OCA\Mail\Http\JsonResponse::success( + $this->setup->createNewAccount($accountName, $emailAddress, $imapHost, $imapPort, $imapSslMode, $imapUser, $imapPassword, $smtpHost, $smtpPort, $smtpSslMode, $smtpUser, $smtpPassword, $this->currentUserId, $id) + ); + } catch (CouldNotConnectException $e) { + $data = [ + 'error' => $e->getReason(), + 'service' => $e->getService(), + 'host' => $e->getHost(), + 'port' => $e->getPort(), + ]; - if (is_null($account)) { - if ($autoDetect) { - throw new ClientException($this->l10n->t('Auto detect failed. Please use manual mode.')); - } else { - $this->logger->error('Updating account failed: ' . $errorMessage); - throw new ClientException($this->l10n->t('Updating account failed: ') . $errorMessage); - } + $this->logger->info('Creating account failed: ' . $e->getMessage(), $data); + return \OCA\Mail\Http\JsonResponse::fail($data); + } catch (ServiceException $e) { + $this->logger->error('Creating account failed: ' . $e->getMessage(), [ + 'exception' => $e, + ]); + return \OCA\Mail\Http\JsonResponse::error('Could not create account'); } - - return new JSONResponse($account); } /** @@ -299,7 +292,6 @@ class AccountsController extends Controller { * * @param string $accountName * @param string $emailAddress - * @param string $password * @param string $imapHost * @param int $imapPort * @param string $imapSslMode @@ -310,17 +302,14 @@ class AccountsController extends Controller { * @param string $smtpSslMode * @param string $smtpUser * @param string $smtpPassword - * @param bool $autoDetect * * @return JSONResponse */ - public function create(string $accountName, string $emailAddress, string $password = null, string $imapHost = null, int $imapPort = null, string $imapSslMode = null, string $imapUser = null, string $imapPassword = null, string $smtpHost = null, int $smtpPort = null, string $smtpSslMode = null, string $smtpUser = null, string $smtpPassword = null, bool $autoDetect = true): JSONResponse { + public function create(string $accountName, string $emailAddress, string $imapHost = null, int $imapPort = null, string $imapSslMode = null, string $imapUser = null, string $imapPassword = null, string $smtpHost = null, int $smtpPort = null, string $smtpSslMode = null, string $smtpUser = null, string $smtpPassword = null): JSONResponse { try { - if ($autoDetect) { - $account = $this->setup->createNewAutoConfiguredAccount($accountName, $emailAddress, $password); - } else { - $account = $this->setup->createNewAccount($accountName, $emailAddress, $imapHost, $imapPort, $imapSslMode, $imapUser, $imapPassword, $smtpHost, $smtpPort, $smtpSslMode, $smtpUser, $smtpPassword, $this->currentUserId); - } + return \OCA\Mail\Http\JsonResponse::success( + $this->setup->createNewAccount($accountName, $emailAddress, $imapHost, $imapPort, $imapSslMode, $imapUser, $imapPassword, $smtpHost, $smtpPort, $smtpSslMode, $smtpUser, $smtpPassword, $this->currentUserId), Http::STATUS_CREATED + ); } catch (CouldNotConnectException $e) { $data = [ 'error' => $e->getReason(), @@ -337,15 +326,6 @@ class AccountsController extends Controller { ]); return \OCA\Mail\Http\JsonResponse::error('Could not create account'); } - - if (is_null($account)) { - return \OCA\Mail\Http\JsonResponse::fail([ - 'error' => 'AUTOCONFIG_FAILED', - 'message' => $this->l10n->t('Auto detect failed. Please use manual mode.'), - ]); - } - - return \OCA\Mail\Http\JsonResponse::success($account, Http::STATUS_CREATED); } /** diff --git a/lib/Controller/AutoConfigController.php b/lib/Controller/AutoConfigController.php new file mode 100644 index 000000000..796f7a42a --- /dev/null +++ b/lib/Controller/AutoConfigController.php @@ -0,0 +1,89 @@ +<?php + +declare(strict_types=1); + +/* + * @copyright 2022 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2022 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +namespace OCA\Mail\Controller; + +use Horde_Mail_Rfc822_Address; +use OCA\Mail\AppInfo\Application; +use OCA\Mail\Http\JsonResponse; +use OCA\Mail\Service\AutoConfig\ConnectivityTester; +use OCA\Mail\Service\AutoConfig\IspDb; +use OCA\Mail\Service\AutoConfig\MxRecord; +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http; +use OCP\IRequest; +use function in_array; + +class AutoConfigController extends Controller { + private IspDb $ispDb; + private MxRecord $mxRecord; + private ConnectivityTester $connectivityTester; + + public function __construct(IRequest $request, + IspDb $ispDb, + MxRecord $mxRecord, + ConnectivityTester $connectivityTester) { + parent::__construct(Application::APP_ID, $request); + $this->ispDb = $ispDb; + $this->mxRecord = $mxRecord; + $this->connectivityTester = $connectivityTester; + } + + /** + * @param string $email + * + * @NoAdminRequired + * @TrapError + * + * @return JsonResponse + */ + public function queryIspdb(string $email): JsonResponse { + $rfc822Address = new Horde_Mail_Rfc822_Address($email); + if (!$rfc822Address->valid) { + return JsonResponse::fail('Invalid email address', Http::STATUS_UNPROCESSABLE_ENTITY); + } + $config = $this->ispDb->query($rfc822Address->host, $rfc822Address); + return JsonResponse::success($config); + } + + public function queryMx(string $email): JsonResponse { + $rfc822Address = new Horde_Mail_Rfc822_Address($email); + if (!$rfc822Address->valid) { + return JsonResponse::fail('Invalid email address', Http::STATUS_UNPROCESSABLE_ENTITY); + } + return JsonResponse::success( + $this->mxRecord->query($rfc822Address->host), + ); + } + + public function testConnectivity(string $host, int $port): JsonResponse { + if (!in_array($port, [143, 993, 465, 587])) { + return JsonResponse::fail('Port not allowed'); + } + return JsonResponse::success( + $this->connectivityTester->canConnect($host, $port), + ); + } +} diff --git a/lib/Service/AutoConfig/AutoConfig.php b/lib/Service/AutoConfig/AutoConfig.php deleted file mode 100644 index 9166a638b..000000000 --- a/lib/Service/AutoConfig/AutoConfig.php +++ /dev/null @@ -1,59 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @author Bernhard Scheirle <bernhard+git@scheirle.de> - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * - * Mail - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OCA\Mail\Service\AutoConfig; - -use OCA\Mail\Db\MailAccount; - -class AutoConfig { - - /** @var IspDbConfigurationDetector */ - private $ispDbDetector; - - /** @var ConfigurationDetector */ - private $configDetector; - - /** - * @param IspDbConfigurationDetector $ispDbDetector - * @param ConfigurationDetector $configDetector - */ - public function __construct(IspDbConfigurationDetector $ispDbDetector, ConfigurationDetector $configDetector) { - $this->ispDbDetector = $ispDbDetector; - $this->configDetector = $configDetector; - } - - /** - * @param string $email - * @param string $password - * @param string $name - * @return null|MailAccount - */ - public function createAutoDetected($email, $password, $name) { - $account = $this->ispDbDetector->detectImapAndSmtp($email, $password, $name); - if (!is_null($account)) { - return $account; - } - return $this->configDetector->detectImapAndSmtp($email, $password, $name); - } -} diff --git a/lib/Service/AutoConfig/Configuration.php b/lib/Service/AutoConfig/Configuration.php new file mode 100644 index 000000000..e8556de98 --- /dev/null +++ b/lib/Service/AutoConfig/Configuration.php @@ -0,0 +1,59 @@ +<?php + +declare(strict_types=1); + +/* + * @copyright 2022 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2022 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +namespace OCA\Mail\Service\AutoConfig; + +use JsonSerializable; +use ReturnTypeWillChange; + +/** + * @psalm-immutable + */ +class Configuration implements JsonSerializable { + private ?ServerConfiguration $imapConfig; + private ?ServerConfiguration $smtpConfig; + + public function __construct(?ServerConfiguration $imapConfig, + ?ServerConfiguration $smtpConfig) { + $this->imapConfig = $imapConfig; + $this->smtpConfig = $smtpConfig; + } + + #[ReturnTypeWillChange] + public function jsonSerialize() { + return [ + 'imapConfig' => $this->imapConfig, + 'smtpConfig' => $this->smtpConfig, + ]; + } + + public function getImapConfig(): ?ServerConfiguration { + return $this->imapConfig; + } + + public function getSmtpConfig(): ?ServerConfiguration { + return $this->smtpConfig; + } +} diff --git a/lib/Service/AutoConfig/ConfigurationDetector.php b/lib/Service/AutoConfig/ConfigurationDetector.php deleted file mode 100644 index 4776f4dd1..000000000 --- a/lib/Service/AutoConfig/ConfigurationDetector.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @copyright 2017 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @author 2017 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -namespace OCA\Mail\Service\AutoConfig; - -use OCA\Mail\Db\MailAccount; - -class ConfigurationDetector { - - /** @var ImapServerDetector */ - private $imapServerDetector; - - /** @var SmtpServerDetector */ - private $smtpServerDetector; - - /** - * @param ImapServerDetector $imapServerDetector - * @param SmtpServerDetector $smtpServerDetector - */ - public function __construct(ImapServerDetector $imapServerDetector, SmtpServerDetector $smtpServerDetector) { - $this->imapServerDetector = $imapServerDetector; - $this->smtpServerDetector = $smtpServerDetector; - } - - /** - * @param string $email - * @param string $password - * @param string $name - * @return null|MailAccount - */ - public function detectImapAndSmtp(string $email, string $password, string $name) { - $account = $this->imapServerDetector->detect($email, $password, $name); - if (is_null($account)) { - return null; - } - - $this->smtpServerDetector->detect($account, $email, $password); - - return $account; - } -} diff --git a/lib/Service/AutoConfig/ImapConnectivityTester.php b/lib/Service/AutoConfig/ImapConnectivityTester.php deleted file mode 100644 index ac0a70ec5..000000000 --- a/lib/Service/AutoConfig/ImapConnectivityTester.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * - * Mail - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OCA\Mail\Service\AutoConfig; - -use Horde_Imap_Client_Exception; -use OCA\Mail\Db\MailAccount; -use Psr\Log\LoggerInterface; - -class ImapConnectivityTester { - - /** @var ImapConnector */ - private $imapConnector; - - /** @var ConnectivityTester */ - private $connectivityTester; - - /** @var string|null */ - private $userId; - - /** @var LoggerInterface */ - private $logger; - - /** - * @param ImapConnector $imapConnector - * @param ConnectivityTester $connectivityTester - * @param string $UserId - * @param LoggerInterface $logger - */ - public function __construct(ImapConnector $imapConnector, - ConnectivityTester $connectivityTester, - ?string $UserId, - LoggerInterface $logger) { - $this->imapConnector = $imapConnector; - $this->connectivityTester = $connectivityTester; - $this->userId = $UserId; - $this->logger = $logger; - } - - /** - * @param string $email - * @param string $host - * @param string|string[] $users - * @param string $password - * @param string $name - * @return MailAccount|null - */ - public function test(string $email, string $host, $users, string $password, string $name) { - if (!is_array($users)) { - $users = [$users]; - } - - $ports = [143, 993]; - $encryptionProtocols = ['ssl', 'tls', 'none']; - $hostPrefixes = ['', 'imap.']; - foreach ($hostPrefixes as $hostPrefix) { - $url = $hostPrefix . $host; - if (gethostbyname($url) === $url) { - continue; - } - foreach ($ports as $port) { - if (!$this->connectivityTester->canConnect($url, $port)) { - continue; - } - foreach ($encryptionProtocols as $encryptionProtocol) { - foreach ($users as $user) { - try { - return $this->imapConnector->connect($email, $password, $name, $host, $port, $encryptionProtocol, $user); - } catch (Horde_Imap_Client_Exception $e) { - $error = $e->getMessage(); - $this->logger->info("Test-Account-Failed: $this->userId, $url, $port, $user, $encryptionProtocol -> $error"); - } - } - } - } - } - return null; - } -} diff --git a/lib/Service/AutoConfig/ImapConnector.php b/lib/Service/AutoConfig/ImapConnector.php deleted file mode 100644 index 6407f338f..000000000 --- a/lib/Service/AutoConfig/ImapConnector.php +++ /dev/null @@ -1,96 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * - * Mail - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OCA\Mail\Service\AutoConfig; - -use OCA\Mail\IMAP\IMAPClientFactory; -use OCP\Security\ICrypto; -use OCA\Mail\Account; -use OCA\Mail\Db\MailAccount; -use Psr\Log\LoggerInterface; - -class ImapConnector { - - /** @var ICrypto */ - private $crypto; - - /** @var LoggerInterface */ - private $logger; - - /** @var string */ - private $userId; - - /** @var IMAPClientFactory */ - private $clientFactory; - - public function __construct(ICrypto $crypto, - LoggerInterface $logger, - IMAPClientFactory $clientFactory, - ?string $UserId) { - $this->crypto = $crypto; - $this->logger = $logger; - $this->userId = $UserId; - $this->clientFactory = $clientFactory; - } - - /** - * @param string $email - * @param string $password - * @param string $name - * @param string $host - * @param int $port - * @param string $encryptionProtocol - * @param string $user - * @return MailAccount - * - * @throws \Horde_Imap_Client_Exception - */ - public function connect(string $email, - string $password, - string $name, - string $host, - int $port, - string $encryptionProtocol, - string $user): MailAccount { - $account = new MailAccount(); - $account->setUserId($this->userId); - $account->setName($name); - $account->setEmail($email); - $account->setInboundHost($host); - $account->setInboundPort($port); - $account->setInboundSslMode($encryptionProtocol); - $account->setInboundUser($user); - $password = $this->crypto->encrypt($password); - $account->setInboundPassword($password); - - $a = new Account($account); - $client = $this->clientFactory->getClient($a); - try { - $client->login(); - $this->logger->info("Test-Account-Successful: $this->userId, $host, $port, $user, $encryptionProtocol"); - return $account; - } finally { - $client->logout(); - } - } -} diff --git a/lib/Service/AutoConfig/ImapServerDetector.php b/lib/Service/AutoConfig/ImapServerDetector.php deleted file mode 100644 index 8a98222cf..000000000 --- a/lib/Service/AutoConfig/ImapServerDetector.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * - * Mail - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OCA\Mail\Service\AutoConfig; - -use OCA\Mail\Db\MailAccount; - -class ImapServerDetector { - - /** @var MxRecord */ - private $mxRecord; - - /** @var ImapConnectivityTester */ - private $imapConnectivityTester; - - /** - * @param MxRecord $mxRecord - * @param ImapConnectivityTester $imapTester - */ - public function __construct(MxRecord $mxRecord, - ImapConnectivityTester $imapTester) { - $this->mxRecord = $mxRecord; - $this->imapConnectivityTester = $imapTester; - } - - /** - * @param string $email - * @param string $password - * @param string $name - * @return MailAccount|null - */ - public function detect(string $email, - string $password, - string $name) { - // splitting the email address into user and host part - // TODO: use horde libs for email address parsing - [$user, $host] = explode("@", $email); - - /* - * Try to get the mx record for the email address - */ - $mxHosts = $this->mxRecord->query($host); - if ($mxHosts) { - // also test the parent domain - $toTest = $this->mxRecord->getSanitizedRecords($mxHosts); - foreach ($toTest as $mxHost) { - $result = $this->imapConnectivityTester->test( - $email, - $mxHost, - [ - $user, - $email - ], - $password, - $name - ); - if ($result) { - return $result; - } - } - } - - /* - * IMAP login with full email address as user - * works for a lot of providers (e.g. Google Mail) - */ - return $this->imapConnectivityTester->test( - $email, - $host, - [ - $user, - $email - ], - $password, - $name - ); - } -} diff --git a/lib/Service/AutoConfig/IspDb.php b/lib/Service/AutoConfig/IspDb.php index 53c601266..4f57ccb2e 100644 --- a/lib/Service/AutoConfig/IspDb.php +++ b/lib/Service/AutoConfig/IspDb.php @@ -26,15 +26,16 @@ declare(strict_types=1); namespace OCA\Mail\Service\AutoConfig; use Exception; +use Horde_Mail_Rfc822_Address; use OCP\Http\Client\IClient; use OCP\Http\Client\IClientService; use Psr\Log\LoggerInterface; +use SimpleXMLElement; +use function str_replace; +use function strtolower; class IspDb { - /** @var string[] */ - private const SUPPORTED_TYPES = ['imap', 'smtp']; - /** @var IClient */ private $client; @@ -44,9 +45,11 @@ class IspDb { /** @returns string[] */ public function getUrls(): array { return [ - '{SCHEME}://autoconfig.{DOMAIN}/mail/config-v1.1.xml?emailaddress={EMAIL}', - '{SCHEME}://{DOMAIN}/.well-known/autoconfig/mail/config-v1.1.xml?emailaddress={EMAIL}', + 'https://autoconfig.{DOMAIN}/mail/config-v1.1.xml?emailaddress={EMAIL}', + 'https://{DOMAIN}/.well-known/autoconfig/mail/config-v1.1.xml?emailaddress={EMAIL}', 'https://autoconfig.thunderbird.net/v1.1/{DOMAIN}', + 'http://autoconfig.{DOMAIN}/mail/config-v1.1.xml?emailaddress={EMAIL}', // insecure fallback 1 + 'http://{DOMAIN}/.well-known/autoconfig/mail/config-v1.1.xml?emailaddress={EMAIL}', // insecure fallback 2 ]; } @@ -58,7 +61,7 @@ class IspDb { /** * Query IspDb for the given url */ - private function queryUrl(string $url): array { + private function queryUrl(string $url, Horde_Mail_Rfc822_Address $email): ?Configuration { try { $xml = $this->client->get($url, [ 'timeout' => 7, @@ -67,7 +70,7 @@ class IspDb { $this->logger->debug('IsbDb: <' . $url . '> failed with "' . $e->getMessage() . '"', [ 'exception' => $e, ]); - return []; + return null; } libxml_use_internal_errors(true); @@ -78,43 +81,71 @@ class IspDb { foreach ($errors as $error) { $this->logger->debug("ISP DB returned an erroneous XML: " . $error->message); } - return []; + return null; } - $provider = [ - 'displayName' => (string)$data->emailProvider->displayName, + $serverConfigs = [ 'imap' => [], 'smtp' => [], ]; foreach ($data->emailProvider->incomingServer as $server) { $type = (string)$server['type']; - if (in_array($type, self::SUPPORTED_TYPES)) { - $provider[$type][] = $this->convertServerElement($server); + if ($type === 'imap') { + $serverConfigs[$type][] = $this->convertServerElement($server, $email); } } - foreach ($data->emailProvider->outgoingServer as $server) { $type = (string)$server['type']; - if (in_array($type, self::SUPPORTED_TYPES)) { - $provider[$type][] = $this->convertServerElement($server); + if ($type === 'smtp') { + $serverConfigs[$type][] = $this->convertServerElement($server, $email); } } - return $provider; + if (empty($serverConfigs['imap']) && empty($serverConfigs['smtp'])) { + return null; + } + return new Configuration( + $serverConfigs['imap'][0] ?? null, + $serverConfigs['smtp'][0] ?? null, + ); + } + + private function mapSocketTypeToSecurity($type): string { + $lowerType = strtolower($type); + if ($lowerType === 'ssl') { + return 'ssl'; + } + if ($lowerType === 'starttls' || $lowerType === 'tls') { + return 'tls'; + } + return 'none'; } /** - * Convert an incomingServer and outgoingServer xml element to array. + * Convert an incomingServer or outgoingServer xml element + * + * Ref https://wiki.mozilla.org/Thunderbird:Autoconfiguration:ConfigFileFormat */ - private function convertServerElement(\SimpleXMLElement $server): array { - return [ - 'hostname' => (string)$server->hostname, - 'port' => (int)$server->port, - 'socketType' => (string)$server->socketType, - 'username' => (string)$server->username, - 'authentication' => (string)$server->authentication, - ]; + private function convertServerElement(SimpleXMLElement $server, Horde_Mail_Rfc822_Address $email): ServerConfiguration { + return new ServerConfiguration( + str_replace( + [ + '%EMAILADDRESS%', + '%EMAILLOCALPART%', + '%EMAILDOMAIN%', + ], + [ + $email->bare_address, + $email->personal, + $email->host, + ], + (string)$server->username + ), + (string)$server->hostname, + (int)$server->port, + $this->mapSocketTypeToSecurity((string)$server->socketType), + ); } /** @@ -122,41 +153,26 @@ class IspDb { * @param bool $tryMx * @return array */ - public function query(string $domain, string $email, bool $tryMx = true): array { + public function query(string $domain, Horde_Mail_Rfc822_Address $email, bool $tryMx = true): ?Configuration { $this->logger->debug("IsbDb: querying <$domain>"); - if (strpos($domain, '@') !== false) { - // TODO: use horde mail address parsing instead - [, $domain] = explode('@', $domain); - } - $provider = []; + $config = null; foreach ($this->getUrls() as $url) { - $url = str_replace(['{DOMAIN}', '{EMAIL}'], [$domain, $email], $url); - if (strpos($url, '{SCHEME}') !== false) { - foreach (['https', 'http'] as $scheme) { - $completeurl = str_replace('{SCHEME}', $scheme, $url); - $this->logger->debug("IsbDb: querying <$domain> via <$completeurl>"); - $provider = $this->queryUrl($completeurl); - if (!empty($provider)) { - return $provider; - } - } - } else { - $this->logger->debug("IsbDb: querying <$domain> via <$url>"); - $provider = $this->queryUrl($url); - if (!empty($provider)) { - return $provider; - } + $url = str_replace(['{DOMAIN}', '{EMAIL}'], [$domain, $email->bare_address], $url); + $this->logger->debug("IsbDb: querying <$domain> via <$url>"); + $config = $this->queryUrl($url, $email); + if ($config !== null) { + return $config; } } if ($tryMx && ($dns = dns_get_record($domain, DNS_MX))) { $domain = $dns[0]['target']; - if (!($provider = $this->query($domain, $email, false))) { + if (!($config = $this->query($domain, $email, false))) { [, $domain] = explode('.', $domain, 2); - $provider = $this->query($domain, $email, false); + $config = $this->query($domain, $email, false); } } - return $provider; + return $config; } } diff --git a/lib/Service/AutoConfig/IspDbConfigurationDetector.php b/lib/Service/AutoConfig/IspDbConfigurationDetector.php deleted file mode 100644 index d53b162b1..000000000 --- a/lib/Service/AutoConfig/IspDbConfigurationDetector.php +++ /dev/null @@ -1,247 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @author 20178 Christoph Wurst <christoph@winzerhof-wurst.at> - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - */ - -namespace OCA\Mail\Service\AutoConfig; - -use Horde_Imap_Client_Exception; -use Horde_Mail_Exception; -use Horde_Mail_Transport_Smtphorde; -use OCA\Mail\Account; -use OCA\Mail\Db\MailAccount; -use OCA\Mail\SMTP\SmtpClientFactory; -use OCP\Security\ICrypto; -use Psr\Log\LoggerInterface; - -class IspDbConfigurationDetector { - - /** @var string */ - private $UserId; - - /** @var LoggerInterface */ - private $logger; - - /** @var string */ - private $userId; - - /** @var ICrypto */ - private $crypto; - - /** @var IspDb */ - private $ispDb; - - /** @var ImapConnector */ - private $imapConnector; - - /** @var SmtpClientFactory */ - private $smtpClientFactory; - - /** - * @param LoggerInterface $logger - * @param string|null $UserId - * @param ICrypto $crypto - * @param IspDb $ispDb - * @param ImapConnector $imapConnector - * @param SmtpClientFactory $smtpClientFactory - */ - public function __construct(LoggerInterface $logger, - ?string $UserId, - ICrypto $crypto, - IspDb $ispDb, - ImapConnector $imapConnector, - SmtpClientFactory $smtpClientFactory) { - $this->logger = $logger; - $this->UserId = $UserId; - $this->ispDb = $ispDb; - $this->crypto = $crypto; - $this->imapConnector = $imapConnector; - $this->smtpClientFactory = $smtpClientFactory; - } - - /** - * @param string $email - * @param string $password - * @param string $name - * @return MailAccount|null - */ - public function detectImapAndSmtp(string $email, string $password, string $name) { - // splitting the email address into user and host part - // TODO: use horde libs for email address parsing - [, $host] = explode("@", $email); - - $ispdb = $this->ispDb->query($host, $email); - - if (empty($ispdb)) { - // Nothing to detect - return null; - } - - $account = $this->detectImap($ispdb, $email, $password, $name); - - // If IMAP detection failed we don't even try SMTP - if (is_null($account)) { - return null; - } - - if ($this->detectSmtp($ispdb, $account, $email, $password)) { - return $account; - } - - // IMAP detection succeeded, but SMTP failed - return null; - } - - /** - * @param array $ispdb - * @param string $email - * @param string $password - * @param string $name - * @return MailAccount|null - */ - private function detectImap(array $ispdb, string $email, string $password, string $name) { - if (!isset($ispdb['imap'])) { - // Nothing to detect - return null; - } - - foreach ($ispdb['imap'] as $imap) { - $account = $this->testImapConfiguration($imap, $email, $password, $name); - if (!is_null($account)) { - return $account; - } - } - - return null; - } - - /** - * @param array $imap - * @param string $email - * @param string $password - * @param string $name - * @return MailAccount|null - */ - private function testImapConfiguration(array $imap, string $email, string $password, string $name) { - $host = $imap['hostname']; - $port = (int) $imap['port']; - $encryptionProtocol = 'none'; - if ($imap['socketType'] === 'SSL') { - $encryptionProtocol = 'ssl'; - } - if ($imap['socketType'] === 'STARTTLS') { - $encryptionProtocol = 'tls'; - } - if ($imap['username'] === '%EMAILADDRESS%') { - $user = $email; - } elseif ($imap['username'] === '%EMAILLOCALPART%') { - [$user,] = explode("@", $email); - } elseif (empty($imap['username'])) { - $this->logger->info("imap username is either an invalid placeholder or is empty"); - return null; - } else { - $user = $imap['username']; - } - - try { - return $this->imapConnector->connect($email, $password, $name, $host, $port, $encryptionProtocol, $user); - } catch (Horde_Imap_Client_Exception $e) { - $error = $e->getMessage(); - $this->logger->info("Test-Account-Failed: $this->userId, $host, $port, $user, $encryptionProtocol -> $error"); - } - - return null; - } - - /** - * @param array $ispdb - * @param MailAccount $account - * @param string $email - * @param string $password - * - * @return bool|null - */ - private function detectSmtp(array $ispdb, MailAccount $account, string $email, string $password): ?bool { - if (!isset($ispdb['smtp'])) { - // Nothing to detect - return null; - } - - foreach ($ispdb['smtp'] as $smtp) { - $detected = $this->testSmtpConfiguration($smtp, $account, $email, $password); - if ($detected) { - return true; - } - } - - return false; - } - - /** - * @param array $smtp - * @param MailAccount $account - * @param string $email - * @param string $password - * - * @return bool|null - */ - private function testSmtpConfiguration(array $smtp, MailAccount $account, string $email, string $password): ?bool { - try { - if ($smtp['username'] === '%EMAILADDRESS%') { - $user = $email; - } elseif ($smtp['username'] === '%EMAILLOCALPART%') { - [$user,] = explode("@", $email); - } elseif (empty($smtp['username'])) { - $this->logger->info("smtp username is either an unknown placeholder or is empty"); - return null; - } else { - $user = $smtp['username']; - } - - $account->setOutboundHost($smtp['hostname']); - $account->setOutboundPort($smtp['port']); - $account->setOutboundPassword($this->crypto->encrypt($password)); - $account->setOutboundUser($user); - - /** mapping 'STARTTLS' expected by e.g. Thunderbird to 'tls' used by mail app */ - if (strtolower($smtp['socketType']) === 'starttls') { - $account->setOutboundSslMode('tls'); - } else { - $account->setOutboundSslMode(strtolower($smtp['socketType'])); - } - - $a = new Account($account); - $transport = $this->smtpClientFactory->create($a); - if ($transport instanceof Horde_Mail_Transport_Smtphorde) { - $transport->getSMTPObject(); - } - - return true; - } catch (Horde_Mail_Exception $ex) { - $error = $ex->getMessage(); - $this->logger->info("Test-Account-Failed(smtp): $error"); - } - return false; - } -} diff --git a/lib/Service/AutoConfig/MxRecord.php b/lib/Service/AutoConfig/MxRecord.php index 42b36df86..b9d2540e3 100644 --- a/lib/Service/AutoConfig/MxRecord.php +++ b/lib/Service/AutoConfig/MxRecord.php @@ -36,25 +36,23 @@ class MxRecord { /** * @param $host - * @return false|array + * @return string[] */ public function query(string $host) { if (getmxrr($host, $mxRecords, $mxWeight) === false) { $this->logger->debug("no MX records for host <$host> found"); - return false; + return []; } $mxRecords = array_filter($mxRecords, function ($record) { return !empty($record); }); + $this->logger->debug("found " . count($mxRecords) . " MX records for host <$host>"); if (empty(($mxRecords))) { - $this->logger->debug("all records for <$host>'s MX are empty"); - return false; + return []; } - $this->logger->debug("found " . count($mxRecords) . " MX records for host <$host>"); - // TODO: sort by weight - return $mxRecords; + return $this->sanitizedRecords($mxRecords); } private function stripSubdomain(string $domain): string { @@ -66,7 +64,7 @@ class MxRecord { return $second . '.' . $top; } - public function getSanitizedRecords(array $mxHosts): array { + private function sanitizedRecords(array $mxHosts): array { return array_unique(array_merge($mxHosts, array_map([$this, 'stripSubdomain'], $mxHosts))); } } diff --git a/lib/Service/AutoConfig/ServerConfiguration.php b/lib/Service/AutoConfig/ServerConfiguration.php new file mode 100644 index 000000000..84e031a8d --- /dev/null +++ b/lib/Service/AutoConfig/ServerConfiguration.php @@ -0,0 +1,59 @@ +<?php + +declare(strict_types=1); + +/* + * @copyright 2022 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2022 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +namespace OCA\Mail\Service\AutoConfig; + +use JsonSerializable; +use ReturnTypeWillChange; + +/** + * @psalm-immutable + */ +class ServerConfiguration implements JsonSerializable { + private string $username; + private string $host; + private int $port; + private string $security; + + public function __construct(string $username, + string $host, + int $port, + string $security) { + $this->username = $username; + $this->host = $host; + $this->port = $port; + $this->security = $security; + } + + #[ReturnTypeWillChange] + public function jsonSerialize() { + return [ + 'username' => $this->username, + 'host' => $this->host, + 'port' => $this->port, + 'security' => $this->security, + ]; + } +} diff --git a/lib/Service/AutoConfig/SmtpConnectivityTester.php b/lib/Service/AutoConfig/SmtpConnectivityTester.php deleted file mode 100644 index b17938db4..000000000 --- a/lib/Service/AutoConfig/SmtpConnectivityTester.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * - * Mail - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OCA\Mail\Service\AutoConfig; - -use Exception; -use Horde_Mail_Transport_Smtphorde; -use OCA\Mail\Account; -use OCA\Mail\Db\MailAccount; -use OCA\Mail\SMTP\SmtpClientFactory; -use OCP\Security\ICrypto; -use Psr\Log\LoggerInterface; - -class SmtpConnectivityTester { - - /** @var ConnectivityTester */ - private $connectivityTester; - - /** @var ICrypto */ - private $crypto; - - /** @var SmtpClientFactory */ - private $clientFactory; - - /** @var LoggerInterface */ - private $logger; - - /** @var string */ - private $userId; - - /** - * @param ConnectivityTester $connectivityTester - * @param ICrypto $crypto - * @param SmtpClientFactory $clientFactory - * @param LoggerInterface $logger - * @param string $UserId - */ - public function __construct(ConnectivityTester $connectivityTester, - ICrypto $crypto, - SmtpClientFactory $clientFactory, - LoggerInterface $logger, - $UserId) { - $this->connectivityTester = $connectivityTester; - $this->crypto = $crypto; - $this->clientFactory = $clientFactory; - $this->logger = $logger; - $this->userId = $UserId; - } - - /** - * @param MailAccount $account - * @param string $host - * @param string|array $users - * @param string $password - * @param bool $withHostPrefix - * @return bool - */ - public function test(MailAccount $account, - string $host, - $users, - string $password, - bool $withHostPrefix = false): bool { - if (!is_array($users)) { - $users = [$users]; - } - - // port 25 should be the last one to test - $ports = [587, 465, 25]; - $protocols = ['ssl', 'tls', 'none']; - $hostPrefixes = ['']; - if ($withHostPrefix) { - $hostPrefixes = ['', 'imap.']; - } - $encryptedPassword = $this->crypto->encrypt($password); - - foreach ($hostPrefixes as $hostPrefix) { - $url = $hostPrefix . $host; - if (gethostbyname($url) === $url) { - continue; - } - foreach ($ports as $port) { - if (!$this->connectivityTester->canConnect($url, $port)) { - continue; - } - foreach ($protocols as $protocol) { - foreach ($users as $user) { - try { - $account->setOutboundHost($url); - $account->setOutboundPort($port); - $account->setOutboundUser($user); - $account->setOutboundPassword($encryptedPassword); - $account->setOutboundSslMode($protocol); - - $this->testStmtpConnection($account); - - $this->logger->info("Test-Account-Successful: $this->userId, $url, $port, $user, $protocol"); - return true; - } catch (Exception $e) { - $error = $e->getMessage(); - $this->logger->info("Test-Account-Failed: $this->userId, $url, $port, $user, $protocol -> $error"); - } - } - } - } - } - return false; - } - - /** - * @param MailAccount $mailAccount - * - * @throws Exception - * - * @return void - */ - protected function testStmtpConnection(MailAccount $mailAccount): void { - $account = new Account($mailAccount); - $smtp = $this->clientFactory->create($account); - if ($smtp instanceof Horde_Mail_Transport_Smtphorde) { - $smtp->getSMTPObject(); - } - } -} diff --git a/lib/Service/AutoConfig/SmtpServerDetector.php b/lib/Service/AutoConfig/SmtpServerDetector.php deleted file mode 100644 index 7b5b2716f..000000000 --- a/lib/Service/AutoConfig/SmtpServerDetector.php +++ /dev/null @@ -1,103 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * @author Christoph Wurst <christoph@winzerhof-wurst.at> - * - * Mail - * - * This code is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License, version 3, - * along with this program. If not, see <http://www.gnu.org/licenses/> - * - */ - -namespace OCA\Mail\Service\AutoConfig; - -use OCA\Mail\Db\MailAccount; -use OCA\Mail\SystemConfig; - -class SmtpServerDetector { - - /** @var MxRecord */ - private $mxRecord; - - /** @var SmtpConnectivityTester */ - private $smtpConnectivityTester; - - /** @var SystemConfig */ - private $systemConfig; - - public function __construct(MxRecord $mxRecord, - SmtpConnectivityTester $smtpTester, - SystemConfig $systemConfig) { - $this->mxRecord = $mxRecord; - $this->smtpConnectivityTester = $smtpTester; - $this->systemConfig = $systemConfig; - } - - /** - * @param MailAccount $account - * @param string $email - * @param string $password - * @return bool - */ - public function detect(MailAccount $account, - string $email, - string $password): bool { - if (!$this->systemConfig->hasWorkingSmtp()) { - return true; - } - - // splitting the email address into user and host part - // TODO: use horde libs for email address parsing - [$user, $host] = explode("@", $email); - - /* - * Try to get the mx record for the email address - */ - $mxHosts = $this->mxRecord->query($host); - if ($mxHosts) { - // also test the parent domain - $toTest = $this->mxRecord->getSanitizedRecords($mxHosts); - foreach ($toTest as $mxHost) { - $result = $this->smtpConnectivityTester->test( - $account, - $mxHost, - [ - $user, - $email - ], - $password - ); - if ($result) { - return true; - } - } - } - - /* - * SMTP login with full email address as user - * works for a lot of providers (e.g. Google Mail) - */ - return $this->smtpConnectivityTester->test( - $account, - $host, - [ - $user, - $email - ], - $password, - true - ); - } -} diff --git a/lib/Service/SetupService.php b/lib/Service/SetupService.php index 9ab0b1374..4b9d951ea 100644 --- a/lib/Service/SetupService.php +++ b/lib/Service/SetupService.php @@ -35,16 +35,12 @@ use OCA\Mail\Db\TagMapper; use OCA\Mail\Exception\CouldNotConnectException; use OCA\Mail\Exception\ServiceException; use OCA\Mail\IMAP\IMAPClientFactory; -use OCA\Mail\Service\AutoConfig\AutoConfig; use OCA\Mail\SMTP\SmtpClientFactory; use OCP\Security\ICrypto; use Psr\Log\LoggerInterface; class SetupService { - /** @var AutoConfig */ - private $autoConfig; - /** @var AccountService */ private $accountService; @@ -63,14 +59,12 @@ class SetupService { /** @var TagMapper */ private $tagMapper; - public function __construct(AutoConfig $autoConfig, - AccountService $accountService, + public function __construct(AccountService $accountService, ICrypto $crypto, SmtpClientFactory $smtpClientFactory, IMAPClientFactory $imapClientFactory, LoggerInterface $logger, TagMapper $tagMapper) { - $this->autoConfig = $autoConfig; $this->accountService = $accountService; $this->crypto = $crypto; $this->smtpClientFactory = $smtpClientFactory; @@ -82,28 +76,6 @@ class SetupService { /** * @param string $accountName * @param string $emailAddress - * @param string $password - * @return Account|null - * - * @link https://github.com/nextcloud/mail/issues/25 - */ - public function createNewAutoConfiguredAccount($accountName, $emailAddress, $password) { - $this->logger->info('setting up auto detected account'); - $mailAccount = $this->autoConfig->createAutoDetected($emailAddress, $password, $accountName); - if (is_null($mailAccount)) { - return null; - } - - $this->accountService->save($mailAccount); - - $this->tagMapper->createDefaultTags($mailAccount); - - return new Account($mailAccount); - } - - /** - * @param string $accountName - * @param string $emailAddress * @param string $imapHost * @param int $imapPort * @param string $imapSslMode |