Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/mail.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bollu <StCyr@users.noreply.github.com>2021-03-01 15:52:09 +0300
committerGitHub <noreply@github.com>2021-03-01 15:52:09 +0300
commit7019e65f8dad3d9302d281946fc7feb14cbe288c (patch)
tree6477da8e3d4fe05559e8f309e87ba29050732823 /lib/Service
parent065c121c5696b3a9aad1741d29e1e47c38440fbc (diff)
parent42d9bfb0e583a49764524b55f09042290580811e (diff)
Merge branch 'master' into dependabot/composer/vimeo/psalm-4.6.1
Diffstat (limited to 'lib/Service')
-rw-r--r--lib/Service/AccountService.php15
-rw-r--r--lib/Service/MailManager.php61
-rw-r--r--lib/Service/MailTransmission.php20
-rw-r--r--lib/Service/Provisioning/Config.php39
-rw-r--r--lib/Service/Provisioning/Manager.php30
-rw-r--r--lib/Service/SetupService.php37
-rw-r--r--lib/Service/TrustedSenderService.php8
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
);
}
}