diff options
author | Cyrille Bollu <StCyr@users.noreply.github.com> | 2021-03-01 15:52:09 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-01 15:52:09 +0300 |
commit | 7019e65f8dad3d9302d281946fc7feb14cbe288c (patch) | |
tree | 6477da8e3d4fe05559e8f309e87ba29050732823 /lib/Service | |
parent | 065c121c5696b3a9aad1741d29e1e47c38440fbc (diff) | |
parent | 42d9bfb0e583a49764524b55f09042290580811e (diff) |
Merge branch 'master' into dependabot/composer/vimeo/psalm-4.6.1
Diffstat (limited to 'lib/Service')
-rw-r--r-- | lib/Service/AccountService.php | 15 | ||||
-rw-r--r-- | lib/Service/MailManager.php | 61 | ||||
-rw-r--r-- | lib/Service/MailTransmission.php | 20 | ||||
-rw-r--r-- | lib/Service/Provisioning/Config.php | 39 | ||||
-rw-r--r-- | lib/Service/Provisioning/Manager.php | 30 | ||||
-rw-r--r-- | lib/Service/SetupService.php | 37 | ||||
-rw-r--r-- | lib/Service/TrustedSenderService.php | 8 |
7 files changed, 190 insertions, 20 deletions
diff --git a/lib/Service/AccountService.php b/lib/Service/AccountService.php index 90766e98c..13462ff2d 100644 --- a/lib/Service/AccountService.php +++ b/lib/Service/AccountService.php @@ -126,6 +126,21 @@ class AccountService { } /** + * @param int $accountId + * + * @throws ClientException + */ + public function deleteByAccountId(int $accountId): void { + try { + $mailAccount = $this->mapper->findById($accountId); + } catch (DoesNotExistException $e) { + throw new ClientException("Account $accountId does not exist", 0, $e); + } + $this->aliasesService->deleteAll($accountId); + $this->mapper->delete($mailAccount); + } + + /** * @param MailAccount $newAccount * @return MailAccount */ diff --git a/lib/Service/MailManager.php b/lib/Service/MailManager.php index 444a1aac5..d37278477 100644 --- a/lib/Service/MailManager.php +++ b/lib/Service/MailManager.php @@ -26,6 +26,7 @@ namespace OCA\Mail\Service; use Horde_Imap_Client; use Horde_Imap_Client_Exception; use Horde_Imap_Client_Exception_NoSupportExtension; +use Horde_Imap_Client_Socket; use OCA\Mail\Account; use OCA\Mail\Contracts\IMailManager; use OCA\Mail\Db\Mailbox; @@ -386,10 +387,13 @@ class MailManager implements IMailManager { } // Only send system flags to the IMAP server as other flags might not be supported - $imapFlags = self::ALLOWED_FLAGS[$flag] ?? []; + $imapFlags = $this->filterFlags($account, $flag, $mailbox); try { foreach ($imapFlags as $imapFlag) { - if ($value) { + if (empty($imapFlag) === true) { + continue; + } + if ($value === true) { $this->imapMessageMapper->addFlag($client, $mb, $uid, $imapFlag); } else { $this->imapMessageMapper->removeFlag($client, $mb, $uid, $imapFlag); @@ -502,4 +506,57 @@ class MailManager implements IMailManager { $this->folderMapper->delete($client, $mailbox->getName()); $this->mailboxMapper->delete($mailbox); } + + /** + * @param Account $account + * @param Mailbox $mailbox + * @param Message $message + * @return array[] + */ + public function getMailAttachments(Account $account, Mailbox $mailbox, Message $message): array { + return $this->imapMessageMapper->getAttachments($this->imapClientFactory->getClient($account), $mailbox->getName(), $message->getUid()); + } + + /** + * Filter out IMAP flags that aren't supported by the client server + * + * @param Horde_Imap_Client_Socket $client + * @param string $flag + * @param string $mailbox + * @return array + */ + public function filterFlags(Account $account, string $flag, string $mailbox): array { + // check for RFC server flags + if (array_key_exists($flag, self::ALLOWED_FLAGS) === true) { + return self::ALLOWED_FLAGS[$flag]; + } + + // Only allow flag setting if IMAP supports Permaflags + // @TODO check if there are length & char limits on permflags + if ($this->isPermflagsEnabled($account, $mailbox) === true) { + return ["$" . $flag]; + } + return []; + } + + /** + * Check IMAP server for support for PERMANENTFLAGS + * + * @param Account $account + * @param string $mailbox + * @return boolean + */ + public function isPermflagsEnabled(Account $account, string $mailbox): bool { + $client = $this->imapClientFactory->getClient($account); + try { + $capabilities = $client->status($mailbox, Horde_Imap_Client::STATUS_PERMFLAGS); + } catch (Horde_Imap_Client_Exception $e) { + throw new ServiceException( + "Could not get message flag options from IMAP: " . $e->getMessage(), + (int) $e->getCode(), + $e + ); + } + return (is_array($capabilities) === true && array_key_exists('permflags', $capabilities) === true && in_array("\*", $capabilities['permflags'], true) === true); + } } diff --git a/lib/Service/MailTransmission.php b/lib/Service/MailTransmission.php index 4630efff6..729da0374 100644 --- a/lib/Service/MailTransmission.php +++ b/lib/Service/MailTransmission.php @@ -26,6 +26,7 @@ namespace OCA\Mail\Service; use Horde_Exception; use Horde_Imap_Client; use Horde_Imap_Client_Data_Fetch; +use Horde_Imap_Client_DateTime; use Horde_Imap_Client_Fetch_Query; use Horde_Imap_Client_Ids; use Horde_Mail_Transport_Null; @@ -432,12 +433,12 @@ class MailTransmission implements IMailTransmission { $query->flags(); $query->uid(); $query->imapDate(); - $query->headers( - 'mdn', - ['disposition-notification-to', 'original-recipient'], - ['cache' => true, 'peek' => true] - ); + $query->headerText([ + 'cache' => true, + 'peek' => true, + ]); + /** @var Horde_Imap_Client_Data_Fetch[] $fetchResults */ $fetchResults = iterator_to_array($imapClient->fetch($mailbox->getName(), $query, [ 'ids' => new Horde_Imap_Client_Ids([$message->getUid()]), ]), false); @@ -446,10 +447,10 @@ class MailTransmission implements IMailTransmission { throw new ServiceException('Message "' .$message->getId() . '" not found.'); } - /** @var \Horde_Imap_Client_DateTime $imapDate */ + /** @var Horde_Imap_Client_DateTime $imapDate */ $imapDate = $fetchResults[0]->getImapDate(); /** @var Horde_Mime_Headers $headers */ - $mdnHeaders = $fetchResults[0]->getHeaders('mdn', Horde_Imap_Client_Data_Fetch::HEADER_PARSE); + $mdnHeaders = $fetchResults[0]->getHeaderText('0', Horde_Imap_Client_Data_Fetch::HEADER_PARSE); /** @var Horde_Mime_Headers_Addresses|null $dispositionNotificationTo */ $dispositionNotificationTo = $mdnHeaders->getHeader('disposition-notification-to'); /** @var Horde_Mime_Headers_Addresses|null $originalRecipient */ @@ -482,7 +483,10 @@ class MailTransmission implements IMailTransmission { 'displayed', $account->getMailAccount()->getOutboundHost(), $smtpClient, - ['from_addr' => $account->getEMailAddress()] + [ + 'from_addr' => $account->getEMailAddress(), + 'charset' => 'UTF-8', + ] ); } catch (Horde_Mime_Exception $e) { throw new ServiceException('Unable to send mdn for message "' . $message->getId() . '" caused by: ' . $e->getMessage(), 0, $e); diff --git a/lib/Service/Provisioning/Config.php b/lib/Service/Provisioning/Config.php index 2af2f1827..74b8cda8d 100644 --- a/lib/Service/Provisioning/Config.php +++ b/lib/Service/Provisioning/Config.php @@ -111,6 +111,45 @@ class Config implements JsonSerializable { } /** + * @return boolean + */ + public function getSieveEnabled(): bool { + return (bool)$this->data['sieveEnabled']; + } + + /** + * @return string + */ + public function getSieveHost() { + return $this->data['sieveHost']; + } + + /** + * @return int + */ + public function getSievePort(): int { + return (int)$this->data['sievePort']; + } + + /** + * @param IUser $user + * @return string + */ + public function buildSieveUser(IUser $user) { + if (isset($this->data['sieveUser'])) { + return $this->buildUserEmail($this->data['sieveUser'], $user); + } + return $this->buildEmail($user); + } + + /** + * @return string + */ + public function getSieveSslMode() { + return $this->data['sieveSslMode']; + } + + /** * Replace %USERID% and %EMAIL% to allow special configurations * * @param string $original diff --git a/lib/Service/Provisioning/Manager.php b/lib/Service/Provisioning/Manager.php index 906de385f..742c87f13 100644 --- a/lib/Service/Provisioning/Manager.php +++ b/lib/Service/Provisioning/Manager.php @@ -100,7 +100,12 @@ class Manager { string $smtpUser, string $smtpHost, int $smtpPort, - string $smtpSslMode): void { + string $smtpSslMode, + bool $sieveEnabled, + string $sieveUser, + string $sieveHost, + int $sievePort, + string $sieveSslMode): void { $config = $this->configMapper->save(new Config([ 'active' => true, 'email' => $email, @@ -112,6 +117,11 @@ class Manager { 'smtpHost' => $smtpHost, 'smtpPort' => $smtpPort, 'smtpSslMode' => $smtpSslMode, + 'sieveEnabled' => $sieveEnabled, + 'sieveUser' => $sieveUser, + 'sieveHost' => $sieveHost, + 'sievePort' => $sievePort, + 'sieveSslMode' => $sieveSslMode, ])); $this->provision($config); @@ -119,10 +129,7 @@ class Manager { private function updateAccount(IUser $user, MailAccount $account, Config $config): MailAccount { $account->setEmail($config->buildEmail($user)); - if ($user->getDisplayName() !== $user->getUID()) { - // Only set if it's something meaningful - $account->setName($user->getDisplayName()); - } + $account->setName($user->getDisplayName()); $account->setInboundUser($config->buildImapUser($user)); $account->setInboundHost($config->getImapHost()); $account->setInboundPort($config->getImapPort()); @@ -131,6 +138,19 @@ class Manager { $account->setOutboundHost($config->getSmtpHost()); $account->setOutboundPort($config->getSmtpPort()); $account->setOutboundSslMode($config->getSmtpSslMode()); + $account->setSieveEnabled($config->getSieveEnabled()); + + if ($config->getSieveEnabled()) { + $account->setSieveUser($config->buildSieveUser($user)); + $account->setSieveHost($config->getSieveHost()); + $account->setSievePort($config->getSievePort()); + $account->setSieveSslMode($config->getSieveSslMode()); + } else { + $account->setSieveUser(null); + $account->setSieveHost(null); + $account->setSievePort(null); + $account->setSieveSslMode(null); + } return $account; } diff --git a/lib/Service/SetupService.php b/lib/Service/SetupService.php index 0be5984bf..ffd6146ac 100644 --- a/lib/Service/SetupService.php +++ b/lib/Service/SetupService.php @@ -26,9 +26,14 @@ declare(strict_types=1); namespace OCA\Mail\Service; +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\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; @@ -48,6 +53,9 @@ class SetupService { /** @var SmtpClientFactory */ private $smtpClientFactory; + /** @var IMAPClientFactory */ + private $imapClientFactory; + /** var LoggerInterface */ private $logger; @@ -55,11 +63,13 @@ class SetupService { AccountService $accountService, ICrypto $crypto, SmtpClientFactory $smtpClientFactory, + IMAPClientFactory $imapClientFactory, LoggerInterface $logger) { $this->autoConfig = $autoConfig; $this->accountService = $accountService; $this->crypto = $crypto; $this->smtpClientFactory = $smtpClientFactory; + $this->imapClientFactory = $imapClientFactory; $this->logger = $logger; } @@ -124,12 +134,35 @@ class SetupService { $account = new Account($newAccount); $this->logger->debug('Connecting to account {account}', ['account' => $newAccount->getEmail()]); - $transport = $this->smtpClientFactory->create($account); - $account->testConnectivity($transport); + $this->testConnectivity($account); $this->accountService->save($newAccount); $this->logger->debug("account created " . $newAccount->getId()); return $account; } + + /** + * @param Account $account + * @throws CouldNotConnectException + */ + protected function testConnectivity(Account $account): void { + $mailAccount = $account->getMailAccount(); + + $imapClient = $this->imapClientFactory->getClient($account); + try { + $imapClient->login(); + } catch (Horde_Imap_Client_Exception $e) { + throw CouldNotConnectException::create($e, 'IMAP', $mailAccount->getInboundHost(), $mailAccount->getInboundPort()); + } + + $transport = $this->smtpClientFactory->create($account); + if ($transport instanceof Horde_Mail_Transport_Smtphorde) { + try { + $transport->getSMTPObject(); + } catch (Horde_Mail_Exception $e) { + throw CouldNotConnectException::create($e, 'SMTP', $mailAccount->getOutboundHost(), $mailAccount->getOutboundPort()); + } + } + } } diff --git a/lib/Service/TrustedSenderService.php b/lib/Service/TrustedSenderService.php index 8210be686..57cebbfa6 100644 --- a/lib/Service/TrustedSenderService.php +++ b/lib/Service/TrustedSenderService.php @@ -44,7 +44,7 @@ class TrustedSenderService implements ITrustedSenderService { ); } - public function trust(string $uid, string $email, ?bool $trust = true): void { + public function trust(string $uid, string $email, string $type, ?bool $trust = true): void { if ($trust && $this->isTrusted($uid, $email)) { // Nothing to do return; @@ -53,12 +53,14 @@ class TrustedSenderService implements ITrustedSenderService { if ($trust) { $this->mapper->create( $uid, - $email + $email, + $type ); } else { $this->mapper->remove( $uid, - $email + $email, + $type ); } } |