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:
authorChristoph Wurst <christoph@winzerhof-wurst.at>2020-10-15 12:24:38 +0300
committerChristoph Wurst <christoph@winzerhof-wurst.at>2020-10-30 19:16:24 +0300
commit15867528b25cad3e1262014d0fa4f967a73d64be (patch)
tree6dd7c46876325acf8aad147b9ef791a73376c102 /lib/Listener
parentfe074001833362fa1eb4d18576131b0678907fb5 (diff)
Store special mailboxes as preference of the account
… instead of using a fragile autodetection every time we need one of those. We will still try to auto-detect the mailboxes but the users will have to option to change the destinations. Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Diffstat (limited to 'lib/Listener')
-rw-r--r--lib/Listener/DeleteDraftListener.php51
-rw-r--r--lib/Listener/DraftMailboxCreatorListener.php99
-rw-r--r--lib/Listener/MailboxesSynchronizedSpecialMailboxesUpdater.php122
-rw-r--r--lib/Listener/SaveSentMessageListener.php56
-rw-r--r--lib/Listener/TrashMailboxCreatorListener.php102
5 files changed, 148 insertions, 282 deletions
diff --git a/lib/Listener/DeleteDraftListener.php b/lib/Listener/DeleteDraftListener.php
index 3f701aa8f..87f46b47a 100644
--- a/lib/Listener/DeleteDraftListener.php
+++ b/lib/Listener/DeleteDraftListener.php
@@ -34,7 +34,6 @@ use OCA\Mail\Db\Message;
use OCA\Mail\Events\DraftSavedEvent;
use OCA\Mail\Events\MessageSentEvent;
use OCA\Mail\IMAP\IMAPClientFactory;
-use OCA\Mail\IMAP\MailboxSync;
use OCA\Mail\IMAP\MessageMapper;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\EventDispatcher\Event;
@@ -52,21 +51,16 @@ class DeleteDraftListener implements IEventListener {
/** @var MessageMapper */
private $messageMapper;
- /** @var MailboxSync */
- private $mailboxSync;
-
/** @var LoggerInterface */
private $logger;
public function __construct(IMAPClientFactory $imapClientFactory,
MailboxMapper $mailboxMapper,
MessageMapper $messageMapper,
- MailboxSync $mailboxSync,
LoggerInterface $logger) {
$this->imapClientFactory = $imapClientFactory;
$this->mailboxMapper = $mailboxMapper;
$this->messageMapper = $messageMapper;
- $this->mailboxSync = $mailboxSync;
$this->logger = $logger;
}
@@ -84,7 +78,12 @@ class DeleteDraftListener implements IEventListener {
*/
private function deleteDraft(Account $account, Message $draft): void {
$client = $this->imapClientFactory->getClient($account);
- $draftsMailbox = $this->getDraftsMailbox($account);
+ try {
+ $draftsMailbox = $this->getDraftsMailbox($account);
+ } catch (DoesNotExistException $e) {
+ $this->logger->warning("Account has no draft mailbox set, can't delete the draft");
+ return;
+ }
try {
$this->messageMapper->addFlag(
@@ -108,38 +107,14 @@ class DeleteDraftListener implements IEventListener {
}
}
+ /**
+ * @throws DoesNotExistException
+ */
private function getDraftsMailbox(Account $account): Mailbox {
- try {
- return $this->mailboxMapper->findSpecial($account, 'drafts');
- } catch (DoesNotExistException $e) {
- $this->logger->debug('Creating drafts mailbox');
- $this->createDraftsMailbox($account);
- $this->logger->debug('Drafts mailbox created');
- }
-
- return $this->mailboxMapper->findSpecial($account, 'drafts');
- }
-
- private function createDraftsMailbox(Account $account): void {
- $client = $this->imapClientFactory->getClient($account);
-
- try {
- // TODO: localize mailbox name
- $client->createMailbox(
- 'Drafts',
- [
- 'special_use' => [
- \Horde_Imap_Client::SPECIALUSE_DRAFTS,
- ],
- ]
- );
- } catch (Horde_Imap_Client_Exception $e) {
- $this->logger->error('Could not create drafts mailbox', [
- 'exception' => $e,
- ]);
+ $draftsMailboxId = $account->getMailAccount()->getDraftsMailboxId();
+ if ($draftsMailboxId === null) {
+ throw new DoesNotExistException("No drafts mailbox ID set");
}
-
- // TODO: find a more elegant solution for updating the mailbox cache
- $this->mailboxSync->sync($account, $this->logger,true);
+ return $this->mailboxMapper->findById($draftsMailboxId);
}
}
diff --git a/lib/Listener/DraftMailboxCreatorListener.php b/lib/Listener/DraftMailboxCreatorListener.php
deleted file mode 100644
index f4d915e81..000000000
--- a/lib/Listener/DraftMailboxCreatorListener.php
+++ /dev/null
@@ -1,99 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author 2019 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\Listener;
-
-use Horde_Imap_Client_Exception;
-use OCA\Mail\Account;
-use OCA\Mail\Db\MailboxMapper;
-use OCA\Mail\Events\SaveDraftEvent;
-use OCA\Mail\IMAP\IMAPClientFactory;
-use OCA\Mail\IMAP\MailboxSync;
-use OCP\AppFramework\Db\DoesNotExistException;
-use OCP\EventDispatcher\Event;
-use OCP\EventDispatcher\IEventListener;
-use Psr\Log\LoggerInterface;
-
-class DraftMailboxCreatorListener implements IEventListener {
-
- /** @var MailboxMapper */
- private $mailboxMapper;
-
- /** @var IMAPClientFactory */
- private $imapClientFactory;
-
- /** @var MailboxSync */
- private $mailboxSync;
-
- /** @var LoggerInterface */
- private $logger;
-
- public function __construct(MailboxMapper $mailboxMapper,
- IMAPClientFactory $imapClientFactory,
- MailboxSync $mailboxSync,
- LoggerInterface $logger) {
- $this->mailboxMapper = $mailboxMapper;
- $this->imapClientFactory = $imapClientFactory;
- $this->mailboxSync = $mailboxSync;
- $this->logger = $logger;
- }
-
- public function handle(Event $event): void {
- if (!($event instanceof SaveDraftEvent)) {
- return;
- }
-
- try {
- $this->mailboxMapper->findSpecial($event->getAccount(), 'drafts');
- } catch (DoesNotExistException $e) {
- $this->logger->debug('Creating drafts mailbox');
- $this->createDraftsMailbox($event->getAccount());
- $this->logger->debug('Drafts mailbox created');
- }
- }
-
- private function createDraftsMailbox(Account $account): void {
- $client = $this->imapClientFactory->getClient($account);
-
- try {
- // TODO: localize mailbox name
- $client->createMailbox(
- 'Drafts',
- [
- 'special_use' => [
- \Horde_Imap_Client::SPECIALUSE_DRAFTS,
- ],
- ]
- );
- } catch (Horde_Imap_Client_Exception $e) {
- $this->logger->error('Could not create drafts mailbox', [
- 'exception' => $e,
- ]);
- }
-
- // TODO: find a more elegant solution for updating the mailbox cache
- $this->mailboxSync->sync($account, $this->logger,true);
- }
-}
diff --git a/lib/Listener/MailboxesSynchronizedSpecialMailboxesUpdater.php b/lib/Listener/MailboxesSynchronizedSpecialMailboxesUpdater.php
new file mode 100644
index 000000000..32c009061
--- /dev/null
+++ b/lib/Listener/MailboxesSynchronizedSpecialMailboxesUpdater.php
@@ -0,0 +1,122 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ *
+ * @author 2020 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\Listener;
+
+use OCA\Mail\Db\MailAccountMapper;
+use OCA\Mail\Db\Mailbox;
+use OCA\Mail\Db\MailboxMapper;
+use OCA\Mail\Events\MailboxesSynchronizedEvent;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\EventDispatcher\Event;
+use OCP\EventDispatcher\IEventListener;
+use Psr\Log\LoggerInterface;
+use function array_combine;
+use function array_key_exists;
+use function array_map;
+use function in_array;
+use function json_decode;
+use function strtolower;
+
+class MailboxesSynchronizedSpecialMailboxesUpdater implements IEventListener {
+
+ /** @var MailAccountMapper */
+ private $mailAccountMapper;
+
+ /** @var MailboxMapper */
+ private $mailboxMapper;
+
+ /** @var LoggerInterface */
+ private $logger;
+
+ public function __construct(MailAccountMapper $mailAccountMapper,
+ MailboxMapper $mailboxMapper,
+ LoggerInterface $logger) {
+ $this->mailAccountMapper = $mailAccountMapper;
+ $this->mailboxMapper = $mailboxMapper;
+ $this->logger = $logger;
+ }
+
+ /**
+ * @param Event $event
+ */
+ public function handle(Event $event): void {
+ /** @var MailboxesSynchronizedEvent $event */
+ $account = $event->getAccount();
+ $mailAccount = $account->getMailAccount();
+ $mailboxes = $this->indexMailboxes(
+ $this->mailboxMapper->findAll($account)
+ );
+
+ if ($mailAccount->getDraftsMailboxId() === null || !array_key_exists($mailAccount->getDraftsMailboxId(), $mailboxes)) {
+ $draftsMailbox = $this->findSpecial($mailboxes, 'drafts');
+ $mailAccount->setDraftsMailboxId($draftsMailbox->getId());
+ }
+ if ($mailAccount->getSentMailboxId() === null || !array_key_exists($mailAccount->getSentMailboxId(), $mailboxes)) {
+ $sentMailbox = $this->findSpecial($mailboxes, 'sent');
+ $mailAccount->setSentMailboxId($sentMailbox->getId());
+ }
+ if ($mailAccount->getTrashMailboxId() === null || !array_key_exists($mailAccount->getTrashMailboxId(), $mailboxes)) {
+ $trashMailbox = $this->findSpecial($mailboxes, 'trash');
+ $mailAccount->setTrashMailboxId($trashMailbox->getId());
+ }
+
+ $this->mailAccountMapper->update($mailAccount);
+ }
+
+ private function indexMailboxes(array $mailboxes): array {
+ return array_combine(
+ array_map(function (Mailbox $mb): int {
+ return $mb->getId();
+ }, $mailboxes),
+ $mailboxes
+ );
+ }
+
+ /**
+ * @param Mailbox[] $mailboxes
+ * @throws DoesNotExistException
+ */
+ private function findSpecial(array $mailboxes, string $specialUse): Mailbox {
+ // First, let's try to detect by special use attribute
+ foreach ($mailboxes as $mailbox) {
+ $specialUses = json_decode($mailbox->getSpecialUse(), true) ?? [];
+ if (in_array($specialUse, $specialUses, true)) {
+ return $mailbox;
+ }
+ }
+
+ // No luck so far, let's do another round and just guess
+ foreach ($mailboxes as $mailbox) {
+ // TODO: also check localized name
+ if (strtolower($mailbox->getName()) === strtolower($specialUse)) {
+ return $mailbox;
+ }
+ }
+
+ // Give up
+ throw new DoesNotExistException("Special mailbox $specialUse does not exist");
+ }
+}
diff --git a/lib/Listener/SaveSentMessageListener.php b/lib/Listener/SaveSentMessageListener.php
index aa43eb6fc..37eedd93c 100644
--- a/lib/Listener/SaveSentMessageListener.php
+++ b/lib/Listener/SaveSentMessageListener.php
@@ -26,13 +26,10 @@ declare(strict_types=1);
namespace OCA\Mail\Listener;
use Horde_Imap_Client_Exception;
-use OCA\Mail\Account;
-use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\MailboxMapper;
use OCA\Mail\Events\MessageSentEvent;
use OCA\Mail\Exception\ServiceException;
use OCA\Mail\IMAP\IMAPClientFactory;
-use OCA\Mail\IMAP\MailboxSync;
use OCA\Mail\IMAP\MessageMapper;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\EventDispatcher\Event;
@@ -50,21 +47,16 @@ class SaveSentMessageListener implements IEventListener {
/** @var MessageMapper */
private $messageMapper;
- /** @var MailboxSync */
- private $mailboxSync;
-
/** @var LoggerInterface */
private $logger;
public function __construct(MailboxMapper $mailboxMapper,
IMAPClientFactory $imapClientFactory,
MessageMapper $messageMapper,
- MailboxSync $mailboxSync,
LoggerInterface $logger) {
$this->mailboxMapper = $mailboxMapper;
$this->imapClientFactory = $imapClientFactory;
$this->messageMapper = $messageMapper;
- $this->mailboxSync = $mailboxSync;
$this->logger = $logger;
}
@@ -73,13 +65,22 @@ class SaveSentMessageListener implements IEventListener {
return;
}
+ $sentMailboxId = $event->getAccount()->getMailAccount()->getSentMailboxId();
+ if ($sentMailboxId === null) {
+ $this->logger->warning("No sent mailbox exists, can't save sent message");
+ return;
+ }
+
// Save the message in the sent mailbox
try {
- $sentMailbox = $this->mailboxMapper->findSpecial($event->getAccount(), 'sent');
+ $sentMailbox = $this->mailboxMapper->findById(
+ $sentMailboxId
+ );
} catch (DoesNotExistException $e) {
- $this->logger->debug('creating sent mailbox');
- $sentMailbox = $this->createSentMailbox($event->getAccount());
- $this->logger->debug('sent mailbox created');
+ $this->logger->error("Sent mailbox could not be found", [
+ 'exception' => $e,
+ ]);
+ return;
}
try {
@@ -92,35 +93,4 @@ class SaveSentMessageListener implements IEventListener {
throw new ServiceException('Could not save sent message on IMAP', 0, $e);
}
}
-
- /**
- * @throws DoesNotExistException
- * @throws ServiceException
- */
- private function createSentMailbox(Account $account): Mailbox {
- $client = $this->imapClientFactory->getClient($account);
-
- try {
- // TODO: localize mailbox name
- $client->createMailbox(
- 'Sent',
- [
- 'special_use' => [
- \Horde_Imap_Client::SPECIALUSE_SENT,
- ],
- ]
- );
- } catch (Horde_Imap_Client_Exception $e) {
- // Let's assume this error is caused because the mailbox already exists,
- // caused by concurrent requests or out-of-sync mailbox cache
- $this->logger->warning('Could not create sent mailbox: ' . $e->getMessage(), [
- 'exception' => $e,
- ]);
- }
-
- // TODO: find a more elegant solution for updating the mailbox cache
- $this->mailboxSync->sync($account, $this->logger,true);
-
- return $this->mailboxMapper->findSpecial($account, 'sent');
- }
}
diff --git a/lib/Listener/TrashMailboxCreatorListener.php b/lib/Listener/TrashMailboxCreatorListener.php
deleted file mode 100644
index 3a57e2b4d..000000000
--- a/lib/Listener/TrashMailboxCreatorListener.php
+++ /dev/null
@@ -1,102 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author 2019 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\Listener;
-
-use Horde_Imap_Client_Exception;
-use OCA\Mail\Account;
-use OCA\Mail\Db\MailboxMapper;
-use OCA\Mail\Events\BeforeMessageDeletedEvent;
-use OCA\Mail\IMAP\IMAPClientFactory;
-use OCA\Mail\IMAP\MailboxSync;
-use OCP\AppFramework\Db\DoesNotExistException;
-use OCP\EventDispatcher\Event;
-use OCP\EventDispatcher\IEventListener;
-use Psr\Log\LoggerInterface;
-
-class TrashMailboxCreatorListener implements IEventListener {
-
- /** @var MailboxMapper */
- private $mailboxMapper;
-
- /** @var IMAPClientFactory */
- private $imapClientFactory;
-
- /** @var MailboxSync */
- private $mailboxSync;
-
- /** @var LoggerInterface */
- private $logger;
-
- public function __construct(MailboxMapper $mailboxMapper,
- IMAPClientFactory $imapClientFactory,
- MailboxSync $mailboxSync,
- LoggerInterface $logger) {
- $this->mailboxMapper = $mailboxMapper;
- $this->imapClientFactory = $imapClientFactory;
- $this->mailboxSync = $mailboxSync;
- $this->logger = $logger;
- }
-
- public function handle(Event $event): void {
- if (!($event instanceof BeforeMessageDeletedEvent)) {
- return;
- }
-
- try {
- $this->mailboxMapper->findSpecial(
- $event->getAccount(),
- 'trash'
- );
- } catch (DoesNotExistException $e) {
- $this->logger->debug("Creating trash mailbox");
- $this->createTrash($event->getAccount());
- $this->logger->debug("Trash mailbox created");
- }
- }
-
- private function createTrash(Account $account): void {
- $client = $this->imapClientFactory->getClient($account);
-
- try {
- // TODO: localize mailbox name
- $client->createMailbox(
- 'Trash',
- [
- 'special_use' => [
- \Horde_Imap_Client::SPECIALUSE_TRASH,
- ],
- ]
- );
-
- // TODO: find a more elegant solution for updating the mailbox cache
- $this->mailboxSync->sync($account, $this->logger,true);
- } catch (Horde_Imap_Client_Exception $e) {
- $this->logger->error('Could not creat trash mailbox', [
- 'exception' => $e,
- ]);
- }
- }
-}