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:
-rw-r--r--appinfo/routes.php81
-rw-r--r--lib/Attachment.php14
-rw-r--r--lib/Contracts/IMailManager.php70
-rw-r--r--lib/Contracts/IMailSearch.php14
-rw-r--r--lib/Contracts/IMailTransmission.php13
-rw-r--r--lib/Controller/AccountsController.php126
-rw-r--r--lib/Controller/AliasesController.php8
-rw-r--r--lib/Controller/MailboxesController.php (renamed from lib/Controller/FoldersController.php)97
-rwxr-xr-xlib/Controller/MessagesController.php243
-rw-r--r--lib/Controller/PageController.php56
-rw-r--r--lib/Db/MailAccount.php1
-rw-r--r--lib/Db/Mailbox.php2
-rw-r--r--lib/Db/MailboxMapper.php28
-rw-r--r--lib/Db/Message.php2
-rw-r--r--lib/Db/MessageMapper.php137
-rw-r--r--lib/Events/DraftSavedEvent.php13
-rw-r--r--lib/Events/MessageSentEvent.php13
-rw-r--r--lib/Events/SaveDraftEvent.php13
-rw-r--r--lib/IMAP/MessageMapper.php18
-rw-r--r--lib/IMAP/Sync/Response.php13
-rw-r--r--lib/IMAP/Threading/ThreadBuilder.php3
-rw-r--r--lib/Listener/DeleteDraftListener.php16
-rw-r--r--lib/Mailbox.php7
-rw-r--r--lib/Model/IMAPMessage.php17
-rw-r--r--lib/Service/AccountService.php12
-rw-r--r--lib/Service/IMailBox.php5
-rw-r--r--lib/Service/MailManager.php66
-rw-r--r--lib/Service/MailTransmission.php30
-rw-r--r--lib/Service/Search/MailSearch.php43
-rw-r--r--lib/Service/Sync/SyncService.php69
-rw-r--r--package-lock.json2
-rw-r--r--src/components/Address.vue5
-rw-r--r--src/components/Composer.vue17
-rw-r--r--src/components/Envelope.vue36
-rw-r--r--src/components/EnvelopeList.vue21
-rw-r--r--src/components/Mailbox.vue87
-rw-r--r--src/components/MailboxMessage.vue43
-rw-r--r--src/components/Message.vue72
-rw-r--r--src/components/MessageAttachment.vue9
-rw-r--r--src/components/MessageAttachments.vue9
-rw-r--r--src/components/Navigation.vue40
-rw-r--r--src/components/NavigationAccount.vue29
-rw-r--r--src/components/NavigationMailbox.vue (renamed from src/components/NavigationFolder.vue)158
-rw-r--r--src/components/NewMessageDetail.vue101
-rw-r--r--src/i18n/MailboxTranslator.js34
-rw-r--r--src/imap/MailboxHierarchy.js10
-rw-r--r--src/imap/MailboxPrefix.js2
-rw-r--r--src/router.js7
-rw-r--r--src/service/AliasService.js9
-rw-r--r--src/service/AttachmentService.js12
-rw-r--r--src/service/FolderService.js50
-rw-r--r--src/service/MailboxService.js48
-rw-r--r--src/service/MessageService.js92
-rw-r--r--src/store/actions.js306
-rw-r--r--src/store/constants.js7
-rw-r--r--src/store/getters.js37
-rw-r--r--src/store/index.js16
-rw-r--r--src/store/mutations.js200
-rw-r--r--src/store/normalization.js10
-rw-r--r--src/tests/setup.js1
-rw-r--r--src/tests/unit/components/Address.spec.js6
-rw-r--r--src/tests/unit/i18n/MailboxTranslator.spec.js8
-rw-r--r--src/tests/unit/imap/MailboxHierarchy.spec.js26
-rw-r--r--src/tests/unit/store/actions.spec.js217
-rw-r--r--src/tests/unit/store/getters.spec.js3
-rw-r--r--src/tests/unit/store/mutations.spec.js176
-rw-r--r--src/tests/unit/store/normalization.spec.js43
-rw-r--r--src/tests/unit/util/EnvelopeUidParser.spec.js44
-rw-r--r--src/util/EnvelopeUidParser.js37
-rw-r--r--src/views/Dashboard.vue46
-rw-r--r--src/views/Home.vue42
-rw-r--r--tests/Integration/Db/MailAccountTest.php2
-rw-r--r--tests/Integration/Framework/ImapTest.php4
-rw-r--r--tests/Integration/MailboxSynchronizationTest.php76
-rw-r--r--tests/Integration/Service/MailTransmissionIntegrationTest.php13
-rw-r--r--tests/Unit/Controller/AccountsControllerTest.php32
-rw-r--r--tests/Unit/Controller/MailboxesControllerTest.php (renamed from tests/Unit/Controller/FoldersControllerTest.php)32
-rw-r--r--tests/Unit/Controller/MessagesControllerTest.php237
-rw-r--r--tests/Unit/Controller/PageControllerTest.php4
-rw-r--r--tests/Unit/Listener/DeleteDraftListenerTest.php15
-rw-r--r--tests/Unit/Listener/DraftMailboxCreatorListenerTest.php9
-rw-r--r--tests/Unit/Listener/FlagRepliedMessageListenerTest.php13
-rw-r--r--tests/Unit/Listener/SaveSentMessageListenerTest.php17
-rw-r--r--tests/Unit/Model/IMAPMessageTest.php2
-rw-r--r--tests/Unit/Service/MailManagerTest.php16
-rw-r--r--tests/Unit/Service/MailTransmissionTest.php2
-rw-r--r--tests/Unit/Service/Search/MailSearchTest.php37
87 files changed, 2062 insertions, 1797 deletions
diff --git a/appinfo/routes.php b/appinfo/routes.php
index 5529db11f..ea6758ce2 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -30,98 +30,123 @@ return [
'verb' => 'GET'
],
[
+ 'name' => 'page#setup',
+ 'url' => '/setup',
+ 'verb' => 'GET'
+ ],
+ [
+ 'name' => 'page#keyboardShortcuts',
+ 'url' => '/keyboard-shortcuts',
+ 'verb' => 'GET'
+ ],
+ [
+ 'name' => 'page#accountSettings',
+ 'url' => '/accounts/{id}/settings',
+ 'verb' => 'GET'
+ ],
+ [
+ 'name' => 'page#mailbox',
+ 'url' => '/box/{id}',
+ 'verb' => 'GET'
+ ],
+ [
+ 'name' => 'page#thread',
+ 'url' => '/box/{mailboxId}/thread/{id}',
+ 'verb' => 'GET'
+ ],
+ [
+ 'name' => 'page#index',
+ 'url' => '/',
+ 'verb' => 'GET'
+ ],
+ [
'name' => 'page#compose',
'url' => '/compose',
'verb' => 'GET'
],
[
'name' => 'accounts#send',
- 'url' => '/api/accounts/{accountId}/send',
+ 'url' => '/api/accounts/{id}/send',
'verb' => 'POST'
],
[
'name' => 'accounts#draft',
- 'url' => '/api/accounts/{accountId}/draft',
+ 'url' => '/api/accounts/{id}/draft',
'verb' => 'POST'
],
[
'name' => 'accounts#patchAccount',
- 'url' => '/api/accounts/{accountId}',
+ 'url' => '/api/accounts/{id}',
'verb' => 'PATCH'
],
[
'name' => 'accounts#updateSignature',
- 'url' => '/api/accounts/{accountId}/signature',
+ 'url' => '/api/accounts/{id}/signature',
'verb' => 'PUT'
],
[
'name' => 'accounts#getQuota',
- 'url' => '/api/accounts/{accountId}/quota',
+ 'url' => '/api/accounts/{id}/quota',
'verb' => 'GET'
],
[
- 'name' => 'folders#sync',
- 'url' => '/api/accounts/{accountId}/folders/{folderId}/sync',
+ 'name' => 'mailboxes#sync',
+ 'url' => '/api/mailboxes/{id}/sync',
'verb' => 'POST'
],
[
- 'name' => 'folders#clearCache',
- 'url' => '/api/accounts/{accountId}/folders/{folderId}/sync',
+ 'name' => 'mailboxes#clearCache',
+ 'url' => '/api/mailboxes/{id}/sync',
'verb' => 'DELETE'
],
[
- 'name' => 'folders#markAllAsRead',
- 'url' => '/api/accounts/{accountId}/folders/{folderId}/read',
+ 'name' => 'mailboxes#markAllAsRead',
+ 'url' => '/api/mailboxes/{id}/read',
'verb' => 'POST'
],
[
- 'name' => 'folders#stats',
- 'url' => '/api/accounts/{accountId}/folders/{folderId}/stats',
+ 'name' => 'mailboxes#stats',
+ 'url' => '/api/mailboxes/{id}/stats',
'verb' => 'GET'
],
[
- 'name' => 'folders#delete',
- 'url' => '/api/accounts/{accountId}/folders/{folderId}',
- 'verb' => 'DELETE'
- ],
- [
'name' => 'messages#downloadAttachment',
- 'url' => '/api/accounts/{accountId}/folders/{folderId}/messages/{messageId}/attachment/{attachmentId}',
+ 'url' => '/api/messages/{id}/attachment/{attachmentId}',
'verb' => 'GET'
],
[
'name' => 'messages#saveAttachment',
- 'url' => '/api/accounts/{accountId}/folders/{folderId}/messages/{messageId}/attachment/{attachmentId}',
+ 'url' => '/api/messages/{id}/attachment/{attachmentId}',
'verb' => 'POST'
],
[
'name' => 'messages#getBody',
- 'url' => '/api/accounts/{accountId}/folders/{folderId}/messages/{messageId}/body',
+ 'url' => '/api/messages/{id}/body',
'verb' => 'GET'
],
[
'name' => 'messages#getSource',
- 'url' => '/api/accounts/{accountId}/folders/{folderId}/messages/{messageId}/source',
+ 'url' => '/api/messages/{id}/source',
'verb' => 'GET'
],
[
'name' => 'messages#getHtmlBody',
- 'url' => '/api/accounts/{accountId}/folders/{folderId}/messages/{messageId}/html',
+ 'url' => '/api/messages/{id}/html',
'verb' => 'GET'
],
[
'name' => 'messages#getThread',
- 'url' => '/api/accounts/{accountId}/message/{id}/thread',
+ 'url' => '/api/messages/{id}/thread',
'verb' => 'GET'
],
[
'name' => 'messages#setFlags',
- 'url' => '/api/accounts/{accountId}/folders/{folderId}/messages/{messageId}/flags',
+ 'url' => '/api/messages/{id}/flags',
'verb' => 'PUT'
],
[
'name' => 'messages#move',
- 'url' => '/api/accounts/{accountId}/folders/{folderId}/messages/{id}/move',
+ 'url' => '/api/messages/{id}/move',
'verb' => 'POST'
],
[
@@ -159,9 +184,9 @@ return [
'accounts' => ['url' => '/api/accounts'],
'aliases' => ['url' => '/api/accounts/{accountId}/aliases'],
'autoComplete' => ['url' => '/api/autoComplete'],
- 'folders' => ['url' => '/api/accounts/{accountId}/folders'],
'localAttachments' => ['url' => '/api/attachments'],
- 'messages' => ['url' => '/api/accounts/{accountId}/folders/{folderId}/messages'],
+ 'mailboxes' => ['url' => '/api/mailboxes'],
+ 'messages' => ['url' => '/api/messages'],
'preferences' => ['url' => '/api/preferences'],
]
];
diff --git a/lib/Attachment.php b/lib/Attachment.php
index 33acaace9..1770587be 100644
--- a/lib/Attachment.php
+++ b/lib/Attachment.php
@@ -32,13 +32,13 @@ class Attachment {
/**
* @param \Horde_Imap_Client_Socket $conn
* @param \Horde_Imap_Client_Mailbox $mailBox
- * @param int $messageId
+ * @param int $messageUid
* @param string $attachmentId
*/
- public function __construct($conn, $mailBox, $messageId, $attachmentId) {
+ public function __construct($conn, $mailBox, $messageUid, $attachmentId) {
$this->conn = $conn;
$this->mailBox = $mailBox;
- $this->messageId = $messageId;
+ $this->messageUid = $messageUid;
$this->attachmentId = $attachmentId;
$this->load();
@@ -53,7 +53,7 @@ class Attachment {
* @var \Horde_Imap_Client_Mailbox
*/
private $mailBox;
- private $messageId;
+ private $messageUid;
private $attachmentId;
/**
@@ -67,13 +67,13 @@ class Attachment {
$fetch_query->mimeHeader($this->attachmentId);
// $list is an array of Horde_Imap_Client_Data_Fetch objects.
- $ids = new \Horde_Imap_Client_Ids($this->messageId);
+ $ids = new \Horde_Imap_Client_Ids($this->messageUid);
$headers = $this->conn->fetch($this->mailBox, $fetch_query, ['ids' => $ids]);
/** @var $fetch Horde_Imap_Client_Data_Fetch */
- if (!isset($headers[$this->messageId])) {
+ if (!isset($headers[$this->messageUid])) {
throw new DoesNotExistException('Unable to load the attachment.');
}
- $fetch = $headers[$this->messageId];
+ $fetch = $headers[$this->messageUid];
/** @var \Horde_Mime_Headers $mimeHeaders */
$mimeHeaders = $fetch->getMimeHeader($this->attachmentId, Horde_Imap_Client_Data_Fetch::HEADER_PARSE);
diff --git a/lib/Contracts/IMailManager.php b/lib/Contracts/IMailManager.php
index 553aea52b..212aee8a8 100644
--- a/lib/Contracts/IMailManager.php
+++ b/lib/Contracts/IMailManager.php
@@ -25,16 +25,28 @@ namespace OCA\Mail\Contracts;
use OCA\Mail\Account;
use OCA\Mail\Db\Mailbox;
+use OCA\Mail\Db\Message;
use OCA\Mail\Exception\ClientException;
use OCA\Mail\Exception\ServiceException;
use OCA\Mail\Folder;
use OCA\Mail\IMAP\FolderStats;
use OCA\Mail\Model\IMAPMessage;
use OCA\Mail\Service\Quota;
+use OCP\AppFramework\Db\DoesNotExistException;
interface IMailManager {
/**
+ * @param string $uid
+ * @param int $id
+ *
+ * @return Mailbox
+ *
+ * @throws DoesNotExistException
+ */
+ public function getMailbox(string $uid, int $id): Mailbox;
+
+ /**
* @param Account $account
*
* @return Mailbox[]
@@ -47,44 +59,63 @@ interface IMailManager {
* @param Account $account
* @param string $name
*
- * @return Folder
+ * @return Mailbox
*
* @throws ServiceException
*/
- public function createFolder(Account $account, string $name): Folder;
+ public function createMailbox(Account $account, string $name): Mailbox;
/**
* @param Account $account
- * @param string $folderId
+ * @param Mailbox $mailbox
*
* @return FolderStats
+ */
+ public function getMailboxStats(Account $account, Mailbox $mailbox): FolderStats;
+
+ /**
+ * @param Mailbox $mailbox
+ * @param $uid
*
- * @throws ServiceException
+ * @return int|null
+ */
+ public function getMessageIdForUid(Mailbox $mailbox, $uid): ?int;
+
+ /**
+ * @param string $uid
+ * @param int $id
+ *
+ * @return Mailbox
+ *
+ * @throws ClientException
*/
- public function getFolderStats(Account $account, string $folderId): FolderStats;
+ public function getMessage(string $uid, int $id): Message;
/**
* @param Account $account
* @param string $mb
- * @param int $id
+ * @param int $uid
*
* @return string
* @throws ClientException
* @throws ServiceException
*/
- public function getSource(Account $account, string $mb, int $id): string;
+ public function getSource(Account $account, string $mb, int $uid): ?string;
/**
* @param Account $account
- * @param string $mailbox
- * @param int $id
+ * @param Mailbox $mailbox
+ * @param int $uid
* @param bool $loadBody
*
* @return IMAPMessage
*
* @throws ServiceException
*/
- public function getMessage(Account $account, string $mailbox, int $id, bool $loadBody = false): IMAPMessage;
+ public function getImapMessage(Account $account,
+ Mailbox $mailbox,
+ int $uid,
+ bool $loadBody = false): IMAPMessage;
/**
* @param Account $account
@@ -97,14 +128,17 @@ interface IMailManager {
/**
* @param Account $sourceAccount
* @param string $sourceFolderId
- * @param int $messageId
+ * @param int $uid
* @param Account $destinationAccount
* @param string $destFolderId
*
* @throws ServiceException
*/
- public function moveMessage(Account $sourceAccount, string $sourceFolderId, int $messageId,
- Account $destinationAccount, string $destFolderId);
+ public function moveMessage(Account $sourceAccount,
+ string $sourceFolderId,
+ int $uid,
+ Account $destinationAccount,
+ string $destFolderId);
/**
* @param Account $account
@@ -119,11 +153,9 @@ interface IMailManager {
* Mark all messages of a folder as read
*
* @param Account $account
- * @param string $folderId
- *
- * @throws ServiceException
+ * @param Mailbox $mailbox
*/
- public function markFolderAsRead(Account $account, string $folderId): void;
+ public function markFolderAsRead(Account $account, Mailbox $mailbox): void;
/**
* @param Account $account
@@ -146,9 +178,9 @@ interface IMailManager {
/**
* @param Account $account
- * @param string $folderId
+ * @param Mailbox $mailbox
*
* @throws ServiceException
*/
- public function deleteMailbox(Account $account, string $folderId): void;
+ public function deleteMailbox(Account $account, Mailbox $mailbox): void;
}
diff --git a/lib/Contracts/IMailSearch.php b/lib/Contracts/IMailSearch.php
index 9487334b2..c751e2c53 100644
--- a/lib/Contracts/IMailSearch.php
+++ b/lib/Contracts/IMailSearch.php
@@ -26,6 +26,7 @@ declare(strict_types=1);
namespace OCA\Mail\Contracts;
use OCA\Mail\Account;
+use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\Message;
use OCA\Mail\Exception\ClientException;
use OCA\Mail\Exception\ServiceException;
@@ -43,18 +44,25 @@ interface IMailSearch {
* @throws ClientException
* @throws ServiceException
*/
- public function findMessage(Account $account, string $mailboxName, int $uid): Message;
+ public function findMessage(Account $account,
+ Mailbox $mailbox,
+ Message $message): Message;
/**
* @param Account $account
- * @param string $mailboxName
+ * @param Mailbox $mailbox
* @param string|null $filter
* @param int|null $cursor
+ * @param int|null $limit
*
* @return Message[]
*
* @throws ClientException
* @throws ServiceException
*/
- public function findMessages(Account $account, string $mailboxName, ?string $filter, ?int $cursor, ?int $limit): array;
+ public function findMessages(Account $account,
+ Mailbox $mailbox,
+ ?string $filter,
+ ?int $cursor,
+ ?int $limit): array;
}
diff --git a/lib/Contracts/IMailTransmission.php b/lib/Contracts/IMailTransmission.php
index ff1d04138..d4e4c3c57 100644
--- a/lib/Contracts/IMailTransmission.php
+++ b/lib/Contracts/IMailTransmission.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace OCA\Mail\Contracts;
use OCA\Mail\Db\Alias;
+use OCA\Mail\Db\Message;
use OCA\Mail\Exception\ServiceException;
use OCA\Mail\Model\NewMessageData;
use OCA\Mail\Model\RepliedMessageData;
@@ -33,27 +34,27 @@ interface IMailTransmission {
/**
* Send a new message or reply to an existing one
*
- * @param string $userId
* @param NewMessageData $message
- * @param RepliedMessageData $reply
+ * @param RepliedMessageData|null $reply
* @param Alias|null $alias
+ * @param Message|null $draft
*
* @throws ServiceException
*/
public function sendMessage(NewMessageData $message,
RepliedMessageData $reply = null,
Alias $alias = null,
- int $draftUID = null);
+ Message $draft = null);
/**
* Save a message draft
*
* @param NewMessageData $message
- * @param int $draftUID
+ * @param Message|null $previousDraft
*
- * @return int
+ * @return array
*
* @throws ServiceException
*/
- public function saveDraft(NewMessageData $message, int $draftUID = null): int;
+ public function saveDraft(NewMessageData $message, Message $previousDraft = null): array;
}
diff --git a/lib/Controller/AccountsController.php b/lib/Controller/AccountsController.php
index e5c8a94bb..94221eb09 100644
--- a/lib/Controller/AccountsController.php
+++ b/lib/Controller/AccountsController.php
@@ -30,8 +30,10 @@ declare(strict_types=1);
namespace OCA\Mail\Controller;
use Exception;
+use Horde_Imap_Client;
use OCA\Mail\Contracts\IMailManager;
use OCA\Mail\Contracts\IMailTransmission;
+use OCA\Mail\Db\Mailbox;
use OCA\Mail\Exception\ClientException;
use OCA\Mail\Exception\ServiceException;
use OCA\Mail\Http\JsonResponse as MailJsonResponse;
@@ -41,6 +43,7 @@ use OCA\Mail\Service\AccountService;
use OCA\Mail\Service\AliasesService;
use OCA\Mail\Service\GroupsIntegration;
use OCA\Mail\Service\SetupService;
+use OCA\Mail\Service\Sync\SyncService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
@@ -77,17 +80,37 @@ class AccountsController extends Controller {
/** @var IMailManager */
private $mailManager;
+ /** @var SyncService */
+ private $syncService;
+
+ /**
+ * AccountsController constructor.
+ *
+ * @param string $appName
+ * @param IRequest $request
+ * @param AccountService $accountService
+ * @param GroupsIntegration $groupsIntegration
+ * @param $UserId
+ * @param ILogger $logger
+ * @param IL10N $l10n
+ * @param AliasesService $aliasesService
+ * @param IMailTransmission $mailTransmission
+ * @param SetupService $setup
+ * @param IMailManager $mailManager
+ * @param SyncService $syncService
+ */
public function __construct(string $appName,
- IRequest $request,
- AccountService $accountService,
- GroupsIntegration $groupsIntegration,
- $UserId,
- ILogger $logger,
- IL10N $l10n,
- AliasesService $aliasesService,
- IMailTransmission $mailTransmission,
- SetupService $setup,
- IMailManager $mailManager
+ IRequest $request,
+ AccountService $accountService,
+ GroupsIntegration $groupsIntegration,
+ $UserId,
+ ILogger $logger,
+ IL10N $l10n,
+ AliasesService $aliasesService,
+ IMailTransmission $mailTransmission,
+ SetupService $setup,
+ IMailManager $mailManager,
+ SyncService $syncService
) {
parent::__construct($appName, $request);
$this->accountService = $accountService;
@@ -99,6 +122,7 @@ class AccountsController extends Controller {
$this->mailTransmission = $mailTransmission;
$this->setup = $setup;
$this->mailManager = $mailManager;
+ $this->syncService = $syncService;
}
/**
@@ -123,13 +147,13 @@ class AccountsController extends Controller {
* @NoAdminRequired
* @TrapError
*
- * @param int $accountId
+ * @param int $id
*
* @return JSONResponse
* @throws ClientException
*/
- public function show($accountId): JSONResponse {
- return new JSONResponse($this->accountService->find($this->currentUserId, $accountId));
+ public function show(int $id): JSONResponse {
+ return new JSONResponse($this->accountService->find($this->currentUserId, $id));
}
/**
@@ -198,7 +222,7 @@ class AccountsController extends Controller {
* @NoAdminRequired
* @TrapError
*
- * @param int $accountId
+ * @param int $id
* @param string|null $editorMode
* @param int|null $order
* @param bool|null $showSubscribedOnly
@@ -207,11 +231,11 @@ class AccountsController extends Controller {
*
* @throws ClientException
*/
- public function patchAccount(int $accountId,
+ public function patchAccount(int $id,
string $editorMode = null,
int $order = null,
bool $showSubscribedOnly = null): JSONResponse {
- $account = $this->accountService->find($this->currentUserId, $accountId);
+ $account = $this->accountService->find($this->currentUserId, $id);
if ($account === null) {
return new JSONResponse(null, Http::STATUS_FORBIDDEN);
@@ -236,7 +260,7 @@ class AccountsController extends Controller {
* @NoAdminRequired
* @TrapError
*
- * @param int $accountId
+ * @param int $id
* @param string|null $signature
*
* @return JSONResponse
@@ -244,8 +268,8 @@ class AccountsController extends Controller {
* @throws ClientException
* @throws ServiceException
*/
- public function updateSignature(int $accountId, string $signature = null): JSONResponse {
- $this->accountService->updateSignature($accountId, $this->currentUserId, $signature);
+ public function updateSignature(int $id, string $signature = null): JSONResponse {
+ $this->accountService->updateSignature($id, $this->currentUserId, $signature);
return new JSONResponse();
}
@@ -259,7 +283,7 @@ class AccountsController extends Controller {
*
* @throws ClientException
*/
- public function destroy($id): JSONResponse {
+ public function destroy(int $id): JSONResponse {
$this->accountService->delete($this->currentUserId, $id);
return new JSONResponse();
}
@@ -315,13 +339,13 @@ class AccountsController extends Controller {
* @NoAdminRequired
* @TrapError
*
- * @param int $accountId
+ * @param int $id
* @param string $subject
* @param string $body
* @param string $to
* @param string $cc
* @param string $bcc
- * @param int|null $draftUID
+ * @param int|null $draftId
* @param string|null $folderId
* @param int|null $messageId
* @param mixed $attachments
@@ -332,19 +356,19 @@ class AccountsController extends Controller {
* @throws ClientException
* @throws ServiceException
*/
- public function send(int $accountId,
+ public function send(int $id,
string $subject,
string $body,
string $to,
string $cc,
string $bcc,
bool $isHtml = true,
- int $draftUID = null,
+ int $draftId = null,
string $folderId = null,
int $messageId = null,
array $attachments = [],
int $aliasId = null): JSONResponse {
- $account = $this->accountService->find($this->currentUserId, $accountId);
+ $account = $this->accountService->find($this->currentUserId, $id);
$alias = $aliasId ? $this->aliasesService->find($aliasId, $this->currentUserId) : null;
$expandedTo = $this->groupsIntegration->expand($to);
@@ -357,8 +381,16 @@ class AccountsController extends Controller {
$repliedMessageData = new RepliedMessageData($account, base64_decode($folderId), $messageId);
}
+ $draft = null;
+ if ($draftId !== null) {
+ try {
+ $draft = $this->mailManager->getMessage($this->currentUserId, $draftId);
+ } catch (ClientException $e) {
+ $this->logger->info("Draft " . $draftId . " could not be loaded: " . $e->getMessage());
+ }
+ }
try {
- $this->mailTransmission->sendMessage($messageData, $repliedMessageData, $alias, $draftUID);
+ $this->mailTransmission->sendMessage($messageData, $repliedMessageData, $alias, $draft);
return new JSONResponse();
} catch (ServiceException $ex) {
$this->logger->error('Sending mail failed: ' . $ex->getMessage());
@@ -370,7 +402,7 @@ class AccountsController extends Controller {
* @NoAdminRequired
* @TrapError
*
- * @param int $accountId
+ * @param int $id
* @param string $subject
* @param string $body
* @param string $to
@@ -382,27 +414,43 @@ class AccountsController extends Controller {
*
* @throws ClientException
*/
- public function draft(int $accountId,
- string $subject = null,
+ public function draft(int $id,
+ string $subject,
string $body,
string $to,
string $cc,
string $bcc,
bool $isHtml = true,
- int $draftUID = null): JSONResponse {
- if ($draftUID === null) {
- $this->logger->info("Saving a new draft in account <$accountId>");
+ int $draftId = null): JSONResponse {
+ if ($draftId === null) {
+ $this->logger->info("Saving a new draft in account <$id>");
} else {
- $this->logger->info("Updating draft <$draftUID> in account <$accountId>");
+ $this->logger->info("Updating draft <$draftId> in account <$id>");
}
- $account = $this->accountService->find($this->currentUserId, $accountId);
+ $account = $this->accountService->find($this->currentUserId, $id);
+ $previousDraft = null;
+ if ($draftId !== null) {
+ try {
+ $previousDraft = $this->mailManager->getMessage($this->currentUserId, $draftId);
+ } catch (ClientException $e) {
+ $this->logger->info("Draft " . $draftId . " could not be loaded: " . $e->getMessage());
+ }
+ }
$messageData = NewMessageData::fromRequest($account, $to, $cc, $bcc, $subject, $body, [], $isHtml);
try {
- $newUID = $this->mailTransmission->saveDraft($messageData, $draftUID);
+ /** @var Mailbox $draftsMailbox */
+ [, $draftsMailbox, $newUID] = $this->mailTransmission->saveDraft($messageData, $previousDraft);
+ $this->syncService->syncMailbox(
+ $account,
+ $draftsMailbox,
+ Horde_Imap_Client::SYNC_NEWMSGS,
+ [],
+ false
+ );
return new JSONResponse([
- 'uid' => $newUID,
+ 'id' => $this->mailManager->getMessageIdForUid($draftsMailbox, $newUID)
]);
} catch (ServiceException $ex) {
$this->logger->error('Saving draft failed: ' . $ex->getMessage());
@@ -413,13 +461,13 @@ class AccountsController extends Controller {
/**
* @NoAdminRequired
*
- * @param int $accountId
+ * @param int $id
*
* @return JSONResponse
* @throws ClientException
*/
- public function getQuota(int $accountId): JSONResponse {
- $account = $this->accountService->find($this->currentUserId, $accountId);
+ public function getQuota(int $id): JSONResponse {
+ $account = $this->accountService->find($this->currentUserId, $id);
$quota = $this->mailManager->getQuota($account);
if ($quota === null) {
diff --git a/lib/Controller/AliasesController.php b/lib/Controller/AliasesController.php
index cda86bd65..ca9d61589 100644
--- a/lib/Controller/AliasesController.php
+++ b/lib/Controller/AliasesController.php
@@ -54,9 +54,10 @@ class AliasesController extends Controller {
* @TrapError
*
* @param int $accountId
+ *
* @return JSONResponse
*/
- public function index($accountId): JSONResponse {
+ public function index(int $accountId): JSONResponse {
return new JSONResponse($this->aliasService->findAll($accountId, $this->currentUser->getUID()));
}
@@ -83,7 +84,7 @@ class AliasesController extends Controller {
* @param int $id
* @return JSONResponse
*/
- public function destroy($id): JSONResponse {
+ public function destroy(int $id): JSONResponse {
return new JSONResponse($this->aliasService->delete($id, $this->currentUser->getUID()));
}
@@ -94,9 +95,10 @@ class AliasesController extends Controller {
* @param int $accountId
* @param string $alias
* @param string $aliasName
+ *
* @return JSONResponse
*/
- public function create($accountId, $alias, $aliasName): JSONResponse {
+ public function create(int $accountId, string $alias, string $aliasName): JSONResponse {
return new JSONResponse($this->aliasService->create($accountId, $alias, $aliasName), Http::STATUS_CREATED);
}
}
diff --git a/lib/Controller/FoldersController.php b/lib/Controller/MailboxesController.php
index 2527658e5..c7ad55007 100644
--- a/lib/Controller/FoldersController.php
+++ b/lib/Controller/MailboxesController.php
@@ -31,8 +31,6 @@ use OCA\Mail\Exception\IncompleteSyncException;
use OCA\Mail\Exception\MailboxNotCachedException;
use OCA\Mail\Exception\ServiceException;
use OCA\Mail\Service\Sync\SyncService;
-use function base64_decode;
-use function is_array;
use OCA\Mail\Contracts\IMailManager;
use OCA\Mail\Exception\NotImplemented;
use OCA\Mail\Service\AccountService;
@@ -41,7 +39,7 @@ use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
use OCP\IRequest;
-class FoldersController extends Controller {
+class MailboxesController extends Controller {
/** @var AccountService */
private $accountService;
@@ -66,7 +64,7 @@ class FoldersController extends Controller {
public function __construct(string $appName,
IRequest $request,
AccountService $accountService,
- $UserId,
+ ?string $UserId,
IMailManager $mailManager,
SyncService $syncService) {
parent::__construct($appName, $request);
@@ -94,7 +92,7 @@ class FoldersController extends Controller {
return new JSONResponse([
'id' => $accountId,
'email' => $account->getEmail(),
- 'folders' => $mailboxes,
+ 'mailboxes' => $mailboxes,
'delimiter' => reset($mailboxes)->getDelimiter(),
]);
}
@@ -103,30 +101,28 @@ class FoldersController extends Controller {
* @NoAdminRequired
* @TrapError
*
- * @param int $accountId
- * @param string $folderId
- * @param string $syncToken
- * @param int[] $uids
+ * @param int $id
+ * @param int[] $ids
+ *
+ * @param bool $init
+ * @param string|null $query
*
* @return JSONResponse
* @throws ClientException
* @throws ServiceException
*/
- public function sync(int $accountId, string $folderId, array $uids = [], bool $init = false, string $query = null): JSONResponse {
- $account = $this->accountService->find($this->currentUserId, $accountId);
-
- if (empty($accountId) || empty($folderId) || !is_array($uids)) {
- return new JSONResponse(null, Http::STATUS_BAD_REQUEST);
- }
+ public function sync(int $id, array $ids = [], bool $init = false, string $query = null): JSONResponse {
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $id);
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
try {
$syncResponse = $this->syncService->syncMailbox(
$account,
- base64_decode($folderId),
+ $mailbox,
Horde_Imap_Client::SYNC_NEWMSGSUIDS | Horde_Imap_Client::SYNC_FLAGSUIDS | Horde_Imap_Client::SYNC_VANISHEDUIDS,
- array_map(function ($uid) {
- return (int) $uid;
- }, $uids),
+ array_map(function ($id) {
+ return (int) $id;
+ }, $ids),
!$init,
$query
);
@@ -143,21 +139,17 @@ class FoldersController extends Controller {
* @NoAdminRequired
* @TrapError
*
- * @param int $accountId
- * @param string $folderId
+ * @param string $id
*
* @return JSONResponse
* @throws ClientException
* @throws ServiceException
*/
- public function clearCache(int $accountId, string $folderId): JSONResponse {
- $account = $this->accountService->find($this->currentUserId, $accountId);
+ public function clearCache(int $id): JSONResponse {
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $id);
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
- if (empty($accountId) || empty($folderId)) {
- return new JSONResponse(null, Http::STATUS_BAD_REQUEST);
- }
-
- $this->syncService->clearCache($account, base64_decode($folderId));
+ $this->syncService->clearCache($account, $mailbox);
return new JSONResponse(null);
}
@@ -165,43 +157,37 @@ class FoldersController extends Controller {
* @NoAdminRequired
* @TrapError
*
- * @param int $accountId
- * @param string $folderId
+ * @param int $id
+ *
* @return JSONResponse
*
* @throws ClientException
*/
- public function markAllAsRead(int $accountId, string $folderId): JSONResponse {
- $account = $this->accountService->find($this->currentUserId, $accountId);
-
- if (empty($accountId) || empty($folderId)) {
- return new JSONResponse(null, Http::STATUS_BAD_REQUEST);
- }
+ public function markAllAsRead(int $id): JSONResponse {
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $id);
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
- $syncResponse = $this->mailManager->markFolderAsRead($account, base64_decode($folderId));
+ $this->mailManager->markFolderAsRead($account, $mailbox);
- return new JSONResponse($syncResponse);
+ return new JSONResponse(null);
}
/**
* @NoAdminRequired
* @TrapError
*
- * @param int $accountId
- * @param string $folderId
+ * @param int $id
*
* @return JSONResponse
*
* @throws ClientException
+ * @throws ServiceException
*/
- public function stats(int $accountId, string $folderId): JSONResponse {
- $account = $this->accountService->find($this->currentUserId, $accountId);
-
- if (empty($accountId) || empty($folderId)) {
- return new JSONResponse(null, Http::STATUS_BAD_REQUEST);
- }
+ public function stats(int $id): JSONResponse {
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $id);
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
- $stats = $this->mailManager->getFolderStats($account, base64_decode($folderId));
+ $stats = $this->mailManager->getMailboxStats($account, $mailbox);
return new JSONResponse($stats);
}
@@ -232,19 +218,24 @@ class FoldersController extends Controller {
public function create(int $accountId, string $name) {
$account = $this->accountService->find($this->currentUserId, $accountId);
- return new JSONResponse($this->mailManager->createFolder($account, $name));
+ return new JSONResponse($this->mailManager->createMailbox($account, $name));
}
/**
* @NoAdminRequired
* @TrapError
- * @param int $accountId
- * @param string $folderId
+ *
+ * @param int $id
+ *
+ * @return JSONResponse
+ * @throws ClientException
* @throws ServiceException
*/
- public function delete(int $accountId, string $folderId): JSONResponse {
- $account = $this->accountService->find($this->currentUserId, $accountId);
- $this->mailManager->deleteMailbox($account, base64_decode($folderId));
+ public function destroy(int $id): JSONResponse {
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $id);
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
+
+ $this->mailManager->deleteMailbox($account, $mailbox);
return new JSONResponse();
}
}
diff --git a/lib/Controller/MessagesController.php b/lib/Controller/MessagesController.php
index ef6357835..df602bf94 100755
--- a/lib/Controller/MessagesController.php
+++ b/lib/Controller/MessagesController.php
@@ -39,7 +39,6 @@ use OCA\Mail\Http\AttachmentDownloadResponse;
use OCA\Mail\Http\HtmlResponse;
use OCA\Mail\Model\IMAPMessage;
use OCA\Mail\Service\AccountService;
-use OCA\Mail\Service\IMailBox;
use OCA\Mail\Service\ItineraryService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Db\DoesNotExistException;
@@ -55,7 +54,6 @@ use OCP\ILogger;
use OCP\IRequest;
use OCP\IURLGenerator;
use function array_map;
-use function base64_decode;
class MessagesController extends Controller {
@@ -131,29 +129,33 @@ class MessagesController extends Controller {
* @NoAdminRequired
* @TrapError
*
- * @param int $accountId
- * @param string $folderId
+ * @param int $mailboxId
* @param int $cursor
* @param string $filter
+ * @param int|null $limit
*
* @return JSONResponse
*
* @throws ClientException
* @throws ServiceException
*/
- public function index(int $accountId, string $folderId, int $cursor = null, string $filter = null, int $limit = null): JSONResponse {
+ public function index(int $mailboxId,
+ int $cursor = null,
+ string $filter = null,
+ int $limit = null): JSONResponse {
try {
- $account = $this->accountService->find($this->currentUserId, $accountId);
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $mailboxId);
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
} catch (DoesNotExistException $e) {
return new JSONResponse(null, Http::STATUS_FORBIDDEN);
}
- $this->logger->debug("loading messages of folder <$folderId>");
+ $this->logger->debug("loading messages of folder <$mailboxId>");
return new JSONResponse(
$this->mailSearch->findMessages(
$account,
- base64_decode($folderId),
+ $mailbox,
$filter === '' ? null : $filter,
$cursor,
$limit
@@ -174,20 +176,22 @@ class MessagesController extends Controller {
* @throws ClientException
* @throws ServiceException
*/
- public function show(int $accountId, string $folderId, int $id): JSONResponse {
+ public function show(int $id): JSONResponse {
try {
- $account = $this->accountService->find($this->currentUserId, $accountId);
+ $message = $this->mailManager->getMessage($this->currentUserId, $id);
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
} catch (DoesNotExistException $e) {
return new JSONResponse(null, Http::STATUS_FORBIDDEN);
}
- $this->logger->debug("loading message of folder <$folderId>");
+ $this->logger->debug("loading message <$id>");
return new JSONResponse(
$this->mailSearch->findMessage(
$account,
- base64_decode($folderId),
- $id
+ $mailbox,
+ $message
)
);
}
@@ -196,40 +200,40 @@ class MessagesController extends Controller {
* @NoAdminRequired
* @TrapError
*
- * @param int $accountId
- * @param string $folderId
- * @param int $messageId
+ * @param int $id
*
* @return JSONResponse
*
* @throws ClientException
* @throws ServiceException
*/
- public function getBody(int $accountId, string $folderId, int $messageId): JSONResponse {
+ public function getBody(int $id): JSONResponse {
try {
- $account = $this->accountService->find($this->currentUserId, $accountId);
+ $message = $this->mailManager->getMessage($this->currentUserId, $id);
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
} catch (DoesNotExistException $e) {
return new JSONResponse(null, Http::STATUS_FORBIDDEN);
}
- $json = $this->mailManager->getMessage(
+ $json = $this->mailManager->getImapMessage(
$account,
- base64_decode($folderId),
- $messageId,
+ $mailbox,
+ $message->getUid(),
true
- )->getFullMessage(
- $accountId,
- base64_decode($folderId),
- $messageId
- );
+ )->getFullMessage($id);
$json['itineraries'] = $this->itineraryService->extract(
$account,
- base64_decode($folderId),
- $messageId
+ $mailbox->getName(),
+ $message->getUid()
);
- $json['attachments'] = array_map(function ($a) use ($accountId, $folderId, $messageId) {
- return $this->enrichDownloadUrl($accountId, $folderId, $messageId, $a);
+ $json['attachments'] = array_map(function ($a) use ($id) {
+ return $this->enrichDownloadUrl(
+ $id,
+ $a
+ );
}, $json['attachments']);
+ $json['databaseId'] = $message->getId();
return new JSONResponse($json);
}
@@ -239,14 +243,19 @@ class MessagesController extends Controller {
* @NoCSRFRequired
* @TrapError
*
- * @param int $accountId
- * @param string $folderId
+ * @param int $id
*
* @return JSONResponse
* @throws ClientException
*/
- public function getThread(int $accountId, int $id): JSONResponse {
- $account = $this->accountService->find($this->currentUserId, $accountId);
+ public function getThread(int $id): JSONResponse {
+ try {
+ $message = $this->mailManager->getMessage($this->currentUserId, $id);
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
+ } catch (DoesNotExistException $e) {
+ return new JSONResponse(null, Http::STATUS_FORBIDDEN);
+ }
return new JSONResponse($this->mailManager->getThread($account, $id));
}
@@ -255,10 +264,7 @@ class MessagesController extends Controller {
* @NoAdminRequired
* @TrapError
*
- * @param int $accountId
- * @param string $folderId
* @param int $id
- * @param int $destAccountId
* @param string $destFolderId
*
* @return JSONResponse
@@ -266,12 +272,24 @@ class MessagesController extends Controller {
* @throws ClientException
* @throws ServiceException
*/
- public function move($accountId, $folderId, $id, $destAccountId, $destFolderId): JSONResponse {
- $srcAccount = $this->accountService->find($this->currentUserId, $accountId);
- $dstAccount = $this->accountService->find($this->currentUserId,
- $destAccountId);
- $this->mailManager->moveMessage($srcAccount, base64_decode($folderId), $id,
- $dstAccount, base64_decode($destFolderId));
+ public function move(int $id, int $destFolderId): JSONResponse {
+ try {
+ $message = $this->mailManager->getMessage($this->currentUserId, $id);
+ $srcMailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
+ $dstMailbox = $this->mailManager->getMailbox($this->currentUserId, $destFolderId);
+ $srcAccount = $this->accountService->find($this->currentUserId, $srcMailbox->getAccountId());
+ $dstAccount = $this->accountService->find($this->currentUserId, $dstMailbox->getAccountId());
+ } catch (DoesNotExistException $e) {
+ return new JSONResponse(null, Http::STATUS_FORBIDDEN);
+ }
+
+ $this->mailManager->moveMessage(
+ $srcAccount,
+ $srcMailbox->getName(),
+ $message->getUid(),
+ $dstAccount,
+ $dstMailbox->getName()
+ );
return new JSONResponse();
}
@@ -284,17 +302,23 @@ class MessagesController extends Controller {
* @param string $folderId
* @param int $messageId
*
- * @return HtmlResponse|TemplateResponse
+ * @return JSONResponse
* @throws ServiceException
*/
- public function getSource(int $accountId, string $folderId, int $messageId): JSONResponse {
- $account = $this->accountService->find($this->currentUserId, $accountId);
+ public function getSource(int $id): JSONResponse {
+ try {
+ $message = $this->mailManager->getMessage($this->currentUserId, $id);
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
+ } catch (DoesNotExistException $e) {
+ return new JSONResponse(null, Http::STATUS_FORBIDDEN);
+ }
$response = new JSONResponse([
'source' => $this->mailManager->getSource(
$account,
- base64_decode($folderId),
- $messageId
+ $mailbox->getName(),
+ $message->getUid()
)
]);
@@ -309,18 +333,18 @@ class MessagesController extends Controller {
* @NoCSRFRequired
* @TrapError
*
- * @param int $accountId
- * @param string $folderId
- * @param int $messageId
+ * @param int $id
*
* @return HtmlResponse|TemplateResponse
*
* @throws ClientException
*/
- public function getHtmlBody(int $accountId, string $folderId, int $messageId): Response {
+ public function getHtmlBody(int $id): Response {
try {
try {
- $account = $this->accountService->find($this->currentUserId, $accountId);
+ $message = $this->mailManager->getMessage($this->currentUserId, $id);
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
} catch (DoesNotExistException $e) {
return new TemplateResponse(
$this->appName,
@@ -331,12 +355,14 @@ class MessagesController extends Controller {
}
$htmlResponse = new HtmlResponse(
- $this->mailManager->getMessage(
+ $this->mailManager->getImapMessage(
$account,
- base64_decode($folderId),
- $messageId,
+ $mailbox,
+ $message->getUid(),
true
- )->getHtmlBody($accountId, base64_decode($folderId), $messageId)
+ )->getHtmlBody(
+ $id
+ )
);
// Harden the default security policy
@@ -369,19 +395,25 @@ class MessagesController extends Controller {
*
* @param int $accountId
* @param string $folderId
- * @param int $messageId
+ * @param int $id
* @param int $attachmentId
*
- * @return AttachmentDownloadResponse
+ * @return Response
*
* @throws ClientException
* @throws ServiceException
*/
- public function downloadAttachment(int $accountId, string $folderId, int $messageId,
- string $attachmentId) {
- $mailBox = $this->getFolder($accountId, $folderId);
-
- $attachment = $mailBox->getAttachment($messageId, $attachmentId);
+ public function downloadAttachment(int $id,
+ string $attachmentId): Response {
+ try {
+ $message = $this->mailManager->getMessage($this->currentUserId, $id);
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
+ } catch (DoesNotExistException $e) {
+ return new JSONResponse(null, Http::STATUS_FORBIDDEN);
+ }
+ $folder = $account->getMailbox($mailbox->getName());
+ $attachment = $folder->getAttachment($message->getUid(), $attachmentId);
// Body party and embedded messages do not have a name
if ($attachment->getName() === null) {
@@ -404,9 +436,7 @@ class MessagesController extends Controller {
* @NoAdminRequired
* @TrapError
*
- * @param int $accountId
- * @param string $folderId
- * @param int $messageId
+ * @param int $id
* @param int $attachmentId
* @param string $targetPath
*
@@ -415,14 +445,22 @@ class MessagesController extends Controller {
* @throws ClientException
* @throws ServiceException
*/
- public function saveAttachment(int $accountId, string $folderId, int $messageId,
- string $attachmentId, string $targetPath) {
- $mailBox = $this->getFolder($accountId, $folderId);
+ public function saveAttachment(int $id,
+ string $attachmentId,
+ string $targetPath) {
+ try {
+ $message = $this->mailManager->getMessage($this->currentUserId, $id);
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
+ } catch (DoesNotExistException $e) {
+ return new JSONResponse(null, Http::STATUS_FORBIDDEN);
+ }
+ $folder = $account->getMailbox($mailbox->getName());
if ($attachmentId === '0') {
// Save all attachments
/* @var $m IMAPMessage */
- $m = $mailBox->getMessage($messageId);
+ $m = $folder->getMessage($id);
$attachmentIds = array_map(function ($a) {
return $a['id'];
}, $m->attachments);
@@ -430,11 +468,11 @@ class MessagesController extends Controller {
$attachmentIds = [$attachmentId];
}
- foreach ($attachmentIds as $attachmentId) {
- $attachment = $mailBox->getAttachment($messageId, $attachmentId);
+ foreach ($attachmentIds as $aid) {
+ $attachment = $folder->getAttachment($message->getUid(), $attachmentId);
$fileName = $attachment->getName() ?? $this->l10n->t('Embedded message %s', [
- $attachmentId,
+ $aid,
]) . '.eml';
$fileParts = pathinfo($fileName);
$fileName = $fileParts['filename'];
@@ -456,9 +494,7 @@ class MessagesController extends Controller {
* @NoAdminRequired
* @TrapError
*
- * @param int $accountId
- * @param string $folderId
- * @param string $messageId
+ * @param string $id
* @param array $flags
*
* @return JSONResponse
@@ -466,12 +502,18 @@ class MessagesController extends Controller {
* @throws ClientException
* @throws ServiceException
*/
- public function setFlags(int $accountId, string $folderId, int $messageId, array $flags): JSONResponse {
- $account = $this->accountService->find($this->currentUserId, $accountId);
+ public function setFlags(int $id, array $flags): JSONResponse {
+ try {
+ $message = $this->mailManager->getMessage($this->currentUserId, $id);
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
+ } catch (DoesNotExistException $e) {
+ return new JSONResponse(null, Http::STATUS_FORBIDDEN);
+ }
foreach ($flags as $flag => $value) {
$value = filter_var($value, FILTER_VALIDATE_BOOLEAN);
- $this->mailManager->flagMessage($account, base64_decode($folderId), $messageId, $flag, $value);
+ $this->mailManager->flagMessage($account, $mailbox->getName(), $message->getUid(), $flag, $value);
}
return new JSONResponse();
}
@@ -489,49 +531,36 @@ class MessagesController extends Controller {
* @throws ClientException
* @throws ServiceException
*/
- public function destroy(int $accountId, string $folderId, int $id): JSONResponse {
- $this->logger->debug("deleting message <$id> of folder <$folderId>, account <$accountId>");
-
+ public function destroy(int $id): JSONResponse {
try {
- $account = $this->accountService->find($this->currentUserId, $accountId);
+ $message = $this->mailManager->getMessage($this->currentUserId, $id);
+ $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId());
+ $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId());
} catch (DoesNotExistException $e) {
return new JSONResponse(null, Http::STATUS_FORBIDDEN);
}
- $this->mailManager->deleteMessage($account, base64_decode($folderId), $id);
- return new JSONResponse();
- }
+ $this->logger->debug("deleting message <$id>");
- /**
- * @param int $accountId
- * @param string $folderId
- *
- * @return IMailBox
- * @deprecated
- *
- * @throws ClientException
- * @throws ServiceException
- */
- private function getFolder(int $accountId, string $folderId): IMailBox {
- $account = $this->accountService->find($this->currentUserId, $accountId);
- return $account->getMailbox(base64_decode($folderId));
+ $this->mailManager->deleteMessage(
+ $account,
+ $mailbox->getName(),
+ $message->getUid()
+ );
+ return new JSONResponse();
}
/**
- * @param int $accountId
- * @param string $folderId
- * @param int $messageId
+ * @param int $id
* @param array $attachment
*
* @return array
*/
- private function enrichDownloadUrl(int $accountId, string $folderId, int $messageId,
+ private function enrichDownloadUrl(int $id,
array $attachment) {
$downloadUrl = $this->urlGenerator->linkToRoute('mail.messages.downloadAttachment',
[
- 'accountId' => $accountId,
- 'folderId' => $folderId,
- 'messageId' => $messageId,
+ 'id' => $id,
'attachmentId' => $attachment['id'],
]);
$downloadUrl = $this->urlGenerator->getAbsoluteURL($downloadUrl);
diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php
index 219bb16ff..fe9181760 100644
--- a/lib/Controller/PageController.php
+++ b/lib/Controller/PageController.php
@@ -117,13 +117,13 @@ class PageController extends Controller {
$this->currentUserId);
try {
$mailboxes = $this->mailManager->getMailboxes($mailAccount);
- $json['folders'] = $mailboxes;
+ $json['mailboxes'] = $mailboxes;
} catch (Exception $ex) {
$this->logger->logException($ex, [
- 'message' => 'Could not load account folders: ' . $ex->getMessage(),
+ 'message' => 'Could not load account mailboxes: ' . $ex->getMessage(),
'level' => ILogger::FATAL,
]);
- $json['folders'] = [];
+ $json['mailboxes'] = [];
$json['error'] = true;
}
$accountsJson[] = $json;
@@ -160,6 +160,56 @@ class PageController extends Controller {
* @NoAdminRequired
* @NoCSRFRequired
*
+ * @return TemplateResponse
+ */
+ public function setup(): TemplateResponse {
+ return $this->index();
+ }
+
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ *
+ * @return TemplateResponse
+ */
+ public function keyboardShortcuts(): TemplateResponse {
+ return $this->index();
+ }
+
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ *
+ * @return TemplateResponse
+ */
+ public function accountSettings(int $id): TemplateResponse {
+ return $this->index();
+ }
+
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ *
+ * @return TemplateResponse
+ */
+ public function mailbox(int $id): TemplateResponse {
+ return $this->index();
+ }
+
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ *
+ * @return TemplateResponse
+ */
+ public function thread(int $mailboxId, int $id): TemplateResponse {
+ return $this->index();
+ }
+
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ *
* @param string $uri
*
* @return RedirectResponse
diff --git a/lib/Db/MailAccount.php b/lib/Db/MailAccount.php
index 36fb54cdf..c63abe27c 100644
--- a/lib/Db/MailAccount.php
+++ b/lib/Db/MailAccount.php
@@ -153,6 +153,7 @@ class MailAccount extends Entity {
*/
public function toJson() {
$result = [
+ 'id' => $this->getId(),
'accountId' => $this->getId(),
'name' => $this->getName(),
'order' => $this->getOrder(),
diff --git a/lib/Db/Mailbox.php b/lib/Db/Mailbox.php
index 2a877ee64..0da25c85f 100644
--- a/lib/Db/Mailbox.php
+++ b/lib/Db/Mailbox.php
@@ -121,12 +121,14 @@ class Mailbox extends Entity implements JsonSerializable {
return [
'databaseId' => $this->getId(),
'id' => base64_encode($this->getName()),
+ 'name' => $this->getName(),
'accountId' => $this->accountId,
'displayName' => $this->getName(),
'attributes' => json_decode($this->attributes ?? '[]', true) ?? [],
'delimiter' => $this->delimiter,
'specialUse' => $specialUse,
'specialRole' => $specialUse[0] ?? 0,
+ 'mailboxes' => [],
];
}
}
diff --git a/lib/Db/MailboxMapper.php b/lib/Db/MailboxMapper.php
index d2361b927..0b2ae36ce 100644
--- a/lib/Db/MailboxMapper.php
+++ b/lib/Db/MailboxMapper.php
@@ -85,6 +85,34 @@ class MailboxMapper extends QBMapper {
}
/**
+ * @param int $id
+ * @param string $uid
+ *
+ * @return Mailbox
+ *
+ * @throws DoesNotExistException
+ * @throws ServiceException
+ */
+ public function findByUid(int $id, string $uid): Mailbox {
+ $qb = $this->db->getQueryBuilder();
+
+ $select = $qb->select('mb.*')
+ ->from($this->getTableName(), 'mb')
+ ->join('mb', 'mail_accounts', 'a', $qb->expr()->eq('mb.account_id', 'a.id', IQueryBuilder::PARAM_INT))
+ ->where(
+ $qb->expr()->eq('a.user_id', $qb->createNamedParameter($uid)),
+ $qb->expr()->eq('mb.id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT)
+ );
+
+ try {
+ return $this->findEntity($select);
+ } catch (MultipleObjectsReturnedException $e) {
+ // Not possible due to DB constraints
+ throw new ServiceException("The impossible has happened", 42, $e);
+ }
+ }
+
+ /**
* @throws DoesNotExistException
*/
public function findSpecial(Account $account, string $specialUse): Mailbox {
diff --git a/lib/Db/Message.php b/lib/Db/Message.php
index 8f028a284..95248b132 100644
--- a/lib/Db/Message.php
+++ b/lib/Db/Message.php
@@ -126,6 +126,7 @@ class Message extends Entity implements JsonSerializable {
$this->bcc = new AddressList([]);
$this->addType('uid', 'integer');
+ $this->addType('mailboxId', 'integer');
$this->addType('sentAt', 'integer');
$this->addType('flagAnswered', 'bool');
$this->addType('flagDeleted', 'bool');
@@ -252,6 +253,7 @@ class Message extends Entity implements JsonSerializable {
'to' => $this->getTo()->jsonSerialize(),
'cc' => $this->getCc()->jsonSerialize(),
'bcc' => $this->getBcc()->jsonSerialize(),
+ 'mailboxId' => $this->getMailboxId(),
];
}
}
diff --git a/lib/Db/MessageMapper.php b/lib/Db/MessageMapper.php
index e6593bb8c..77d0564ed 100644
--- a/lib/Db/MessageMapper.php
+++ b/lib/Db/MessageMapper.php
@@ -31,6 +31,7 @@ use OCA\Mail\Address;
use OCA\Mail\AddressList;
use OCA\Mail\IMAP\Threading\DatabaseMessage;
use OCA\Mail\Service\Search\SearchQuery;
+use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\QBMapper;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\DB\QueryBuilder\IQueryBuilder;
@@ -51,6 +52,11 @@ class MessageMapper extends QBMapper {
$this->timeFactory = $timeFactory;
}
+ /**
+ * @param IQueryBuilder $query
+ *
+ * @return int[]
+ */
private function findUids(IQueryBuilder $query): array {
$result = $query->execute();
$uids = array_map(function (array $row) {
@@ -61,6 +67,21 @@ class MessageMapper extends QBMapper {
return $uids;
}
+ /**
+ * @param IQueryBuilder $query
+ *
+ * @return int[]
+ */
+ private function findIds(IQueryBuilder $query): array {
+ $result = $query->execute();
+ $uids = array_map(function (array $row) {
+ return (int)$row['id'];
+ }, $result->fetchAll());
+ $result->closeCursor();
+
+ return $uids;
+ }
+
public function findHighestUid(Mailbox $mailbox): ?int {
$query = $this->db->getQueryBuilder();
@@ -78,12 +99,64 @@ class MessageMapper extends QBMapper {
return $max;
}
+ public function findByUserId(string $uid, int $id): Message {
+ $query = $this->db->getQueryBuilder();
+
+ $query->select('m.*')
+ ->from($this->getTableName(), 'm')
+ ->join('m', 'mail_mailboxes', 'mb', $query->expr()->eq('m.mailbox_id', 'mb.id', IQueryBuilder::PARAM_INT))
+ ->join('m', 'mail_accounts', 'a', $query->expr()->eq('mb.account_id', 'a.id', IQueryBuilder::PARAM_INT))
+ ->where(
+ $query->expr()->eq('a.user_id', $query->createNamedParameter($uid)),
+ $query->expr()->eq('m.id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT)
+ );
+
+ $results = $this->findRecipients($this->findEntities($query));
+ if (empty($results)) {
+ throw new DoesNotExistException("Message $id does not exist");
+ }
+ return $results[0];
+ }
+
public function findAllUids(Mailbox $mailbox): array {
$query = $this->db->getQueryBuilder();
$query->select('uid')
->from($this->getTableName())
- ->where($query->expr()->eq('mailbox_id', $query->createNamedParameter($mailbox->getId())));
+ ->where($query->expr()->eq('mailbox_id', $query->createNamedParameter($mailbox->getId(), IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT));
+
+ return $this->findUids($query);
+ }
+
+ public function findAllIds(Mailbox $mailbox): array {
+ $query = $this->db->getQueryBuilder();
+
+ $query->select('id')
+ ->from($this->getTableName())
+ ->where($query->expr()->eq('mailbox_id', $query->createNamedParameter($mailbox->getId(), IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT));
+
+ return $this->findIds($query);
+ }
+
+ /**
+ * @param Mailbox $mailbox
+ * @param int[] $ids
+ *
+ * @return int[]
+ */
+ public function findUidsForIds(Mailbox $mailbox, array $ids) {
+ if (empty($ids)) {
+ // Shortcut for empty sets
+ return [];
+ }
+
+ $query = $this->db->getQueryBuilder();
+ $query->select('uid')
+ ->from($this->getTableName())
+ ->where(
+ $query->expr()->eq('mailbox_id', $query->createNamedParameter($mailbox->getId(), IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT),
+ $query->expr()->in('id', $query->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY), IQueryBuilder::PARAM_INT_ARRAY)
+ );
return $this->findUids($query);
}
@@ -382,11 +455,11 @@ class MessageMapper extends QBMapper {
*
* @return int[]
*/
- public function findUidsByQuery(Mailbox $mailbox, SearchQuery $query, ?int $limit, array $uids = null): array {
+ public function findIdsByQuery(Mailbox $mailbox, SearchQuery $query, ?int $limit, array $uids = null): array {
$qb = $this->db->getQueryBuilder();
$select = $qb
- ->selectDistinct('m.uid')
+ ->selectDistinct('m.id')
->addSelect('m.sent_at')
->from($this->getTableName(), 'm');
@@ -477,7 +550,7 @@ class MessageMapper extends QBMapper {
}
return array_map(function (Message $message) {
- return $message->getUid();
+ return $message->getId();
}, $this->findEntities($select));
}
@@ -503,6 +576,28 @@ class MessageMapper extends QBMapper {
}
/**
+ * @param int[] $ids
+ *
+ * @return Message[]
+ */
+ public function findByIds(array $ids): array {
+ if (empty($ids)) {
+ return [];
+ }
+ $qb = $this->db->getQueryBuilder();
+
+ $select = $qb
+ ->select('*')
+ ->from($this->getTableName())
+ ->where(
+ $qb->expr()->in('id', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY), IQueryBuilder::PARAM_INT_ARRAY)
+ )
+ ->orderBy('sent_at', 'desc');
+
+ return $this->findRecipients($this->findEntities($select));
+ }
+
+ /**
* @param Message[] $messages
*
* @return Message[]
@@ -558,18 +653,26 @@ class MessageMapper extends QBMapper {
*
* @return Message[]
*/
- public function findNewUids(Mailbox $mailbox, int $highest): array {
+ public function findNewIds(Mailbox $mailbox, array $ids): array {
$qb = $this->db->getQueryBuilder();
+ $sub = $this->db->getQueryBuilder();
+ $subSelect = $sub
+ ->select($sub->func()->max('uid'))
+ ->from($this->getTableName())
+ ->where(
+ $sub->expr()->eq('mailbox_id', $qb->createNamedParameter($mailbox->getId(), IQueryBuilder::PARAM_INT)),
+ $sub->expr()->in('id', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY), IQueryBuilder::PARAM_INT_ARRAY)
+ );
$select = $qb
- ->select('uid')
+ ->select('id')
->from($this->getTableName())
->where(
$qb->expr()->eq('mailbox_id', $qb->createNamedParameter($mailbox->getId(), IQueryBuilder::PARAM_INT)),
- $qb->expr()->gt('uid', $qb->createNamedParameter($highest, IQueryBuilder::PARAM_INT))
+ $qb->expr()->gt('uid', $qb->createFunction('(' . $subSelect->getSQL() . ')'), IQueryBuilder::PARAM_INT)
);
- return $this->findUids($select);
+ return $this->findIds($select);
}
public function findChanged(Mailbox $mailbox, int $since): array {
@@ -644,4 +747,22 @@ class MessageMapper extends QBMapper {
->where($qb4->expr()->in('id', $qb4->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY), IQueryBuilder::PARAM_INT_ARRAY));
$recipientsQuery->execute();
}
+
+ public function getIdForUid(Mailbox $mailbox, $uid): ?int {
+ $qb = $this->db->getQueryBuilder();
+
+ $select = $qb
+ ->select('m.id')
+ ->from($this->getTableName(), 'm')
+ ->where(
+ $qb->expr()->eq('mailbox_id', $qb->createNamedParameter($mailbox->getId()), IQueryBuilder::PARAM_INT),
+ $qb->expr()->eq('uid', $qb->createNamedParameter($uid, IQueryBuilder::PARAM_INT), IQueryBuilder::PARAM_INT)
+ );
+ $result = $select->execute();
+ $rows = $result->fetchAll();
+ if (empty($rows)) {
+ return null;
+ }
+ return (int) $rows[0]['id'];
+ }
}
diff --git a/lib/Events/DraftSavedEvent.php b/lib/Events/DraftSavedEvent.php
index f8b6368da..677b4556c 100644
--- a/lib/Events/DraftSavedEvent.php
+++ b/lib/Events/DraftSavedEvent.php
@@ -26,6 +26,7 @@ declare(strict_types=1);
namespace OCA\Mail\Events;
use OCA\Mail\Account;
+use OCA\Mail\Db\Message;
use OCA\Mail\Model\NewMessageData;
use OCP\EventDispatcher\Event;
@@ -37,16 +38,16 @@ class DraftSavedEvent extends Event {
/** @var NewMessageData */
private $newMessageData;
- /** @var int|null */
- private $draftUid;
+ /** @var Message|null */
+ private $draft;
public function __construct(Account $account,
NewMessageData $newMessageData,
- ?int $draftUid) {
+ ?Message $draft) {
parent::__construct();
$this->account = $account;
$this->newMessageData = $newMessageData;
- $this->draftUid = $draftUid;
+ $this->draft = $draft;
}
public function getAccount(): Account {
@@ -57,7 +58,7 @@ class DraftSavedEvent extends Event {
return $this->newMessageData;
}
- public function getDraftUid(): ?int {
- return $this->draftUid;
+ public function getDraft(): ?Message {
+ return $this->draft;
}
}
diff --git a/lib/Events/MessageSentEvent.php b/lib/Events/MessageSentEvent.php
index 563467c4c..a2973cb8c 100644
--- a/lib/Events/MessageSentEvent.php
+++ b/lib/Events/MessageSentEvent.php
@@ -27,6 +27,7 @@ namespace OCA\Mail\Events;
use Horde_Mime_Mail;
use OCA\Mail\Account;
+use OCA\Mail\Db\Message;
use OCA\Mail\Model\IMessage;
use OCA\Mail\Model\NewMessageData;
use OCA\Mail\Model\RepliedMessageData;
@@ -43,8 +44,8 @@ class MessageSentEvent extends Event {
/** @var null|RepliedMessageData */
private $repliedMessageData;
- /** @var int|null */
- private $draftUid;
+ /** @var Message|null */
+ private $draft;
/** @var IMessage */
private $message;
@@ -55,14 +56,14 @@ class MessageSentEvent extends Event {
public function __construct(Account $account,
NewMessageData $newMessageData,
?RepliedMessageData $repliedMessageData,
- ?int $draftUid,
+ ?Message $draft,
IMessage $message,
Horde_Mime_Mail $mail) {
parent::__construct();
$this->account = $account;
$this->newMessageData = $newMessageData;
$this->repliedMessageData = $repliedMessageData;
- $this->draftUid = $draftUid;
+ $this->draft = $draft;
$this->message = $message;
$this->mail = $mail;
}
@@ -79,8 +80,8 @@ class MessageSentEvent extends Event {
return $this->repliedMessageData;
}
- public function getDraftUid(): ?int {
- return $this->draftUid;
+ public function getDraft(): ?Message {
+ return $this->draft;
}
public function getMessage(): IMessage {
diff --git a/lib/Events/SaveDraftEvent.php b/lib/Events/SaveDraftEvent.php
index 1f5590281..830bfe976 100644
--- a/lib/Events/SaveDraftEvent.php
+++ b/lib/Events/SaveDraftEvent.php
@@ -26,6 +26,7 @@ declare(strict_types=1);
namespace OCA\Mail\Events;
use OCA\Mail\Account;
+use OCA\Mail\Db\Message;
use OCA\Mail\Model\NewMessageData;
use OCP\EventDispatcher\Event;
@@ -37,16 +38,16 @@ class SaveDraftEvent extends Event {
/** @var NewMessageData */
private $newMessageData;
- /** @var int|null */
- private $draftUid;
+ /** @var Message|null */
+ private $draft;
public function __construct(Account $account,
NewMessageData $newMessageData,
- ?int $draftUid) {
+ ?Message $draft) {
parent::__construct();
$this->account = $account;
$this->newMessageData = $newMessageData;
- $this->draftUid = $draftUid;
+ $this->draft = $draft;
}
public function getAccount(): Account {
@@ -57,7 +58,7 @@ class SaveDraftEvent extends Event {
return $this->newMessageData;
}
- public function getDraftUid(): ?int {
- return $this->draftUid;
+ public function getDraft(): ?Message {
+ return $this->draft;
}
}
diff --git a/lib/IMAP/MessageMapper.php b/lib/IMAP/MessageMapper.php
index 2d0f3cee8..3b4fde341 100644
--- a/lib/IMAP/MessageMapper.php
+++ b/lib/IMAP/MessageMapper.php
@@ -364,14 +364,14 @@ class MessageMapper {
/**
* @param Horde_Imap_Client_Socket $client
* @param string $mailbox
- * @param int $id
+ * @param int $uid
*
* @return string|null
* @throws ServiceException
*/
public function getSource(Horde_Imap_Client_Socket $client,
string $mailbox,
- int $id): ?string {
+ int $uid): ?string {
$query = new Horde_Imap_Client_Fetch_Query();
$query->uid();
$query->fullText([
@@ -380,7 +380,7 @@ class MessageMapper {
try {
$result = iterator_to_array($client->fetch($mailbox, $query, [
- 'ids' => new Horde_Imap_Client_Ids($id),
+ 'ids' => new Horde_Imap_Client_Ids($uid),
]), false);
} catch (Horde_Imap_Client_Exception $e) {
throw new ServiceException("Could not fetch message source: " . $e->getMessage(), $e->getCode(), $e);
@@ -399,13 +399,13 @@ class MessageMapper {
public function getHtmlBody(Horde_Imap_Client_Socket $client,
string $mailbox,
- int $id): ?string {
+ int $uid): ?string {
$messageQuery = new Horde_Imap_Client_Fetch_Query();
$messageQuery->envelope();
$messageQuery->structure();
$result = $client->fetch($mailbox, $messageQuery, [
- 'ids' => new Horde_Imap_Client_Ids([$id]),
+ 'ids' => new Horde_Imap_Client_Ids([$uid]),
]);
if (($message = $result->first()) === null) {
@@ -435,7 +435,7 @@ class MessageMapper {
}
$parts = $client->fetch($mailbox, $partsQuery, [
- 'ids' => new Horde_Imap_Client_Ids([$id]),
+ 'ids' => new Horde_Imap_Client_Ids([$uid]),
]);
foreach ($parts as $part) {
@@ -456,12 +456,12 @@ class MessageMapper {
public function getRawAttachments(Horde_Imap_Client_Socket $client,
string $mailbox,
- int $id): array {
+ int $uid): array {
$messageQuery = new Horde_Imap_Client_Fetch_Query();
$messageQuery->structure();
$result = $client->fetch($mailbox, $messageQuery, [
- 'ids' => new Horde_Imap_Client_Ids([$id]),
+ 'ids' => new Horde_Imap_Client_Ids([$uid]),
]);
if (($structureResult = $result->first()) === null) {
@@ -488,7 +488,7 @@ class MessageMapper {
}
$parts = $client->fetch($mailbox, $partsQuery, [
- 'ids' => new Horde_Imap_Client_Ids([$id]),
+ 'ids' => new Horde_Imap_Client_Ids([$uid]),
]);
if (($messageData = $parts->first()) === null) {
throw new DoesNotExistException('Message does not exist');
diff --git a/lib/IMAP/Sync/Response.php b/lib/IMAP/Sync/Response.php
index 9e95b342e..d12625775 100644
--- a/lib/IMAP/Sync/Response.php
+++ b/lib/IMAP/Sync/Response.php
@@ -24,14 +24,15 @@ declare(strict_types=1);
namespace OCA\Mail\IMAP\Sync;
use JsonSerializable;
+use OCA\Mail\Db\Message;
use OCA\Mail\Model\IMAPMessage;
class Response implements JsonSerializable {
- /** @var IMAPMessage[] */
+ /** @var IMAPMessage|Message[] */
private $newMessages;
- /** @var IMAPMessage[] */
+ /** @var IMAPMessage|Message[] */
private $changedMessages;
/** @var int[] */
@@ -39,8 +40,8 @@ class Response implements JsonSerializable {
/**
* @param string $syncToken
- * @param IMAPMessage[] $newMessages
- * @param IMAPMessage[] $changedMessages
+ * @param IMAPMessage|Message[] $newMessages
+ * @param IMAPMessage|Message[] $changedMessages
* @param int[] $vanishedMessageUids
*/
public function __construct(array $newMessages = [],
@@ -52,14 +53,14 @@ class Response implements JsonSerializable {
}
/**
- * @return IMAPMessage[]
+ * @return IMAPMessage|Message[]
*/
public function getNewMessages(): array {
return $this->newMessages;
}
/**
- * @return IMAPMessage[]
+ * @return IMAPMessage|Message[]
*/
public function getChangedMessages(): array {
return $this->changedMessages;
diff --git a/lib/IMAP/Threading/ThreadBuilder.php b/lib/IMAP/Threading/ThreadBuilder.php
index 72283423f..8053d045d 100644
--- a/lib/IMAP/Threading/ThreadBuilder.php
+++ b/lib/IMAP/Threading/ThreadBuilder.php
@@ -110,6 +110,9 @@ class ThreadBuilder {
// Step 1.C
//$parentId = $message->getReferences()[count($message->getReferences()) - 1] ?? null;
//$container->setParent($idTable[$parentId] ?? null);
+ if ($parent === $container) {
+ throw new \Exception("about to run into a nasty endless loop");
+ }
if ($parent === null || !$parent->hasAncestor($container)) {
$container->setParent($parent);
}
diff --git a/lib/Listener/DeleteDraftListener.php b/lib/Listener/DeleteDraftListener.php
index 0e76adec6..9758a0fa0 100644
--- a/lib/Listener/DeleteDraftListener.php
+++ b/lib/Listener/DeleteDraftListener.php
@@ -30,6 +30,7 @@ use Horde_Imap_Client_Exception;
use OCA\Mail\Account;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\MailboxMapper;
+use OCA\Mail\Db\Message;
use OCA\Mail\Events\DraftSavedEvent;
use OCA\Mail\Events\MessageSentEvent;
use OCA\Mail\IMAP\IMAPClientFactory;
@@ -70,17 +71,18 @@ class DeleteDraftListener implements IEventListener {
}
public function handle(Event $event): void {
- if ($event instanceof DraftSavedEvent && $event->getDraftUid() !== null) {
- $this->deleteDraft($event->getAccount(), $event->getDraftUid());
- } elseif ($event instanceof MessageSentEvent && $event->getDraftUid() !== null) {
- $this->deleteDraft($event->getAccount(), $event->getDraftUid());
+ if ($event instanceof DraftSavedEvent && $event->getDraft() !== null) {
+ $this->deleteDraft($event->getAccount(), $event->getDraft());
+ } elseif ($event instanceof MessageSentEvent && $event->getDraft() !== null) {
+ $this->deleteDraft($event->getAccount(), $event->getDraft());
}
}
/**
- * @param DraftSavedEvent $event
+ * @param Account $account
+ * @param Message $draft
*/
- private function deleteDraft(Account $account, int $draftUid): void {
+ private function deleteDraft(Account $account, Message $draft): void {
$client = $this->imapClientFactory->getClient($account);
$draftsMailbox = $this->getDraftsMailbox($account);
@@ -88,7 +90,7 @@ class DeleteDraftListener implements IEventListener {
$this->messageMapper->addFlag(
$client,
$draftsMailbox,
- $draftUid,
+ $draft->getUid(), // TODO: the UID could be from another mailbox
Horde_Imap_Client::FLAG_DELETED
);
} catch (Horde_Imap_Client_Exception $e) {
diff --git a/lib/Mailbox.php b/lib/Mailbox.php
index 09daef680..5aecf8330 100644
--- a/lib/Mailbox.php
+++ b/lib/Mailbox.php
@@ -295,12 +295,13 @@ class Mailbox implements IMailBox {
}
/**
- * @param int $messageId
+ * @param int $messageUid
* @param string $attachmentId
+ *
* @return Attachment
*/
- public function getAttachment(int $messageId, string $attachmentId): Attachment {
- return new Attachment($this->conn, $this->mailBox, $messageId, $attachmentId);
+ public function getAttachment(int $messageUid, string $attachmentId): Attachment {
+ return new Attachment($this->conn, $this->mailBox, $messageUid, $attachmentId);
}
/**
diff --git a/lib/Model/IMAPMessage.php b/lib/Model/IMAPMessage.php
index 1dae7a1d0..8b7ae12a3 100644
--- a/lib/Model/IMAPMessage.php
+++ b/lib/Model/IMAPMessage.php
@@ -48,7 +48,6 @@ use OCA\Mail\Service\Html;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\Files\File;
use OCP\Files\SimpleFS\ISimpleFile;
-use function base64_encode;
use function in_array;
use function mb_convert_encoding;
@@ -422,15 +421,17 @@ class IMAPMessage implements IMessage, JsonSerializable {
}
/**
+ * @param int $id
+ *
* @return array
*/
- public function getFullMessage(int $accountId, string $mailbox, int $id): array {
+ public function getFullMessage(int $id): array {
$mailBody = $this->plainMessage;
$data = $this->jsonSerialize();
if ($this->hasHtmlMessage) {
$data['hasHtmlBody'] = true;
- $data['body'] = $this->getHtmlBody($accountId, $mailbox, $id);
+ $data['body'] = $this->getHtmlBody($id);
} else {
$mailBody = $this->htmlService->convertLinks($mailBody);
list($mailBody, $signature) = $this->htmlService->parseMailBody($mailBody);
@@ -462,17 +463,13 @@ class IMAPMessage implements IMessage, JsonSerializable {
}
/**
- * @param int $accountId
- * @param string $folderId
- * @param int $messageId
+ * @param int $id
*
* @return string
*/
- public function getHtmlBody(int $accountId, string $folderId, int $messageId): string {
+ public function getHtmlBody(int $id): string {
return $this->htmlService->sanitizeHtmlMailBody($this->htmlMessage, [
- 'accountId' => $accountId,
- 'folderId' => base64_encode($folderId),
- 'messageId' => $messageId,
+ 'id' => $id,
], function ($cid) {
$match = array_filter($this->attachments,
function ($a) use ($cid) {
diff --git a/lib/Service/AccountService.php b/lib/Service/AccountService.php
index 83a4a6977..36fbf11a1 100644
--- a/lib/Service/AccountService.php
+++ b/lib/Service/AccountService.php
@@ -89,25 +89,25 @@ class AccountService {
/**
* @param string $uid
- * @param int $accountId
+ * @param int $id
*
* @return Account
* @throws ClientException
*/
- public function find(string $uid, int $accountId): Account {
+ public function find(string $uid, int $id): Account {
if ($this->accounts !== null) {
foreach ($this->accounts as $account) {
- if ($account->getId() === $accountId) {
+ if ($account->getId() === $id) {
return $account;
}
}
- throw new ClientException("Account $accountId does not exist or you don\'t have permission to access it");
+ throw new ClientException("Account $id does not exist or you don\'t have permission to access it");
}
try {
- return new Account($this->mapper->find($uid, $accountId));
+ return new Account($this->mapper->find($uid, $id));
} catch (DoesNotExistException $e) {
- throw new ClientException("Account $accountId does not exist or you don\'t have permission to access it");
+ throw new ClientException("Account $id does not exist or you don\'t have permission to access it");
}
}
diff --git a/lib/Service/IMailBox.php b/lib/Service/IMailBox.php
index 093e3d7f1..d75c5c562 100644
--- a/lib/Service/IMailBox.php
+++ b/lib/Service/IMailBox.php
@@ -47,11 +47,12 @@ interface IMailBox {
public function getMessage(int $id, bool $loadHtmlMessageBody = false);
/**
- * @param int $messageId
+ * @param int $messageUid
* @param string $attachmentId
+ *
* @return Attachment
*/
- public function getAttachment(int $messageId, string $attachmentId): Attachment;
+ public function getAttachment(int $messageUid, string $attachmentId): Attachment;
/**
* @param int $flags
diff --git a/lib/Service/MailManager.php b/lib/Service/MailManager.php
index 08cceb812..09d04dcc3 100644
--- a/lib/Service/MailManager.php
+++ b/lib/Service/MailManager.php
@@ -30,6 +30,7 @@ use OCA\Mail\Account;
use OCA\Mail\Contracts\IMailManager;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\MailboxMapper;
+use OCA\Mail\Db\Message;
use OCA\Mail\Db\MessageMapper as DbMessageMapper;
use OCA\Mail\Events\BeforeMessageDeletedEvent;
use OCA\Mail\Events\MessageDeletedEvent;
@@ -100,6 +101,14 @@ class MailManager implements IMailManager {
$this->eventDispatcher = $eventDispatcher;
}
+ public function getMailbox(string $uid, int $id): Mailbox {
+ try {
+ return $this->mailboxMapper->findByUid($id, $uid);
+ } catch (DoesNotExistException $e) {
+ throw new ClientException("Mailbox $id does not exist", 0, $e);
+ }
+ }
+
/**
* @param Account $account
*
@@ -116,10 +125,10 @@ class MailManager implements IMailManager {
* @param Account $account
* @param string $name
*
- * @return Folder
+ * @return Mailbox
* @throws ServiceException
*/
- public function createFolder(Account $account, string $name): Folder {
+ public function createMailbox(Account $account, string $name): Mailbox {
$client = $this->imapClientFactory->getClient($account);
$folder = $this->folderMapper->createFolder($client, $account, $name);
@@ -132,30 +141,33 @@ class MailManager implements IMailManager {
$this->mailboxSync->sync($account, true);
- return $folder;
+ return $this->mailboxMapper->find($account, $name);
}
/**
* @param Account $account
- * @param string $folderId
+ * @param Mailbox $mailbox
*
* @return FolderStats
+ * @throws Horde_Imap_Client_Exception
*/
- public function getFolderStats(Account $account, string $folderId): FolderStats {
+ public function getMailboxStats(Account $account, Mailbox $mailbox): FolderStats {
$client = $this->imapClientFactory->getClient($account);
- return $this->folderMapper->getFoldersStatusAsObject($client, $folderId);
+ return $this->folderMapper->getFoldersStatusAsObject($client, $mailbox->getName());
}
- public function getMessage(Account $account, string $mailbox, int $id, bool $loadBody = false): IMAPMessage {
+ public function getImapMessage(Account $account,
+ Mailbox $mailbox,
+ int $uid,
+ bool $loadBody = false): IMAPMessage {
$client = $this->imapClientFactory->getClient($account);
- $mailbox = $this->mailboxMapper->find($account, $mailbox);
try {
return $this->imapMessageMapper->find(
$client,
$mailbox->getName(),
- $id,
+ $uid,
$loadBody
);
} catch (Horde_Imap_Client_Exception|DoesNotExistException $e) {
@@ -167,24 +179,32 @@ class MailManager implements IMailManager {
return $this->dbMessageMapper->findThread($account, $messageId);
}
+ public function getMessageIdForUid(Mailbox $mailbox, $uid): ?int {
+ return $this->dbMessageMapper->getIdForUid($mailbox, $uid);
+ }
+
+ public function getMessage(string $uid, int $id): Message {
+ return $this->dbMessageMapper->findByUserId($uid, $id);
+ }
+
/**
* @param Account $account
* @param string $mb
- * @param int $id
+ * @param int $uid
*
* @return string
*
* @throws ClientException
* @throws ServiceException
*/
- public function getSource(Account $account, string $mailbox, int $id): string {
+ public function getSource(Account $account, string $mailbox, int $uid): ?string {
$client = $this->imapClientFactory->getClient($account);
try {
return $this->imapMessageMapper->getSource(
$client,
$mailbox,
- $id
+ $uid
);
} catch (Horde_Imap_Client_Exception|DoesNotExistException $e) {
throw new ServiceException("Could not load message", 0, $e);
@@ -194,7 +214,7 @@ class MailManager implements IMailManager {
/**
* @param Account $sourceAccount
* @param string $sourceFolderId
- * @param int $messageId
+ * @param int $uid
* @param Account $destinationAccount
* @param string $destFolderId
*
@@ -204,7 +224,7 @@ class MailManager implements IMailManager {
*/
public function moveMessage(Account $sourceAccount,
string $sourceFolderId,
- int $messageId,
+ int $uid,
Account $destinationAccount,
string $destFolderId) {
if ($sourceAccount->getId() === $destinationAccount->getId()) {
@@ -212,7 +232,7 @@ class MailManager implements IMailManager {
$sourceAccount,
$sourceFolderId,
$destFolderId,
- $messageId
+ $uid
);
} else {
throw new ServiceException('It is not possible to move across accounts yet');
@@ -284,10 +304,10 @@ class MailManager implements IMailManager {
$this->imapMessageMapper->move($client, $sourceFolderId, $messageId, $destFolderId);
}
- public function markFolderAsRead(Account $account, string $folderId): void {
+ public function markFolderAsRead(Account $account, Mailbox $mailbox): void {
$client = $this->imapClientFactory->getClient($account);
- $this->imapMessageMapper->markAllRead($client, $folderId);
+ $this->imapMessageMapper->markAllRead($client, $mailbox->getName());
}
public function flagMessage(Account $account, string $mailbox, int $uid, string $flag, bool $value): void {
@@ -371,18 +391,14 @@ class MailManager implements IMailManager {
/**
* @param Account $account
- * @param string $folderId
+ * @param Mailbox $mailbox
+ *
* @throws ServiceException
*/
public function deleteMailbox(Account $account,
- string $folderId): void {
- try {
- $mailbox = $this->mailboxMapper->find($account, $folderId);
- } catch (DoesNotExistException $e) {
- throw new ServiceException("Source mailbox $folderId does not exist", 0, $e);
- }
+ Mailbox $mailbox): void {
$client = $this->imapClientFactory->getClient($account);
- $this->folderMapper->delete($client, $folderId);
+ $this->folderMapper->delete($client, $mailbox->getName());
$this->mailboxMapper->delete($mailbox);
}
}
diff --git a/lib/Service/MailTransmission.php b/lib/Service/MailTransmission.php
index 9db9c1d4a..e8ff9d135 100644
--- a/lib/Service/MailTransmission.php
+++ b/lib/Service/MailTransmission.php
@@ -39,6 +39,7 @@ use OCA\Mail\Contracts\IAttachmentService;
use OCA\Mail\Contracts\IMailTransmission;
use OCA\Mail\Db\Alias;
use OCA\Mail\Db\MailboxMapper;
+use OCA\Mail\Db\Message;
use OCA\Mail\Events\DraftSavedEvent;
use OCA\Mail\Events\MessageSentEvent;
use OCA\Mail\Events\SaveDraftEvent;
@@ -102,22 +103,10 @@ class MailTransmission implements IMailTransmission {
$this->logger = $logger;
}
- /**
- * Send a new message or reply to an existing one
- *
- * @param NewMessageData $messageData
- * @param RepliedMessageData $replyData
- * @param Alias|null $alias
- * @param int|null $draftUID
- *
- * @throws ServiceException
- *
- * @return void
- */
public function sendMessage(NewMessageData $messageData,
RepliedMessageData $replyData = null,
Alias $alias = null,
- int $draftUID = null) {
+ Message $draft = null) {
$account = $messageData->getAccount();
if ($replyData !== null) {
@@ -178,17 +167,22 @@ class MailTransmission implements IMailTransmission {
$this->eventDispatcher->dispatch(
MessageSentEvent::class,
- new MessageSentEvent($account, $messageData, $replyData, $draftUID, $message, $mail)
+ new MessageSentEvent($account, $messageData, $replyData, $draft, $message, $mail)
);
}
/**
+ * @param NewMessageData $message
+ * @param Message|null $previousDraft
+ *
+ * @return array
+ *
* @throws ServiceException
*/
- public function saveDraft(NewMessageData $message, int $draftUID = null): int {
+ public function saveDraft(NewMessageData $message, Message $previousDraft = null): array {
$this->eventDispatcher->dispatch(
SaveDraftEvent::class,
- new SaveDraftEvent($message->getAccount(), $message, $draftUID)
+ new SaveDraftEvent($message->getAccount(), $message, $previousDraft)
);
$account = $message->getAccount();
@@ -243,10 +237,10 @@ class MailTransmission implements IMailTransmission {
$this->eventDispatcher->dispatch(
DraftSavedEvent::class,
- new DraftSavedEvent($account, $message, $draftUID)
+ new DraftSavedEvent($account, $message, $previousDraft)
);
- return $newUid;
+ return [$account, $draftsMailbox, $newUid];
}
private function buildReplyMessage(Account $account,
diff --git a/lib/Service/Search/MailSearch.php b/lib/Service/Search/MailSearch.php
index cead97321..85b021704 100644
--- a/lib/Service/Search/MailSearch.php
+++ b/lib/Service/Search/MailSearch.php
@@ -75,32 +75,26 @@ class MailSearch implements IMailSearch {
$this->logger = $logger;
}
- public function findMessage(Account $account, string $mailboxName, int $uid): Message {
- try {
- $mailbox = $this->mailboxMapper->find($account, $mailboxName);
- } catch (DoesNotExistException $e) {
- throw new ServiceException('Mailbox does not exist', 0, $e);
- }
-
- $messages = $this->previewEnhancer->process(
+ public function findMessage(Account $account,
+ Mailbox $mailbox,
+ Message $message): Message {
+ $processed = $this->previewEnhancer->process(
$account,
$mailbox,
- $this->messageMapper->findByUids(
- $mailbox,
- [$uid]
- )
+ [$message]
);
- if (empty($messages)) {
+ if (empty($processed)) {
throw new DoesNotExistException("Message does not exist");
}
- return $messages[0];
+ return $processed[0];
}
/**
* @param Account $account
- * @param string $mailboxName
+ * @param Mailbox $mailbox
* @param string|null $filter
* @param int|null $cursor
+ * @param int|null $limit
*
* @return Message[]
*
@@ -108,16 +102,10 @@ class MailSearch implements IMailSearch {
* @throws ServiceException
*/
public function findMessages(Account $account,
- string $mailboxName,
+ Mailbox $mailbox,
?string $filter,
?int $cursor,
?int $limit): array {
- try {
- $mailbox = $this->mailboxMapper->find($account, $mailboxName);
- } catch (DoesNotExistException $e) {
- throw new ServiceException('Mailbox does not exist', 0, $e);
- }
-
if ($mailbox->hasLocks()) {
throw MailboxLockedException::from($mailbox);
}
@@ -141,9 +129,8 @@ class MailSearch implements IMailSearch {
return $this->previewEnhancer->process(
$account,
$mailbox,
- $this->messageMapper->findByUids(
- $mailbox,
- $this->getUids($account, $mailbox, $query, $limit)
+ $this->messageMapper->findByIds(
+ $this->getIds($account, $mailbox, $query, $limit)
)
);
}
@@ -153,9 +140,9 @@ class MailSearch implements IMailSearch {
*
* @throws ServiceException
*/
- private function getUids(Account $account, Mailbox $mailbox, SearchQuery $query, ?int $limit): array {
+ private function getIds(Account $account, Mailbox $mailbox, SearchQuery $query, ?int $limit): array {
if (empty($query->getTextTokens())) {
- return $this->messageMapper->findUidsByQuery($mailbox, $query, $limit);
+ return $this->messageMapper->findIdsByQuery($mailbox, $query, $limit);
}
$fromImap = $this->imapSearchProvider->findMatches(
@@ -163,6 +150,6 @@ class MailSearch implements IMailSearch {
$mailbox,
$query
);
- return $this->messageMapper->findUidsByQuery($mailbox, $query, $limit, $fromImap);
+ return $this->messageMapper->findIdsByQuery($mailbox, $query, $limit, $fromImap);
}
}
diff --git a/lib/Service/Sync/SyncService.php b/lib/Service/Sync/SyncService.php
index 484ce597b..385a66b84 100644
--- a/lib/Service/Sync/SyncService.php
+++ b/lib/Service/Sync/SyncService.php
@@ -38,10 +38,8 @@ use OCA\Mail\IMAP\PreviewEnhancer;
use OCA\Mail\IMAP\Sync\Response;
use OCA\Mail\Service\Search\FilterStringParser;
use OCA\Mail\Service\Search\SearchQuery;
-use OCP\AppFramework\Db\DoesNotExistException;
use function array_diff;
use function array_map;
-use function end;
class SyncService {
@@ -74,46 +72,36 @@ class SyncService {
/**
* @param Account $account
- * @param string $mailboxId
+ * @param Mailbox $mailbox
*
* @throws MailboxLockedException
* @throws ServiceException
*/
public function clearCache(Account $account,
- string $mailboxId): void {
- try {
- $mailbox = $this->mailboxMapper->find($account, $mailboxId);
- } catch (DoesNotExistException $e) {
- throw new ServiceException('Mailbox to sync does not exist in the database', 0, $e);
- }
-
+ Mailbox $mailbox): void {
$this->synchronizer->clearCache($account, $mailbox);
}
/**
* @param Account $account
- * @param string $mailboxId
+ * @param Mailbox $mailbox
* @param int $criteria
- * @param array $knownUids
+ * @param int[] $knownIds
* @param bool $partialOnly
*
+ * @param string|null $filter
+ *
* @return Response
* @throws ClientException
* @throws MailboxNotCachedException
* @throws ServiceException
*/
public function syncMailbox(Account $account,
- string $mailboxId,
+ Mailbox $mailbox,
int $criteria,
- array $knownUids,
+ array $knownIds,
bool $partialOnly,
string $filter = null): Response {
- try {
- $mailbox = $this->mailboxMapper->find($account, $mailboxId);
- } catch (DoesNotExistException $e) {
- throw new ServiceException('Mailbox to sync does not exist in the database', 0, $e);
- }
-
if ($partialOnly && !$mailbox->isCached()) {
throw MailboxNotCachedException::from($mailbox);
}
@@ -122,52 +110,57 @@ class SyncService {
$account,
$mailbox,
$criteria,
- $knownUids,
+ $this->messageMapper->findUidsForIds($mailbox, $knownIds),
!$partialOnly
);
$query = $filter === null ? null : $this->filterStringParser->parse($filter);
-
- return $this->getDatabaseSyncChanges($account, $mailbox, $knownUids, $query);
+ return $this->getDatabaseSyncChanges(
+ $account,
+ $mailbox,
+ $knownIds,
+ $query
+ );
}
/**
* @param Account $account
* @param Mailbox $mailbox
- * @param array $knownUids
+ * @param int[] $knownIds
* @param SearchQuery $query
*
* @return Response
* @todo does not work with text token search queries
*
*/
- private function getDatabaseSyncChanges(Account $account, Mailbox $mailbox, array $knownUids, ?SearchQuery $query): Response {
- if (empty($knownUids)) {
- $newUids = $this->messageMapper->findAllUids($mailbox);
+ private function getDatabaseSyncChanges(Account $account,
+ Mailbox $mailbox,
+ array $knownIds,
+ ?SearchQuery $query): Response {
+ if (empty($knownIds)) {
+ $newIds = $this->messageMapper->findAllIds($mailbox);
} else {
- sort($knownUids, SORT_NUMERIC);
- $last = end($knownUids);
- $newUids = $this->messageMapper->findNewUids($mailbox, $last);
+ $newIds = $this->messageMapper->findNewIds($mailbox, $knownIds);
}
if ($query !== null) {
// Filter new messages to those that also match the current filter
- $newUids = $this->messageMapper->findUidsByQuery($mailbox, $query, null, $newUids);
+ $newIds = $this->messageMapper->findIdsByQuery($mailbox, $query, null, $newIds);
}
- $new = $this->messageMapper->findByUids($mailbox, $newUids);
+ $new = $this->messageMapper->findByIds($newIds);
// TODO: $changed = $this->messageMapper->findChanged($mailbox, $uids);
if ($query !== null) {
- $changedUids = $this->messageMapper->findUidsByQuery($mailbox, $query, null, $knownUids);
+ $changedIds = $this->messageMapper->findIdsByQuery($mailbox, $query, null, $knownIds);
} else {
- $changedUids = $knownUids;
+ $changedIds = $knownIds;
}
- $changed = $this->messageMapper->findByUids($mailbox, $changedUids);
+ $changed = $this->messageMapper->findByIds($changedIds);
- $stillKnownUids = array_map(static function (Message $msg) {
- return $msg->getUid();
+ $stillKnownIds = array_map(static function (Message $msg) {
+ return $msg->getId();
}, $changed);
- $vanished = array_values(array_diff($knownUids, $stillKnownUids));
+ $vanished = array_values(array_diff($knownIds, $stillKnownIds));
return new Response(
$this->previewEnhancer->process($account, $mailbox, $new),
diff --git a/package-lock.json b/package-lock.json
index 2aeec20c3..8c996d577 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4687,7 +4687,7 @@
},
"domelementtype": {
"version": "1.3.1",
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+ "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
"integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
},
"domexception": {
diff --git a/src/components/Address.vue b/src/components/Address.vue
index 092d272a0..0840480b4 100644
--- a/src/components/Address.vue
+++ b/src/components/Address.vue
@@ -28,9 +28,8 @@ export default {
return {
name: 'message',
params: {
- accountId: this.$route.params.accountId,
- folderId: this.$route.params.folderId,
- messageUuid: 'new',
+ mailboxId: this.$route.params.mailboxId,
+ threadId: 'new',
},
query: {
to: this.email,
diff --git a/src/components/Composer.vue b/src/components/Composer.vue
index bcc4c43a6..7eda5beff 100644
--- a/src/components/Composer.vue
+++ b/src/components/Composer.vue
@@ -405,7 +405,7 @@ export default {
},
},
watch: {
- '$route.params.messageUuid'() {
+ '$route.params.threadId'() {
this.reset()
},
allRecipients() {
@@ -497,29 +497,28 @@ export default {
return `"${recipient.label}" <${recipient.email}>`
}
},
- getMessageData(uid) {
+ getMessageData(id) {
return {
account: this.selectedAlias.id,
aliasId: this.selectedAlias.aliasId,
to: this.selectTo.map(this.recipientToRfc822).join(', '),
cc: this.selectCc.map(this.recipientToRfc822).join(', '),
bcc: this.selectBcc.map(this.recipientToRfc822).join(', '),
- draftUID: uid,
+ draftId: id,
subject: this.subjectVal,
body: this.encrypt ? plain(this.bodyVal) : html(this.bodyVal),
attachments: this.attachments,
- folderId: this.replyTo ? this.replyTo.folderId : undefined,
- messageId: this.replyTo ? this.replyTo.uid : undefined,
+ messageId: this.replyTo ? this.replyTo.databaseId : undefined,
isHtml: !this.editorPlainText,
}
},
saveDraft(data) {
this.savingDraft = true
this.draftsPromise = this.draftsPromise
- .then((uid) => {
- const draftData = data(uid)
+ .then((id) => {
+ const draftData = data(id)
if (
- !uid
+ !id
&& !draftData.subject
&& !draftData.body
&& !draftData.cc
@@ -531,7 +530,7 @@ export default {
// and fires an input event
logger.debug('Nothing substantial to save, ignoring draft save')
this.savingDraft = false
- return uid
+ return id
}
return this.draft(draftData)
})
diff --git a/src/components/Envelope.vue b/src/components/Envelope.vue
index 46b911778..aad27d236 100644
--- a/src/components/Envelope.vue
+++ b/src/components/Envelope.vue
@@ -1,7 +1,7 @@
<template>
<router-link class="app-content-list-item" :class="{seen: data.flags.seen, draft, selected: selected}" :to="link">
<div
- v-if="folder.isUnified"
+ v-if="mailbox.isUnified"
class="mail-message-account-color"
:style="{'background-color': accountColor}" />
<div
@@ -99,7 +99,7 @@ export default {
type: Object,
required: true,
},
- folder: {
+ mailbox: {
type: Object,
required: true,
},
@@ -126,17 +126,16 @@ export default {
},
link() {
if (this.draft) {
- // TODO: does not work with a unified drafts folder
- // the query should also contain the account and folder
+ // TODO: does not work with a unified drafts mailbox
+ // the query should also contain the account and mailbox
// id for that to work
return {
name: 'message',
params: {
- accountId: this.$route.params.accountId,
- folderId: this.$route.params.folderId,
+ mailboxId: this.$route.params.mailboxId,
filter: this.$route.params.filter ? this.$route.params.filter : undefined,
- messageUuid: 'new',
- draftUid: this.data.uid,
+ threadId: 'new',
+ draftId: this.data.databaseId,
},
exact: true,
}
@@ -144,36 +143,35 @@ export default {
return {
name: 'message',
params: {
- accountId: this.$route.params.accountId,
- folderId: this.$route.params.folderId,
+ mailboxId: this.$route.params.mailboxId,
filter: this.$route.params.filter ? this.$route.params.filter : undefined,
- messageUuid: this.data.uuid,
+ threadId: this.data.databaseId,
},
exact: true,
}
}
},
addresses() {
- // Show recipients' label/address in a sent folder
- if (this.folder.specialRole === 'sent') {
+ // Show recipients' label/address in a sent mailbox
+ if (this.mailbox.specialRole === 'sent') {
const recipients = [this.data.to, this.data.cc].flat().map(function(recipient) {
return recipient.label ? recipient.label : recipient.email
})
return recipients.length > 0 ? recipients.join(', ') : t('mail', 'Blind copy recipients only')
}
- // Show sender label/address in other folder types
+ // Show sender label/address in other mailbox types
return this.data.from.length === 0 ? '?' : this.data.from[0].label || this.data.from[0].email
},
avatarEmail() {
- // Show first recipients' avatar in a sent folder (or undefined when sent to Bcc only)
- if (this.folder.specialRole === 'sent') {
+ // Show first recipients' avatar in a sent mailbox (or undefined when sent to Bcc only)
+ if (this.mailbox.specialRole === 'sent') {
const recipients = [this.data.to, this.data.cc].flat().map(function(recipient) {
return recipient.email
})
return recipients.length > 0 ? recipients[0] : undefined
}
- // Show sender avatar in other folder types
+ // Show sender avatar in other mailbox types
if (this.data.from.length > 0) {
return this.data.from[0].email
} else {
@@ -203,9 +201,7 @@ export default {
onDelete() {
this.$emit('delete')
this.$store.dispatch('deleteMessage', {
- accountId: this.data.accountId,
- folderId: this.data.folderId,
- uid: this.data.uid,
+ id: this.data.databaseId,
})
},
},
diff --git a/src/components/EnvelopeList.vue b/src/components/EnvelopeList.vue
index aa2d0d6b8..c790495f8 100644
--- a/src/components/EnvelopeList.vue
+++ b/src/components/EnvelopeList.vue
@@ -33,12 +33,12 @@
:class="{refreshing: refreshing}" />
<Envelope
v-for="env in envelopes"
- :key="env.uuid"
+ :key="env.databaseId"
:data="env"
- :folder="folder"
+ :mailbox="mailbox"
:selected="isEnvelopeSelected(envelopes.indexOf(env))"
:select-mode="selectMode"
- @delete="$emit('delete', env.uuid)"
+ @delete="$emit('delete', env.databaseId)"
@update:selected="onEnvelopeSelectToggle(env, ...$event)" />
<div
v-if="loadMoreButton && !loadingMore"
@@ -57,6 +57,7 @@ import Actions from '@nextcloud/vue/dist/Components/Actions'
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
import Envelope from './Envelope'
+import logger from '../logger'
export default {
name: 'EnvelopeList',
@@ -70,7 +71,7 @@ export default {
type: Object,
required: true,
},
- folder: {
+ mailbox: {
type: Object,
required: true,
},
@@ -148,7 +149,7 @@ export default {
deleteAllSelected() {
this.selection.forEach((envelopeId) => {
// Navigate if the message being deleted is the one currently viewed
- if (this.envelopes[envelopeId].uuid === this.$route.params.messageUuid) {
+ if (this.envelopes[envelopeId].databaseId === this.$route.params.threadId) {
let next
if (envelopeId === 0) {
next = this.envelopes[envelopeId + 1]
@@ -160,14 +161,16 @@ export default {
this.$router.push({
name: 'message',
params: {
- accountId: this.$route.params.accountId,
- folderId: this.$route.params.folderId,
- messageUuid: next.uuid,
+ mailboxId: this.$route.params.mailboxId,
+ threadId: next.databaseId,
},
})
}
}
- this.$store.dispatch('deleteMessage', this.envelopes[envelopeId])
+ logger.info(`deleting message ${this.envelopes[envelopeId].databaseId}`)
+ this.$store.dispatch('deleteMessage', {
+ id: this.envelopes[envelopeId].databaseId,
+ })
})
this.unselectAll()
},
diff --git a/src/components/Mailbox.vue b/src/components/Mailbox.vue
index 3f8ab8066..8621fa2bf 100644
--- a/src/components/Mailbox.vue
+++ b/src/components/Mailbox.vue
@@ -31,7 +31,7 @@
<EnvelopeList
v-else
:account="account"
- :folder="folder"
+ :mailbox="mailbox"
:search-query="searchQuery"
:envelopes="envelopesToShow"
:refreshing="refreshing"
@@ -70,7 +70,7 @@ export default {
type: Object,
required: true,
},
- folder: {
+ mailbox: {
type: Object,
required: true,
},
@@ -115,7 +115,7 @@ export default {
},
computed: {
envelopes() {
- return this.$store.getters.getEnvelopes(this.account.id, this.folder.id, this.searchQuery)
+ return this.$store.getters.getEnvelopes(this.mailbox.databaseId, this.searchQuery)
},
envelopesToShow() {
if (this.paginate === 'manual' && !this.expanded) {
@@ -134,7 +134,7 @@ export default {
account() {
this.loadEnvelopes()
},
- folder() {
+ mailbox() {
this.loadEnvelopes()
},
searchQuery() {
@@ -163,8 +163,7 @@ export default {
this.$store
.dispatch('syncEnvelopes', {
- accountId: this.account.id,
- folderId: this.folder.id,
+ mailboxId: this.mailbox.databaseId,
query: this.searchQuery,
init: true,
})
@@ -175,15 +174,14 @@ export default {
})
},
async loadEnvelopes() {
- logger.debug('fetching envelopes')
+ logger.debug(`fetching envelopes for mailbox ${this.mailbox.databaseId} and query ${this.searchQuery}`, this.mailbox)
this.loadingEnvelopes = true
this.loadingCacheInitialization = false
this.error = false
try {
const envelopes = await this.$store.dispatch('fetchEnvelopes', {
- accountId: this.account.id,
- folderId: this.folder.id,
+ mailboxId: this.mailbox.databaseId,
query: this.searchQuery,
limit: this.initialPageSize,
})
@@ -196,15 +194,15 @@ export default {
// Show first message
const first = envelopes[0]
- // Keep the selected account-folder combination, but navigate to the message
- // (it's not a bug that we don't use first.accountId and first.folderId here)
+ // Keep the selected account-mailbox combination, but navigate to the message
+ // (it's not a bug that we don't use first.accountId and first.mailboxId here)
+ logger.debug('showing the first message of mailbox ' + this.$route.params.mailboxId)
this.$router.replace({
name: 'message',
params: {
- accountId: this.$route.params.accountId,
- folderId: this.$route.params.folderId,
+ mailboxId: this.$route.params.mailboxId,
filter: this.$route.params.filter ? this.$route.params.filter : undefined,
- messageUuid: first.uuid,
+ threadId: first.databaseId,
},
})
}
@@ -248,8 +246,7 @@ export default {
try {
const envelopes = await this.$store.dispatch('fetchNextEnvelopePage', {
- accountId: this.account.accountId,
- folderId: this.folder.id,
+ mailboxId: this.mailbox.databaseId,
envelopes: this.envelopes,
query: this.searchQuery,
})
@@ -265,23 +262,18 @@ export default {
},
handleShortcut(e) {
const envelopes = this.envelopes
- const currentUuid = this.$route.params.messageUuid
-
- if (!currentUuid) {
- logger.debug('ignoring shortcut: no envelope selected')
- return
- }
-
- const current = envelopes.filter((e) => e.uuid === currentUuid)
- if (current.length === 0) {
- logger.debug('ignoring shortcut: currently displayed messages is not in current envelope list')
- return
- }
+ const currentId = parseInt(this.$route.params.threadId, 10)
- const env = current[0]
+ const env = envelopes.find((e) => e.databaseId === currentId)
const idx = envelopes.indexOf(env)
let next
+ if (e.srcKey !== 'refresh' && !env) {
+ logger.debug('envelope is not in the list, ignoring shortcut', {
+ srcKey: e.srcKey,
+ })
+ }
+
switch (e.srcKey) {
case 'next':
case 'prev':
@@ -300,26 +292,23 @@ export default {
return
}
- // Keep the selected account-folder combination, but navigate to a different message
- // (it's not a bug that we don't use next.accountId and next.folderId here)
+ // Keep the selected account-mailbox combination, but navigate to a different message
+ // (it's not a bug that we don't use next.accountId and next.mailboxId here)
this.$router.push({
name: 'message',
params: {
- accountId: this.$route.params.accountId,
- folderId: this.$route.params.folderId,
+ mailboxId: this.$route.params.mailboxId,
filter: this.$route.params.filter ? this.$route.params.filter : undefined,
- messageUuid: next.uuid,
+ threadId: next.databaseId,
},
})
break
case 'del':
logger.debug('deleting', { env })
- this.onDelete(env.uuid)
+ this.onDelete(env.databaseId)
this.$store
.dispatch('deleteMessage', {
- accountId: env.accountId,
- folderId: env.folderId,
- uid: env.uid,
+ id: env.databaseId,
})
.catch((error) =>
logger.error('could not delete envelope', {
@@ -365,7 +354,7 @@ export default {
try {
await this.$store.dispatch('syncEnvelopes', {
accountId: this.account.accountId,
- folderId: this.folder.id,
+ mailboxId: this.mailbox.databaseId,
query: this.searchQuery,
})
} catch (error) {
@@ -381,14 +370,14 @@ export default {
this.refreshing = false
}
},
- onDelete(uuid) {
- const idx = findIndex(propEq('uuid', uuid), this.envelopes)
+ onDelete(id) {
+ const idx = findIndex(propEq('databaseId', id), this.envelopes)
if (idx === -1) {
logger.debug('envelope to delete does not exist in envelope list')
return
}
this.envelopes.splice(idx, 1)
- if (uuid !== this.$route.params.messageUuid) {
+ if (id !== this.$route.params.threadId) {
logger.debug('other message open, not jumping to the next/previous message')
return
}
@@ -399,15 +388,14 @@ export default {
return
}
- // Keep the selected account-folder combination, but navigate to a different message
- // (it's not a bug that we don't use next.accountId and next.folderId here)
+ // Keep the selected mailbox, but navigate to a different message
+ // (it's not a bug that we don't use next.mailboxId here)
this.$router.push({
name: 'message',
params: {
- accountId: this.$route.params.accountId,
- folderId: this.$route.params.folderId,
+ mailboxId: this.$route.params.mailboxId,
filter: this.$route.params.filter ? this.$route.params.filter : undefined,
- messageUuid: next.uuid,
+ threadId: next.databaseId,
},
})
},
@@ -421,13 +409,12 @@ export default {
},
async loadMailbox() {
// When the account is unified or inbox, return nothing, else sync the mailbox
- if (this.account.isUnified || this.folder.specialRole === 'inbox') {
+ if (this.account.isUnified || this.mailbox.specialRole === 'inbox') {
return
}
try {
await this.$store.dispatch('syncEnvelopes', {
- accountId: this.$route.params.accountId,
- folderId: this.$route.params.folderId,
+ mailboxId: this.$route.params.mailboxId,
query: this.searchQuery,
})
diff --git a/src/components/MailboxMessage.vue b/src/components/MailboxMessage.vue
index bcbf066a1..a45c8b6fc 100644
--- a/src/components/MailboxMessage.vue
+++ b/src/components/MailboxMessage.vue
@@ -11,9 +11,9 @@
:infinite-scroll-distance="10"
@shortkey.native="onShortcut">
<Mailbox
- v-if="!folder.isPriorityInbox"
+ v-if="!mailbox.isPriorityInbox"
:account="account"
- :folder="folder"
+ :mailbox="mailbox"
:search-query="query"
:bus="bus" />
<template v-else>
@@ -27,7 +27,7 @@
<Mailbox
class="nameimportant"
:account="unifiedAccount"
- :folder="unifiedInbox"
+ :mailbox="unifiedInbox"
:search-query="appendToSearch('is:important')"
:paginate="'manual'"
:is-priority-inbox="true"
@@ -38,7 +38,7 @@
<Mailbox
class="namestarred"
:account="unifiedAccount"
- :folder="unifiedInbox"
+ :mailbox="unifiedInbox"
:search-query="appendToSearch('is:starred not:important')"
:paginate="'manual'"
:is-priority-inbox="true"
@@ -48,7 +48,7 @@
<Mailbox
class="nameother"
:account="unifiedAccount"
- :folder="unifiedInbox"
+ :mailbox="unifiedInbox"
:open-first="false"
:search-query="appendToSearch('not:starred not:important')"
:is-priority-inbox="true"
@@ -102,7 +102,7 @@ export default {
type: Object,
required: true,
},
- folder: {
+ mailbox: {
type: Object,
required: true,
},
@@ -129,13 +129,13 @@ export default {
return this.$store.getters.getAccount(UNIFIED_ACCOUNT_ID)
},
unifiedInbox() {
- return this.$store.getters.getFolder(UNIFIED_ACCOUNT_ID, UNIFIED_INBOX_ID)
+ return this.$store.getters.getMailbox(UNIFIED_INBOX_ID)
},
hasMessages() {
- // it actually should be `return this.$store.getters.getEnvelopes(this.account.id, this.folder.id).length > 0`
- // but for some reason Vue doesn't track the dependencies on reactive data then and messages in subfolders can't
+ // it actually should be `return this.$store.getters.getEnvelopes(this.account.id, this.mailbox.databaseId).length > 0`
+ // but for some reason Vue doesn't track the dependencies on reactive data then and messages in submailboxes can't
// be opened then
- const list = this.folder.envelopeLists[normalizedEnvelopeListId(this.searchQuery)]
+ const list = this.mailbox.envelopeLists[normalizedEnvelopeListId(this.searchQuery)]
if (list === undefined) {
return false
@@ -143,7 +143,7 @@ export default {
return list.length > 0
},
showMessage() {
- return (this.folder.isPriorityInbox === true || this.hasMessages) && this.$route.name === 'message'
+ return (this.mailbox.isPriorityInbox === true || this.hasMessages) && this.$route.name === 'message'
},
query() {
if (this.$route.params.filter === 'starred') {
@@ -156,17 +156,19 @@ export default {
},
newMessage() {
return (
- this.$route.params.messageUuid === 'new'
- || this.$route.params.messageUuid === 'reply'
- || this.$route.params.messageUuid === 'replyAll'
+ this.$route.params.threadId === 'new'
+ || this.$route.params.threadId === 'reply'
+ || this.$route.params.threadId === 'replyAll'
)
},
},
created() {
this.alive = true
- // eslint-disable-next-line no-new
- new OCA.Search(this.searchProxy, this.clearSearchProxy)
+ window.addEventListener('DOMContentLoaded', (event) => {
+ // eslint-disable-next-line no-new
+ new OCA.Search(this.searchProxy, this.clearSearchProxy)
+ })
},
beforeDestroy() {
this.alive = false
@@ -174,16 +176,15 @@ export default {
methods: {
hideMessage() {
this.$router.replace({
- name: 'folder',
+ name: 'mailbox',
params: {
- accountId: this.account.id,
- folderId: this.folder.id,
+ mailboxId: this.mailbox.databaseId,
filter: this.$route.params.filter ? this.$route.params.filter : undefined,
},
})
},
- deleteMessage(envelopeUid) {
- this.bus.$emit('delete', envelopeUid)
+ deleteMessage(id) {
+ this.bus.$emit('delete', id)
},
onScroll(event) {
logger.debug('scroll', { event })
diff --git a/src/components/Message.vue b/src/components/Message.vue
index 54efdfdef..209ee080d 100644
--- a/src/components/Message.vue
+++ b/src/components/Message.vue
@@ -156,19 +156,10 @@ export default {
return isPgpgMessage(this.message.hasHtmlBody ? html(this.message.body) : plain(this.message.body))
},
htmlUrl() {
- return generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}/messages/{uid}/html', {
- accountId: this.message.accountId,
- folderId: this.message.folderId,
- uid: this.message.uid,
+ return generateUrl('/apps/mail/api/messages/{id}/html', {
+ id: this.envelope.databaseId,
})
},
- replyTo() {
- return {
- accountId: this.message.accountId,
- folderId: this.message.folderId,
- messageId: this.message.uid,
- }
- },
hasMultipleRecipients() {
return this.replyRecipient.to.concat(this.replyRecipient.cc).length > 1
},
@@ -177,9 +168,8 @@ export default {
$route(to, from) {
if (
from.name === to.name
- && Number.parseInt(from.params.accountId, 10) === Number.parseInt(to.params.accountId, 10)
- && from.params.folderId === to.params.folderId
- && from.params.messageUuid === to.params.messageUuid
+ && from.params.mailboxId === to.params.mailboxId
+ && from.params.threadId === to.params.threadId
&& from.params.filter === to.params.filter
) {
logger.debug('navigated but the message is still the same')
@@ -201,18 +191,21 @@ export default {
this.replyRecipient = {}
this.replySubject = ''
- const messageUuid = this.$route.params.messageUuid
+ const threadId = this.$route.params.threadId
try {
const [envelope, message] = await Promise.all([
- this.$store.dispatch('fetchEnvelope', messageUuid),
- this.$store.dispatch('fetchMessage', messageUuid),
+ this.$store.dispatch('fetchEnvelope', threadId),
+ this.$store.dispatch('fetchMessage', threadId),
])
logger.debug('envelope and message fetched', { envelope, message })
// TODO: add timeout so that message isn't flagged when only viewed
- // for a few seconds
- if (message && message.uuid !== this.$route.params.messageUuid) {
- logger.debug("User navigated away, loaded message won't be shown nor flagged as seen")
+ // for a few seconds
+ if (envelope && envelope.databaseId !== parseInt(this.$route.params.threadId, 10)) {
+ logger.debug("User navigated away, loaded message won't be shown nor flagged as seen", {
+ messageId: envelope.databaseId,
+ threadId: this.$route.params.threadId,
+ })
return
}
@@ -220,13 +213,13 @@ export default {
this.message = message
if (envelope === undefined || message === undefined) {
- logger.info('message could not be found', { messageUuid, envelope, message })
+ logger.info('message could not be found', { threadId, envelope, message })
this.errorMessage = getRandomMessageErrorMessage()
this.loading = false
return
}
- const account = this.$store.getters.getAccount(message.accountId)
+ const account = this.$store.getters.getAccount(envelope.accountId)
this.replyRecipient = buildReplyRecipients(message, {
label: account.name,
email: account.emailAddress,
@@ -240,7 +233,7 @@ export default {
return this.$store.dispatch('toggleEnvelopeSeen', envelope)
}
} catch (error) {
- logger.error('could not load message ', { messageUuid, error })
+ logger.error('could not load message ', { threadId, error })
if (error.isError) {
this.errorMessage = t('mail', 'Could not load your message')
this.error = error
@@ -252,13 +245,12 @@ export default {
this.$router.push({
name: 'message',
params: {
- accountId: this.$route.params.accountId,
- folderId: this.$route.params.folderId,
- messageUuid: 'reply',
+ mailboxId: this.$route.params.mailboxId,
+ threadId: 'reply',
filter: this.$route.params.filter ? this.$route.params.filter : undefined,
},
query: {
- uuid: this.message.uuid,
+ messageId: this.$route.params.threadId,
},
})
},
@@ -266,13 +258,12 @@ export default {
this.$router.push({
name: 'message',
params: {
- accountId: this.$route.params.accountId,
- folderId: this.$route.params.folderId,
- messageUuid: 'replyAll',
+ mailboxId: this.$route.params.mailboxId,
+ threadId: 'replyAll',
filter: this.$route.params.filter ? this.$route.params.filter : undefined,
},
query: {
- uuid: this.message.uuid,
+ messageId: this.$route.params.threadId,
},
})
},
@@ -280,13 +271,12 @@ export default {
this.$router.push({
name: 'message',
params: {
- accountId: this.$route.params.accountId,
- folderId: this.$route.params.folderId,
- messageUuid: 'new',
+ mailboxId: this.$route.params.mailboxId,
+ threadId: 'new',
filter: this.$route.params.filter ? this.$route.params.filter : undefined,
},
query: {
- uuid: this.message.uuid,
+ messageId: this.$route.params.threadId,
},
})
},
@@ -297,11 +287,9 @@ export default {
this.$store.dispatch('toggleEnvelopeJunk', this.envelope)
},
onDelete() {
- this.$emit('delete', this.envelope.uid)
+ this.$emit('delete', this.envelope.databaseId)
this.$store.dispatch('deleteMessage', {
- accountId: this.message.accountId,
- folderId: this.message.folderId,
- uid: this.message.uid,
+ id: this.envelope.databaseId,
})
},
async onShowSource() {
@@ -309,10 +297,8 @@ export default {
try {
const resp = await axios.get(
- generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}/messages/{uid}/source', {
- accountId: this.message.accountId,
- folderId: this.message.folderId,
- uid: this.message.uid,
+ generateUrl('/apps/mail/api/messages/{id}/source', {
+ id: this.envelope.databaseId,
})
)
diff --git a/src/components/MessageAttachment.vue b/src/components/MessageAttachment.vue
index 5e6274d16..50494b1e2 100644
--- a/src/components/MessageAttachment.vue
+++ b/src/components/MessageAttachment.vue
@@ -57,7 +57,6 @@ import { translate as t } from '@nextcloud/l10n'
import { getFilePickerBuilder } from '@nextcloud/dialogs'
import PopoverMenu from '@nextcloud/vue/dist/Components/PopoverMenu'
-import { parseUuid } from '../util/EnvelopeUidParser'
import Logger from '../logger'
import { downloadAttachment, saveAttachmentToFiles } from '../service/AttachmentService'
@@ -140,10 +139,10 @@ export default {
return formatFileSize(size)
},
saveToCloud() {
- const saveAttachment = (accountId, folderId, messageId, attachmentId) => (directory) => {
- return saveAttachmentToFiles(accountId, folderId, messageId, attachmentId, directory)
+ const saveAttachment = (id, attachmentId) => (directory) => {
+ return saveAttachmentToFiles(id, attachmentId, directory)
}
- const { accountId, folderId, uid } = parseUuid(this.$route.params.messageUuid)
+ const id = this.$route.params.threadId
const picker = getFilePickerBuilder(t('mail', 'Choose a folder to store the attachment in'))
.setMultiSelect(false)
.addMimeTypeFilter('httpd/unix-directory')
@@ -157,7 +156,7 @@ export default {
this.savingToCloud = true
return dest
})
- .then(saveAttachment(accountId, folderId, uid, this.id))
+ .then(saveAttachment(id, this.id))
.then(() => Logger.info('saved'))
.catch((e) => Logger.error('not saved', { error: e }))
.then(() => (this.savingToCloud = false))
diff --git a/src/components/MessageAttachments.vue b/src/components/MessageAttachments.vue
index aef44c87c..4e2700f81 100644
--- a/src/components/MessageAttachments.vue
+++ b/src/components/MessageAttachments.vue
@@ -48,7 +48,6 @@
<script>
import { getFilePickerBuilder } from '@nextcloud/dialogs'
-import { parseUuid } from '../util/EnvelopeUidParser'
import { saveAttachmentsToFiles } from '../service/AttachmentService'
import MessageAttachment from './MessageAttachment'
@@ -84,10 +83,10 @@ export default {
.setType(1)
.build()
- const saveAttachments = (accountId, folderId, messageId) => (directory) => {
- return saveAttachmentsToFiles(accountId, folderId, messageId, directory)
+ const saveAttachments = (id) => (directory) => {
+ return saveAttachmentsToFiles(id, directory)
}
- const { accountId, folderId, uid } = parseUuid(this.$route.params.messageUuid)
+ const id = this.$route.params.threadId
return picker
.pick()
@@ -95,7 +94,7 @@ export default {
this.savingToCloud = true
return dest
})
- .then(saveAttachments(accountId, folderId, uid))
+ .then(saveAttachments(id))
.then(() => Logger.info('saved'))
.catch((error) => Logger.error('not saved', { error }))
.then(() => (this.savingToCloud = false))
diff --git a/src/components/Navigation.vue b/src/components/Navigation.vue
index 082f3ea2b..ea60fd027 100644
--- a/src/components/Navigation.vue
+++ b/src/components/Navigation.vue
@@ -32,24 +32,24 @@
v-if="group.account"
:key="group.account.id"
:account="group.account"
- :first-folder="group.folders[0]"
+ :first-mailbox="group.mailboxes[0]"
:is-first="isFirst(group.account)"
:is-last="isLast(group.account)" />
- <template v-for="item in group.folders">
- <NavigationFolder
+ <template v-for="item in group.mailboxes">
+ <NavigationMailbox
v-show="
!group.isCollapsible ||
!group.account.collapsed ||
SHOW_COLLAPSED.indexOf(item.specialRole) !== -1
"
- :key="item.key"
+ :key="item.databaseId"
:account="group.account"
- :folder="item" />
- <NavigationFolder
+ :mailbox="item" />
+ <NavigationMailbox
v-if="!group.account.isUnified && item.specialRole === 'inbox'"
- :key="item.key + '-starred'"
+ :key="item.databaseId + '-starred'"
:account="group.account"
- :folder="item"
+ :mailbox="item"
filter="starred" />
</template>
<NavigationAccountExpandCollapse
@@ -74,7 +74,7 @@ import AppNavigationSpacer from '@nextcloud/vue/dist/Components/AppNavigationSpa
import logger from '../logger'
import NavigationAccount from './NavigationAccount'
import NavigationAccountExpandCollapse from './NavigationAccountExpandCollapse'
-import NavigationFolder from './NavigationFolder'
+import NavigationMailbox from './NavigationMailbox'
import AppSettingsMenu from '../components/AppSettingsMenu'
@@ -90,7 +90,7 @@ export default {
AppSettingsMenu,
NavigationAccount,
NavigationAccountExpandCollapse,
- NavigationFolder,
+ NavigationMailbox,
},
data() {
return {
@@ -100,16 +100,16 @@ export default {
computed: {
menu() {
return this.$store.getters.accounts.map((account) => {
- const folders = this.$store.getters.getFolders(account.id)
- const nonSpecialRoleFolders = folders.filter(
- (folder) => SHOW_COLLAPSED.indexOf(folder.specialRole) === -1
+ const mailboxes = this.$store.getters.getMailboxes(account.id)
+ const nonSpecialRoleMailboxes = mailboxes.filter(
+ (mailbox) => SHOW_COLLAPSED.indexOf(mailbox.specialRole) === -1
)
- const isCollapsible = nonSpecialRoleFolders.length > 1
+ const isCollapsible = nonSpecialRoleMailboxes.length > 1
return {
id: account.id,
account,
- folders,
+ mailboxes,
isCollapsible,
}
})
@@ -119,11 +119,10 @@ export default {
onNewMessage() {
const accountId = this.$route.params.accountId || this.$store.getters.accounts[0].id
- // FIXME: this assumes that there's at least one folder
- const folderId = this.$route.params.folderId || this.$store.getters.getFolders(accountId)[0].id
+ const mailboxId = this.$route.params.mailboxId || this.$store.getters.getMailboxes(accountId)[0]?.databaseId
if (
this.$router.currentRoute.name === 'message'
- && this.$router.currentRoute.params.messageUuid === 'new'
+ && this.$router.currentRoute.params.getMailboxes === 'new'
) {
// If we already show the composer, navigating to it would be pointless (and doesn't work)
// instead trigger an event to reset the composer
@@ -135,10 +134,9 @@ export default {
.push({
name: 'message',
params: {
- accountId,
- folderId,
+ mailboxId,
filter: this.$route.params.filter ? this.$route.params.filter : undefined,
- messageUuid: 'new',
+ threadId: 'new',
},
})
.catch((err) => {
diff --git a/src/components/NavigationAccount.vue b/src/components/NavigationAccount.vue
index 3bdbb7b4e..463fb1bef 100644
--- a/src/components/NavigationAccount.vue
+++ b/src/components/NavigationAccount.vue
@@ -27,7 +27,7 @@
:icon="iconError"
:menu-open.sync="menuOpen"
:title="account.emailAddress"
- :to="firstFolderRoute"
+ :to="firstMailboxRoute"
:exact="true"
@update:menuOpen="onMenuToggle">
<!-- Color dot -->
@@ -47,10 +47,10 @@
@update:checked="changeShowSubscribedOnly">
{{ t('mail', 'Show only subscribed folders') }}
</ActionCheckbox>
- <ActionButton v-if="!editing" icon="icon-folder" @click="openCreateFolder">
+ <ActionButton v-if="!editing" icon="icon-folder" @click="openCreateMailbox">
{{ t('mail', 'Add folder') }}
</ActionButton>
- <ActionInput v-if="editing" icon="icon-folder" @submit.prevent.stop="createFolder" />
+ <ActionInput v-if="editing" icon="icon-folder" @submit.prevent.stop="createMailbox" />
<ActionText v-if="showSaving" icon="icon-loading-small">
{{ t('mail', 'Saving') }}
</ActionText>
@@ -98,7 +98,7 @@ export default {
type: Object,
required: true,
},
- firstFolder: {
+ firstMailbox: {
type: Object,
required: true,
},
@@ -135,12 +135,11 @@ export default {
},
}
},
- firstFolderRoute() {
+ firstMailboxRoute() {
return {
- name: 'folder',
+ name: 'mailbox',
params: {
- accountId: this.account.id,
- folderId: this.firstFolder.id,
+ mailboxId: this.firstMailbox.databaseId,
},
}
},
@@ -168,22 +167,22 @@ export default {
},
},
methods: {
- createFolder(e) {
+ createMailbox(e) {
this.editing = true
const name = e.target.elements[1].value
- logger.info('creating folder ' + name)
+ logger.info('creating mailbox ' + name)
this.menuOpen = false
this.$store
- .dispatch('createFolder', { account: this.account, name })
- .then(() => logger.info(`folder ${name} created`))
+ .dispatch('createMailbox', { account: this.account, name })
+ .then(() => logger.info(`mailbox ${name} created`))
.catch((error) => {
- logger.error('could not create folder', { error })
+ logger.error('could not create mailbox', { error })
throw error
})
this.editing = false
this.showSaving = false
},
- openCreateFolder() {
+ openCreateMailbox() {
this.editing = true
this.showSaving = false
},
@@ -243,7 +242,7 @@ export default {
})
.then(() => {
this.savingShowOnlySubscribed = false
- logger.info('show only subscribed folders updated to ' + onlySubscribed)
+ logger.info('show only subscribed mailboxes updated to ' + onlySubscribed)
})
.catch((error) => {
logger.error('could not update subscription mode', { error })
diff --git a/src/components/NavigationFolder.vue b/src/components/NavigationMailbox.vue
index e81f56d7f..e25945110 100644
--- a/src/components/NavigationFolder.vue
+++ b/src/components/NavigationMailbox.vue
@@ -22,69 +22,69 @@
<template>
<AppNavigationItem
v-if="visible"
- :id="genId(folder)"
- :key="genId(folder)"
+ :id="genId(mailbox)"
+ :key="genId(mailbox)"
:allow-collapse="true"
:menu-open.sync="menuOpen"
:force-menu="true"
:icon="icon"
:title="title"
:to="to"
- :open.sync="showSubFolders"
+ :open.sync="showSubMailboxes"
@update:menuOpen="onMenuToggle">
<!-- actions -->
<template slot="actions">
<template>
<ActionText
- v-if="!account.isUnified && folder.specialRole !== 'flagged'"
+ v-if="!account.isUnified && mailbox.specialRole !== 'flagged'"
icon="icon-info"
- :title="folderId">
+ :title="mailbox.name">
{{ statsText }}
</ActionText>
<ActionButton
- v-if="folder.specialRole !== 'flagged'"
+ v-if="mailbox.specialRole !== 'flagged'"
icon="icon-mail"
:title="t('mail', 'Mark all as read')"
:disabled="loadingMarkAsRead"
@click="markAsRead">
- {{ t('mail', 'Mark all messages of this folder as read') }}
+ {{ t('mail', 'Mark all messages of this mailbox as read') }}
</ActionButton>
<ActionButton
- v-if="!editing && top && !account.isUnified && folder.specialRole !== 'flagged'"
+ v-if="!editing && top && !account.isUnified && mailbox.specialRole !== 'flagged'"
icon="icon-folder"
- @click="openCreateFolder">
+ @click="openCreateMailbox">
{{ t('mail', 'Add subfolder') }}
</ActionButton>
- <ActionInput v-if="editing" icon="icon-folder" @submit.prevent.stop="createFolder" />
+ <ActionInput v-if="editing" icon="icon-folder" @submit.prevent.stop="createMailbox" />
<ActionText v-if="showSaving" icon="icon-loading-small">
{{ t('mail', 'Saving') }}
</ActionText>
<ActionButton
- v-if="debug && !account.isUnified && folder.specialRole !== 'flagged'"
+ v-if="debug && !account.isUnified && mailbox.specialRole !== 'flagged'"
icon="icon-settings"
:title="t('mail', 'Clear cache')"
:disabled="clearingCache"
@click="clearCache">
{{ t('mail', 'Clear locally cached data, in case there are issues with synchronization.') }}
</ActionButton>
- <ActionButton v-if="!account.isUnified && !folder.specialRole" icon="icon-delete" @click="deleteFolder">
+ <ActionButton v-if="!account.isUnified && !mailbox.specialRole" icon="icon-delete" @click="deleteMailbox">
{{ t('mail', 'Delete folder') }}
</ActionButton>
</template>
</template>
- <AppNavigationCounter v-if="folder.unread" slot="counter">
- {{ folder.unread }}
+ <AppNavigationCounter v-if="mailbox.unread" slot="counter">
+ {{ mailbox.unread }}
</AppNavigationCounter>
- <!-- subfolders -->
- <NavigationFolder
- v-for="subFolder in subFolders"
- :key="genId(subFolder)"
+ <!-- submailboxes -->
+ <NavigationMailbox
+ v-for="subMailbox in subMailboxes"
+ :key="genId(subMailbox)"
:account="account"
- :folder="subFolder"
+ :mailbox="subMailbox"
:top="false" />
</AppNavigationItem>
</template>
@@ -97,13 +97,13 @@ import ActionInput from '@nextcloud/vue/dist/Components/ActionInput'
import ActionText from '@nextcloud/vue/dist/Components/ActionText'
import { clearCache } from '../service/MessageService'
-import { getFolderStats } from '../service/FolderService'
+import { getMailboxStatus } from '../service/MailboxService'
import logger from '../logger'
import { translatePlural as n } from '@nextcloud/l10n'
import { translate as translateMailboxName } from '../i18n/MailboxTranslator'
export default {
- name: 'NavigationFolder',
+ name: 'NavigationMailbox',
components: {
AppNavigationItem,
AppNavigationCounter,
@@ -116,7 +116,7 @@ export default {
type: Object,
required: true,
},
- folder: {
+ mailbox: {
type: Object,
required: true,
},
@@ -133,12 +133,12 @@ export default {
data() {
return {
debug: window?.OC?.debug || false,
- folderStats: undefined,
+ mailboxStats: undefined,
loadingMarkAsRead: false,
clearingCache: false,
showSaving: false,
editing: false,
- showSubFolders: false,
+ showSubMailboxes: false,
menuOpen: false,
}
},
@@ -146,58 +146,54 @@ export default {
visible() {
return (
this.account.showSubscribedOnly === false
- || (this.folder.attributes && this.folder.attributes.includes('\\subscribed'))
+ || (this.mailbox.attributes && this.mailbox.attributes.includes('\\subscribed'))
)
},
title() {
if (this.filter === 'starred') {
// Little hack to trick the translation logic into a different path
return translateMailboxName({
- ...this.folder,
+ ...this.mailbox,
specialUse: ['flagged'],
})
}
- return translateMailboxName(this.folder)
- },
- folderId() {
- return atob(this.folder.id)
+ return translateMailboxName(this.mailbox)
},
icon() {
if (this.filter === 'starred') {
return 'icon-flagged'
- } else if (this.folder.isPriorityInbox) {
+ } else if (this.mailbox.isPriorityInbox) {
return 'icon-important'
}
- return this.folder.specialRole ? 'icon-' + this.folder.specialRole : 'icon-folder'
+ return this.mailbox.specialRole ? 'icon-' + this.mailbox.specialRole : 'icon-folder'
},
to() {
return {
- name: 'folder',
+ name: 'mailbox',
params: {
- accountId: this.account.id,
- folderId: this.folder.id,
+ mailboxId: this.mailbox.databaseId,
filter: this.filter ? this.filter : undefined,
},
}
},
- subFolders() {
- return this.$store.getters.getSubfolders(this.account.id, this.folder.id)
+ subMailboxes() {
+ return this.$store.getters.getSubMailboxes(this.mailbox.databaseId)
},
statsText() {
- if (this.folderStats && 'total' in this.folderStats && 'unread' in this.folderStats) {
- if (this.folderStats.unread === 0) {
- return n('mail', '{total} message', '{total} messages', this.folderStats.total, {
- total: this.folderStats.total,
+ if (this.mailboxStats && 'total' in this.mailboxStats && 'unread' in this.mailboxStats) {
+ if (this.mailboxStats.unread === 0) {
+ return n('mail', '{total} message', '{total} messages', this.mailboxStats.total, {
+ total: this.mailboxStats.total,
})
} else {
return n(
'mail',
'{unread} unread of {total}',
'{unread} unread of {total}',
- this.folderStats.unread,
+ this.mailboxStats.unread,
{
- total: this.folderStats.total,
- unread: this.folderStats.unread,
+ total: this.mailboxStats.total,
+ unread: this.mailboxStats.unread,
}
)
}
@@ -207,12 +203,12 @@ export default {
},
methods: {
/**
- * Generate unique key id for a specific folder
- * @param {Object} folder the folder to gen id for
+ * Generate unique key id for a specific mailbox
+ * @param {Object} mailbox the mailbox to gen id for
* @returns {string}
*/
- genId(folder) {
- return 'account-' + this.account.id + '_' + folder.id
+ genId(mailbox) {
+ return 'mailbox-' + mailbox.databaseId
},
/**
@@ -221,51 +217,51 @@ export default {
*/
onMenuToggle(open) {
if (open) {
- this.fetchFolderStats()
+ this.fetchMailboxStats()
}
},
/**
- * Fetch folder unread/read stats
+ * Fetch mailbox unread/read stats
*/
- async fetchFolderStats() {
- this.folderStats = null
- if (this.account.isUnified || this.folder.specialRole === 'flagged') {
+ async fetchMailboxStats() {
+ this.mailboxStats = null
+ if (this.account.isUnified || this.mailbox.specialRole === 'flagged') {
return
}
try {
- const stats = await getFolderStats(this.account.id, this.folder.id)
- logger.debug('loaded folder stats', { stats })
- this.folderStats = stats
+ const stats = await getMailboxStatus(this.mailbox.databaseId)
+ logger.debug(`loaded mailbox stats for ${this.mailbox.databaseId}`, { stats })
+ this.mailboxStats = stats
} catch (error) {
- this.folderStats = { error: true }
- logger.error(`could not load folder stats for ${this.folder.id}`, error)
+ this.mailboxStats = { error: true }
+ logger.error(`could not load mailbox stats for ${this.mailbox.databaseId}`, error)
}
},
- async createFolder(e) {
+ async createMailbox(e) {
this.editing = true
const name = e.target.elements[1].value
- const withPrefix = atob(this.folder.id) + this.folder.delimiter + name
- logger.info(`creating folder ${withPrefix} as subfolder of ${this.folder.id}`)
+ const withPrefix = atob(this.mailbox.databaseId) + this.mailbox.delimiter + name
+ logger.info(`creating mailbox ${withPrefix} as submailbox of ${this.mailbox.databaseId}`)
this.menuOpen = false
try {
- await this.$store.dispatch('createFolder', {
+ await this.$store.dispatch('createMailbox', {
account: this.account,
name: withPrefix,
})
} catch (error) {
- logger.error(`could not create folder ${withPrefix}`, { error })
+ logger.error(`could not create mailbox ${withPrefix}`, { error })
throw error
} finally {
this.editing = false
this.showSaving = false
}
- logger.info(`folder ${withPrefix} created`)
- this.showSubFolders = true
+ logger.info(`mailbox ${withPrefix} created`)
+ this.showSubMailboxes = true
},
- openCreateFolder() {
+ openCreateMailbox() {
this.editing = true
this.showSaving = false
},
@@ -273,12 +269,12 @@ export default {
this.loadingMarkAsRead = true
this.$store
- .dispatch('markFolderRead', {
+ .dispatch('markMailboxRead', {
accountId: this.account.id,
- folderId: this.folder.id,
+ mailboxId: this.mailbox.databaseId,
})
- .then(() => logger.info(`folder ${this.folder.id} marked as read`))
- .catch((error) => logger.error(`could not mark folder ${this.folder.id} as read`, { error }))
+ .then(() => logger.info(`mailbox ${this.mailbox.databaseId} marked as read`))
+ .catch((error) => logger.error(`could not mark mailbox ${this.mailbox.databaseId} as read`, { error }))
.then(() => (this.loadingMarkAsRead = false))
},
async clearCache() {
@@ -286,10 +282,10 @@ export default {
this.clearingCache = true
logger.debug('clearing message cache', {
accountId: this.account.id,
- folderId: this.folder.id,
+ mailboxId: this.mailbox.databaseId,
})
- await clearCache(this.account.id, this.folder.id)
+ await clearCache(this.account.id, this.mailbox.databaseId)
// TODO: there might be a nicer way to handle this
window.location.reload(false)
@@ -297,28 +293,26 @@ export default {
this.clearCache = false
}
},
- deleteFolder() {
- const id = this.folder.id
- logger.info('delete folder', { folder: this.folder })
+ deleteMailbox() {
+ const id = this.mailbox.databaseId
+ logger.info('delete mailbox', { mailbox: this.mailbox })
OC.dialogs.confirmDestructive(
- t('mail', 'The folder and all messages in it will be deleted.', {
- folderId: this.folderId,
- }),
+ t('mail', 'The folder and all messages in it will be deleted.'),
t('mail', 'Delete folder'),
{
type: OC.dialogs.YES_NO_BUTTONS,
- confirm: t('mail', 'Delete folder {folderId}', { folderId: this.folderId }),
+ confirm: t('mail', 'Delete folder {name}', { name: this.mailbox.displayName }),
confirmClasses: 'error',
cancel: t('mail', 'Cancel'),
},
(result) => {
if (result) {
return this.$store
- .dispatch('deleteFolder', { account: this.account, folder: this.folder })
+ .dispatch('deleteMailbox', { mailbox: this.mailbox })
.then(() => {
- logger.info(`folder ${id} deleted`)
+ logger.info(`mailbox ${id} deleted`)
})
- .catch((error) => logger.error('could not delete folder', { error }))
+ .catch((error) => logger.error('could not delete mailbox', { error }))
}
}
)
diff --git a/src/components/NewMessageDetail.vue b/src/components/NewMessageDetail.vue
index 09d812173..d9ea48fc3 100644
--- a/src/components/NewMessageDetail.vue
+++ b/src/components/NewMessageDetail.vue
@@ -25,6 +25,7 @@
import AppContentDetails from '@nextcloud/vue/dist/Components/AppContentDetails'
import Axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
+import { translate as t } from '@nextcloud/l10n'
import { buildForwardSubject, buildReplySubject, buildRecipients as buildReplyRecipients } from '../ReplyBuilder'
import Composer from './Composer'
@@ -64,13 +65,15 @@ export default {
subject: this.draft.subject,
body: this.draft.hasHtmlBody ? html(this.draft.body) : plain(this.draft.body),
}
- } else if (this.$route.query.uuid !== undefined) {
+ } else if (this.$route.query.messageId !== undefined) {
// Forward or reply to a message
const message = this.original
logger.debug('forwarding or replying to message', { message })
- if (this.$route.params.messageUuid === 'reply') {
- logger.debug('simple reply')
+ if (this.$route.params.threadId === 'reply') {
+ logger.debug('simple reply', {
+ message,
+ })
return {
accountId: message.accountId,
@@ -81,7 +84,7 @@ export default {
originalBody: this.originalBody,
replyTo: message,
}
- } else if (this.$route.params.messageUuid === 'replyAll') {
+ } else if (this.$route.params.threadId === 'replyAll') {
logger.debug('replying to all', { original: this.original })
const account = this.$store.getters.getAccount(message.accountId)
const recipients = buildReplyRecipients(message, {
@@ -112,6 +115,9 @@ export default {
}
} else {
// New or mailto: message
+ logger.debug('composing a new message or handling a mailto link', {
+ threadId: this.$route.params.threadId,
+ })
let accountId
// Only preselect an account when we're not in a unified mailbox
@@ -134,10 +140,14 @@ export default {
// `saveDraft` replaced the current URL with the updated draft UID
// in that case we don't really start a new draft but just keep the
// URL consistent, hence not loading anything
- if (this.draft && to.name === 'message' && to.params.draftUid === this.draft.uid) {
+ if (to.name === 'message' && this.draft && to.params.draftId === parseInt(this.draft.databaseId, 10)) {
logger.debug('detected navigation to current (new) draft UID, not reloading')
return
}
+ logger.debug('the draft ID changed, we have to fetch the draft', {
+ currentId: this.draft.databaseId,
+ newId: to.params.draftId,
+ })
this.fetchMessage()
},
@@ -159,30 +169,33 @@ export default {
]
},
fetchMessage() {
- if (this.$route.params.draftUid !== undefined) {
- return this.fetchDraftMessage(this.$route.params.draftUid)
- } else if (this.$route.query.uuid !== undefined) {
- return this.fetchOriginalMessage(this.$route.query.uuid)
+ if (this.$route.params.draftId !== undefined) {
+ return this.fetchDraftMessage(this.$route.params.draftId)
+ } else if (this.$route.query.messageId !== undefined) {
+ return this.fetchOriginalMessage(this.$route.query.messageId)
}
},
- fetchDraftMessage(draftUid) {
+ fetchDraftMessage(id) {
this.loading = true
this.draft = undefined
this.error = undefined
this.errorMessage = ''
this.$store
- .dispatch('fetchMessage', draftUid)
+ .dispatch('fetchMessage', id)
.then((draft) => {
- if (draft.uid !== this.$route.params.draftUid) {
- logger.debug("User navigated away, loaded draft won't be shown")
+ if (draft.databaseId !== parseInt(this.$route.params.draftId, 10)) {
+ logger.debug("User navigated away, loaded draft won't be shown", {
+ draft,
+ draftId: this.$route.params.draftId,
+ })
return
}
this.draft = draft
if (this.draft === undefined) {
- logger.info('draft could not be found', { draftUid })
+ logger.info('draft could not be found', { id })
this.errorMessage = getRandomMessageErrorMessage()
this.loading = false
return
@@ -191,7 +204,7 @@ export default {
this.loading = false
})
.catch((error) => {
- logger.error('could not load draft ' + draftUid, { error })
+ logger.error(`could not load draft ${id}`, { error })
if (error.isError) {
this.errorMessage = t('mail', 'Could not load your draft')
this.error = error
@@ -199,15 +212,21 @@ export default {
}
})
},
- async fetchOriginalMessage(uid) {
+ async fetchOriginalMessage(id) {
this.loading = true
this.error = undefined
this.errorMessage = ''
+ logger.debug(`fetching original message ${id}`)
+
try {
- const message = await this.$store.dispatch('fetchMessage', uid)
- if (message.uuid !== this.$route.query.uuid) {
- logger.debug("User navigated away, loaded original message won't be used")
+ const message = await this.$store.dispatch('fetchMessage', id)
+ if (message.databaseId !== parseInt(this.$route.query.messageId, 10)) {
+ logger.debug("User navigated away, loaded original message won't be used", {
+ message,
+ messageId: message.databaseId,
+ urlId: this.$route.query.messageId,
+ })
return
}
@@ -218,10 +237,8 @@ export default {
if (message.hasHtmlBody) {
logger.debug('original message has HTML body')
const resp = await Axios.get(
- generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}/messages/{uid}/html', {
- accountId: message.accountId,
- folderId: message.folderId,
- uid: message.uid,
+ generateUrl('/apps/mail/api/messages/{id}/html', {
+ id,
})
)
@@ -229,7 +246,7 @@ export default {
}
this.originalBody = body
} catch (error) {
- logger.error('could not load original message ' + uid, { error })
+ logger.error('could not load original message ' + id, { error })
if (error.isError) {
this.errorMessage = t('mail', 'Could not load original message')
this.error = error
@@ -239,41 +256,17 @@ export default {
this.loading = false
}
},
- saveDraft(data) {
- if (data.draftUID === undefined && this.draft) {
- logger.debug('draft data does not have a draftUID, adding one')
- data.draftUID = this.draft.id
+ async saveDraft(data) {
+ if (data.draftId === undefined && this.draft) {
+ logger.debug('draft data does not have a draftId, adding one', { draft: this.draft, data, id: this.draft.databaseId })
+ data.draftId = this.draft.databaseId
}
const dataForServer = {
...data,
body: data.isHtml ? data.body.value : toPlain(data.body).value,
}
- return saveDraft(data.account, dataForServer).then(({ uid }) => {
- if (this.draft === undefined) {
- return uid
- }
-
- logger.info('replacing draft ' + this.draft.uid + ' with ' + uid)
- const update = {
- draft: this.draft,
- uid,
- data,
- }
- return this.$store
- .dispatch('replaceDraft', update)
- .then(() =>
- this.$router.replace({
- name: 'message',
- params: {
- accountId: this.$route.params.accountId,
- folderId: this.$route.params.folderId,
- messageUuid: 'new',
- draftUid: this.draft.uid,
- },
- })
- )
- .then(() => uid)
- })
+ const { id } = await saveDraft(data.account, dataForServer)
+ return id
},
sendMessage(data) {
logger.debug('sending message', { data })
diff --git a/src/i18n/MailboxTranslator.js b/src/i18n/MailboxTranslator.js
index 6c150493a..b5ada8457 100644
--- a/src/i18n/MailboxTranslator.js
+++ b/src/i18n/MailboxTranslator.js
@@ -21,28 +21,28 @@
import { translate as t } from '@nextcloud/l10n'
-const translateSpecial = (folder) => {
- if (folder.specialUse.includes('all')) {
+const translateSpecial = (mailbox) => {
+ if (mailbox.specialUse.includes('all')) {
// TRANSLATORS: translated mail box name
return t('mail', 'All')
}
- if (folder.specialUse.includes('archive')) {
+ if (mailbox.specialUse.includes('archive')) {
// TRANSLATORS: translated mail box name
return t('mail', 'Archive')
}
- if (folder.specialUse.includes('drafts')) {
+ if (mailbox.specialUse.includes('drafts')) {
// TRANSLATORS: translated mail box name
return t('mail', 'Drafts')
}
- if (folder.specialUse.includes('flagged')) {
+ if (mailbox.specialUse.includes('flagged')) {
// TRANSLATORS: translated mail box name
return t('mail', 'Favorites')
}
- if (folder.specialUse.includes('inbox')) {
- if (folder.isPriorityInbox) {
+ if (mailbox.specialUse.includes('inbox')) {
+ if (mailbox.isPriorityInbox) {
// TRANSLATORS: translated mail box name
return t('mail', 'Priority inbox')
- } else if (folder.isUnified) {
+ } else if (mailbox.isUnified) {
// TRANSLATORS: translated mail box name
return t('mail', 'All inboxes')
} else {
@@ -50,28 +50,28 @@ const translateSpecial = (folder) => {
return t('mail', 'Inbox')
}
}
- if (folder.specialUse.includes('junk')) {
+ if (mailbox.specialUse.includes('junk')) {
// TRANSLATORS: translated mail box name
return t('mail', 'Junk')
}
- if (folder.specialUse.includes('sent')) {
+ if (mailbox.specialUse.includes('sent')) {
// TRANSLATORS: translated mail box name
return t('mail', 'Sent')
}
- if (folder.specialUse.includes('trash')) {
+ if (mailbox.specialUse.includes('trash')) {
// TRANSLATORS: translated mail box name
return t('mail', 'Trash')
}
- throw new Error(`unknown special use ${folder.specialUse}`)
+ throw new Error(`unknown special use ${mailbox.specialUse}`)
}
-export const translate = (folder) => {
- if (folder.specialUse.length > 0) {
+export const translate = (mailbox) => {
+ if (mailbox.specialUse.length > 0) {
try {
- return translateSpecial(folder)
+ return translateSpecial(mailbox)
} catch (e) {
- console.error('could not translate special folder', e)
+ console.error('could not translate special mailbox', e)
}
}
- return folder.displayName
+ return mailbox.displayName
}
diff --git a/src/imap/MailboxHierarchy.js b/src/imap/MailboxHierarchy.js
index e90b1ce7b..c418c3e0b 100644
--- a/src/imap/MailboxHierarchy.js
+++ b/src/imap/MailboxHierarchy.js
@@ -21,8 +21,8 @@
const getParentId = (mailbox, hasPrefix) => {
const top = hasPrefix ? 1 : 0
- const hierarchy = atob(mailbox.id).split(mailbox.delimiter)
- if (hierarchy.length <= top + 1 || atob(mailbox.id) === 'INBOX/FLAGGED') {
+ const hierarchy = mailbox.name.split(mailbox.delimiter)
+ if (hierarchy.length <= top + 1 || mailbox.name === 'INBOX/FLAGGED') {
return
}
if (hasPrefix) {
@@ -40,7 +40,7 @@ export const buildMailboxHierarchy = (mailboxes, havePrefix) => {
const cloned = mailboxes.map((mailbox) => {
return {
- folders: [],
+ mailboxes: [],
...mailbox,
}
})
@@ -52,9 +52,9 @@ export const buildMailboxHierarchy = (mailboxes, havePrefix) => {
}
const parentId = getParentId(mailbox, havePrefix)
- const parent = cloned.filter((mailbox) => atob(mailbox.id) === parentId)[0]
+ const parent = cloned.filter((mailbox) => mailbox.name === parentId)[0]
if (parent) {
- parent.folders.push(mailbox)
+ parent.mailboxes.push(mailbox)
}
})
diff --git a/src/imap/MailboxPrefix.js b/src/imap/MailboxPrefix.js
index 291a2eb02..68a49b4bf 100644
--- a/src/imap/MailboxPrefix.js
+++ b/src/imap/MailboxPrefix.js
@@ -24,7 +24,7 @@ const PREFIX = 'INBOX'
export const havePrefix = (mailboxes) => {
return (
mailboxes.filter((mailbox) => {
- const hierarchy = mailbox.id.split(mailbox.delimiter)
+ const hierarchy = mailbox.name.split(mailbox.delimiter)
if (hierarchy.length < 1 || hierarchy[0] !== PREFIX) {
return false
}
diff --git a/src/router.js b/src/router.js
index 487bd81d5..ff1665887 100644
--- a/src/router.js
+++ b/src/router.js
@@ -10,6 +10,7 @@ const Setup = () => import('./views/Setup')
Vue.use(Router)
export default new Router({
+ mode: 'history',
base: generateUrl('/apps/mail/'),
linkActiveClass: 'active',
routes: [
@@ -24,12 +25,12 @@ export default new Router({
component: Home,
},
{
- path: '/accounts/:accountId/folders/:filter?/:folderId',
- name: 'folder',
+ path: '/box/:filter?/:mailboxId',
+ name: 'mailbox',
component: Home,
},
{
- path: '/accounts/:accountId/folders/:filter?/:folderId/message/:messageUuid/:draftUid?',
+ path: '/box/:filter?/:mailboxId/thread/:threadId/:draftId?',
name: 'message',
component: Home,
},
diff --git a/src/service/AliasService.js b/src/service/AliasService.js
index cd07aa15c..6f0391b51 100644
--- a/src/service/AliasService.js
+++ b/src/service/AliasService.js
@@ -2,12 +2,13 @@ import { generateUrl } from '@nextcloud/router'
import axios from '@nextcloud/axios'
export const createAlias = async(account, data) => {
- const url = generateUrl('/apps/mail/api/accounts/{id}/aliases', {
- id: account.accountId,
- })
+ const url = generateUrl('/apps/mail/api/aliases')
return axios
- .post(url, data)
+ .post(url, {
+ accountId: account.id,
+ ...data,
+ })
.then((resp) => resp.data)
.catch((e) => {
if (e.response && e.response.status === 400) {
diff --git a/src/service/AttachmentService.js b/src/service/AttachmentService.js
index 3f47cfef6..7bfe27455 100644
--- a/src/service/AttachmentService.js
+++ b/src/service/AttachmentService.js
@@ -22,13 +22,11 @@
import Axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
-export function saveAttachmentToFiles(accountId, folderId, messageId, attachmentId, directory) {
+export function saveAttachmentToFiles(id, attachmentId, directory) {
const url = generateUrl(
- 'apps/mail/api/accounts/{accountId}/folders/{folderId}/messages/{messageId}/attachment/{attachmentId}',
+ '/apps/mail/api/messages/{id}/attachment/{attachmentId}',
{
- accountId,
- folderId,
- messageId,
+ id,
attachmentId,
}
)
@@ -38,8 +36,8 @@ export function saveAttachmentToFiles(accountId, folderId, messageId, attachment
})
}
-export function saveAttachmentsToFiles(accountId, folderId, messageId, directory) {
- return saveAttachmentToFiles(accountId, folderId, messageId, 0, directory)
+export function saveAttachmentsToFiles(id, directory) {
+ return saveAttachmentToFiles(id, 0, directory)
}
export function downloadAttachment(url) {
diff --git a/src/service/FolderService.js b/src/service/FolderService.js
deleted file mode 100644
index d1ec0243e..000000000
--- a/src/service/FolderService.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import { generateUrl } from '@nextcloud/router'
-import Axios from '@nextcloud/axios'
-
-export function fetchAll(accountId) {
- const url = generateUrl('/apps/mail/api/accounts/{accountId}/folders', {
- accountId,
- })
-
- // FIXME: this return format is weird and should be avoided
- // TODO: respect `resp.data.delimiter` value
- return Axios.get(url).then((resp) => resp.data.folders)
-}
-
-export function create(accountId, name) {
- const url = generateUrl('/apps/mail/api/accounts/{accountId}/folders', {
- accountId,
- })
-
- const data = {
- name,
- }
- return Axios.post(url, data).then((resp) => resp.data)
-}
-
-export function getFolderStats(accountId, folderId) {
- const url = generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}/stats', {
- accountId,
- folderId,
- })
-
- return Axios.get(url).then((resp) => resp.data)
-}
-
-export function markFolderRead(accountId, folderId) {
- const url = generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}/read', {
- accountId,
- folderId,
- })
-
- return Axios.post(url).then((resp) => resp.data)
-}
-
-export const deleteFolder = async(accountId, folderId) => {
- const url = generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}', {
- accountId,
- folderId,
- })
-
- await Axios.delete(url)
-}
diff --git a/src/service/MailboxService.js b/src/service/MailboxService.js
new file mode 100644
index 000000000..0b0e38c4e
--- /dev/null
+++ b/src/service/MailboxService.js
@@ -0,0 +1,48 @@
+import { generateUrl } from '@nextcloud/router'
+import axios from '@nextcloud/axios'
+
+export async function fetchAll(accountId) {
+ const url = generateUrl('/apps/mail/api/mailboxes?accountId={accountId}', {
+ accountId,
+ })
+
+ const resp = await axios.get(url)
+
+ // FIXME: this return format is weird and should be avoided
+ // TODO: respect `resp.data.delimiter` value
+ return resp.data.mailboxes
+}
+
+export function create(accountId, name) {
+ const url = generateUrl('/apps/mail/api/mailboxes')
+
+ const data = {
+ accountId,
+ name,
+ }
+ return axios.post(url, data).then((resp) => resp.data)
+}
+
+export function getMailboxStatus(id) {
+ const url = generateUrl('/apps/mail/api/mailboxes/{id}/stats', {
+ id,
+ })
+
+ return axios.get(url).then((resp) => resp.data)
+}
+
+export function markMailboxRead(id) {
+ const url = generateUrl('/apps/mail/api/mailboxes/{id}/read', {
+ id,
+ })
+
+ return axios.post(url).then((resp) => resp.data)
+}
+
+export const deleteMailbox = async(id) => {
+ const url = generateUrl('/apps/mail/api/mailboxes/{id}', {
+ id,
+ })
+
+ await axios.delete(url)
+}
diff --git a/src/service/MessageService.js b/src/service/MessageService.js
index 57f94b911..d9ee16bac 100644
--- a/src/service/MessageService.js
+++ b/src/service/MessageService.js
@@ -1,28 +1,24 @@
import { generateUrl } from '@nextcloud/router'
import axios from '@nextcloud/axios'
-import { curry, map } from 'ramda'
+import { curry } from 'ramda'
import { parseErrorResponse } from '../http/ErrorResponseParser'
import { convertAxiosError } from '../errors/convert'
import SyncIncompleteError from '../errors/SyncIncompleteError'
-const amendEnvelopeWithIds = curry((accountId, folderId, envelope) => ({
+const amendEnvelopeWithIds = curry((accountId, envelope) => ({
accountId,
- folderId,
- uuid: `${accountId}-${folderId}-${envelope.uid}`,
...envelope,
}))
-export function fetchEnvelope(accountId, folderId, uid) {
- const url = generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}/messages/{uid}', {
- accountId,
- folderId,
- uid,
+export function fetchEnvelope(id) {
+ const url = generateUrl('/apps/mail/api/messages/{id}', {
+ id,
})
return axios
.get(url)
- .then((resp) => amendEnvelopeWithIds(accountId, folderId, resp.data))
+ .then((resp) => resp.data)
.catch((error) => {
if (error.response && error.response.status === 404) {
return undefined
@@ -31,12 +27,11 @@ export function fetchEnvelope(accountId, folderId, uid) {
})
}
-export function fetchEnvelopes(accountId, folderId, query, cursor, limit) {
- const url = generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}/messages', {
- accountId,
- folderId,
- })
- const params = {}
+export function fetchEnvelopes(mailboxId, query, cursor, limit) {
+ const url = generateUrl('/apps/mail/api/messages')
+ const params = {
+ mailboxId,
+ }
if (query) {
params.filter = query
@@ -53,21 +48,19 @@ export function fetchEnvelopes(accountId, folderId, query, cursor, limit) {
params,
})
.then((resp) => resp.data)
- .then(map(amendEnvelopeWithIds(accountId, folderId)))
.catch((error) => {
throw convertAxiosError(error)
})
}
-export async function syncEnvelopes(accountId, folderId, uids, query, init = false) {
- const url = generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}/sync', {
- accountId,
- folderId,
+export async function syncEnvelopes(accountId, id, ids, query, init = false) {
+ const url = generateUrl('/apps/mail/api/mailboxes/{id}/sync', {
+ id,
})
try {
const response = await axios.post(url, {
- uids,
+ ids,
query,
init,
})
@@ -76,7 +69,7 @@ export async function syncEnvelopes(accountId, folderId, uids, query, init = fal
throw new SyncIncompleteError()
}
- const amend = amendEnvelopeWithIds(accountId, folderId)
+ const amend = amendEnvelopeWithIds(accountId)
return {
newMessages: response.data.newMessages.map(amend),
changedMessages: response.data.changedMessages.map(amend),
@@ -87,10 +80,9 @@ export async function syncEnvelopes(accountId, folderId, uids, query, init = fal
}
}
-export async function clearCache(accountId, folderId) {
- const url = generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}/sync', {
- accountId,
- folderId,
+export async function clearCache(accountId, id) {
+ const url = generateUrl('/apps/mail/api/mailboxes/{id}/sync', {
+ id,
})
try {
@@ -104,38 +96,34 @@ export async function clearCache(accountId, folderId) {
}
}
-export function setEnvelopeFlag(accountId, folderId, uid, flag, value) {
- const url = generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}/messages/{uid}/flags', {
- accountId,
- folderId,
- uid,
+export function setEnvelopeFlag(id, flag, value) {
+ const url = generateUrl('/apps/mail/api/messages/{id}/flags', {
+ id,
})
- const flags = {}
- flags[flag] = value
-
return axios
.put(url, {
- flags,
+ flags: {
+ [flag]: value,
+ },
})
}
-export function fetchMessage(accountId, folderId, id) {
- const url = generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}/messages/{id}/body', {
- accountId,
- folderId,
+export async function fetchMessage(id) {
+ const url = generateUrl('/apps/mail/api/messages/{id}/body', {
id,
})
- return axios
- .get(url)
- .then((resp) => resp.data)
- .catch((error) => {
- if (error.response && error.response.status === 404) {
- return undefined
- }
- return Promise.reject(parseErrorResponse(error.response))
- })
+ try {
+ const resp = await axios.get(url)
+ return resp.data
+ } catch (error) {
+ if (error.response && error.response.status === 404) {
+ return undefined
+ }
+
+ throw parseErrorResponse(error.response)
+ }
}
export async function saveDraft(accountId, data) {
@@ -154,10 +142,8 @@ export function sendMessage(accountId, data) {
return axios.post(url, data).then((resp) => resp.data)
}
-export function deleteMessage(accountId, folderId, id) {
- const url = generateUrl('/apps/mail/api/accounts/{accountId}/folders/{folderId}/messages/{id}', {
- accountId,
- folderId,
+export function deleteMessage(id) {
+ const url = generateUrl('/apps/mail/api/messages/{id}', {
id,
})
diff --git a/src/store/actions.js b/src/store/actions.js
index 344b643c1..d0a62e26e 100644
--- a/src/store/actions.js
+++ b/src/store/actions.js
@@ -51,11 +51,11 @@ import {
updateSignature,
} from '../service/AccountService'
import {
- create as createFolder,
- fetchAll as fetchAllFolders,
- markFolderRead,
- deleteFolder,
-} from '../service/FolderService'
+ create as createMailbox,
+ deleteMailbox,
+ fetchAll as fetchAllMailboxes,
+ markMailboxRead,
+} from '../service/MailboxService'
import {
deleteMessage,
fetchEnvelope,
@@ -68,22 +68,21 @@ import { createAlias, deleteAlias } from '../service/AliasService'
import logger from '../logger'
import { normalizedEnvelopeListId } from './normalization'
import { showNewMessagesNotification } from '../service/NotificationService'
-import { parseUuid } from '../util/EnvelopeUidParser'
import { matchError } from '../errors/match'
import SyncIncompleteError from '../errors/SyncIncompleteError'
import MailboxLockedError from '../errors/MailboxLockedError'
import { wait } from '../util/wait'
-import { UNIFIED_ACCOUNT_ID, UNIFIED_INBOX_ID } from './constants'
+import { UNIFIED_INBOX_ID } from './constants'
const PAGE_SIZE = 20
const sliceToPage = slice(0, PAGE_SIZE)
-const findIndividualFolders = curry((getFolders, specialRole) =>
+const findIndividualMailboxes = curry((getMailboxes, specialRole) =>
pipe(
filter(complement(prop('isUnified'))),
- map(prop('accountId')),
- map(getFolders),
+ map(prop('id')),
+ map(getMailboxes),
flatten,
filter(propEq('specialRole', specialRole))
)
@@ -114,13 +113,13 @@ export default {
},
createAccount({ commit }, config) {
return createAccount(config).then((account) => {
- logger.debug(`account ${account.id} created, fetching folders …`, account)
- return fetchAllFolders(account.id)
- .then((folders) => {
- account.folders = folders
+ logger.debug(`account ${account.id} created, fetching mailboxes …`, account)
+ return fetchAllMailboxes(account.id)
+ .then((mailboxes) => {
+ account.mailboxes = mailboxes
commit('addAccount', account)
})
- .then(() => console.info("new account's folders fetched"))
+ .then(() => console.info("new account's mailboxes fetched"))
.then(() => account)
})
},
@@ -152,16 +151,15 @@ export default {
throw err
})
},
- async deleteFolder({ commit }, { account, folder }) {
- await deleteFolder(account.id, folder.id)
- commit('removeFolder', { accountId: account.id, folderId: folder.id })
+ async deleteMailbox({ commit }, { mailbox }) {
+ await deleteMailbox(mailbox.databaseId)
+ commit('removeMailbox', { id: mailbox.databaseId })
},
- createFolder({ commit }, { account, name }) {
- return createFolder(account.id, name).then((folder) => {
- console.debug(`folder ${name} created for account ${account.id}`, { folder })
- commit('addFolder', { account, folder })
- commit('expandAccount', account.id)
- })
+ async createMailbox({ commit }, { account, name }) {
+ const mailbox = await createMailbox(account.id, name)
+ console.debug(`mailbox ${name} created for account ${account.id}`, { mailbox })
+ commit('addMailbox', { account, mailbox })
+ commit('expandAccount', account.id)
},
moveAccount({ commit, getters }, { account, up }) {
const accounts = getters.accounts
@@ -185,61 +183,56 @@ export default {
})
)
},
- markFolderRead({ getters, dispatch }, { accountId, folderId }) {
- const folder = getters.getFolder(accountId, folderId)
+ markMailboxRead({ getters, dispatch }, { accountId, mailboxId }) {
+ const mailbox = getters.getMailbox(mailboxId)
- if (folder.isUnified) {
- const findIndividual = findIndividualFolders(getters.getFolders, folder.specialRole)
- const individualFolders = findIndividual(getters.accounts)
+ if (mailbox.isUnified) {
+ const findIndividual = findIndividualMailboxes(getters.getMailboxes, mailbox.specialRole)
+ const individualMailboxes = findIndividual(getters.accounts)
return Promise.all(
- individualFolders.map((f) =>
- dispatch('markFolderRead', {
- accountId: f.accountId,
- folderId: f.id,
+ individualMailboxes.map((mb) =>
+ dispatch('markMailboxRead', {
+ accountId: mb.accountId,
+ mailboxId: mb.databaseId,
})
)
)
}
- return markFolderRead(accountId, folderId).then(
+ return markMailboxRead(mailboxId).then(
dispatch('syncEnvelopes', {
accountId,
- folderId,
+ mailboxId,
})
)
},
- fetchEnvelope({ commit, getters }, uuid) {
- const { accountId, folderId, uid } = parseUuid(uuid)
-
- const cached = getters.getEnvelope(accountId, folderId, uid)
+ fetchEnvelope({ commit, getters }, id) {
+ const cached = getters.getEnvelope(id)
if (cached) {
- logger.debug(`using cached value for envelope ${uuid}`)
+ logger.debug(`using cached value for envelope ${id}`)
return cached
}
- return fetchEnvelope(accountId, folderId, uid).then((envelope) => {
+ return fetchEnvelope(id).then((envelope) => {
// Only commit if not undefined (not found)
if (envelope) {
commit('addEnvelope', {
- accountId,
- folderId,
envelope,
})
}
// Always use the object from the store
- return getters.getEnvelope(accountId, folderId, uid)
+ return getters.getEnvelope(id)
})
},
- fetchEnvelopes({ state, commit, getters, dispatch }, { accountId, folderId, query }) {
- const folder = getters.getFolder(accountId, folderId)
+ fetchEnvelopes({ state, commit, getters, dispatch }, { mailboxId, query }) {
+ const mailbox = getters.getMailbox(mailboxId)
- if (folder.isUnified) {
+ if (mailbox.isUnified) {
const fetchIndividualLists = pipe(
- map((f) =>
+ map((mb) =>
dispatch('fetchEnvelopes', {
- accountId: f.accountId,
- folderId: f.id,
+ mailboxId: mb.databaseId,
query,
})
),
@@ -247,7 +240,7 @@ export default {
andThen(map(sliceToPage))
)
const fetchUnifiedEnvelopes = pipe(
- findIndividualFolders(getters.getFolders, folder.specialRole),
+ findIndividualMailboxes(getters.getMailboxes, mailbox.specialRole),
fetchIndividualLists,
andThen(combineEnvelopeLists),
andThen(sliceToPage),
@@ -255,8 +248,6 @@ export default {
tap(
map((envelope) =>
commit('addEnvelope', {
- accountId,
- folderId,
envelope,
query,
})
@@ -274,31 +265,29 @@ export default {
tap(
map((envelope) =>
commit('addEnvelope', {
- accountId,
- folderId,
query,
envelope,
})
)
)
)
- )(accountId, folderId, query, undefined, PAGE_SIZE)
+ )(mailboxId, query, undefined, PAGE_SIZE)
},
- fetchNextEnvelopePage({ commit, getters, dispatch }, { accountId, folderId, query, rec = true }) {
- const folder = getters.getFolder(accountId, folderId)
+ fetchNextEnvelopePage({ commit, getters, dispatch }, { mailboxId, query, rec = true }) {
+ const mailbox = getters.getMailbox(mailboxId)
- if (folder.isUnified) {
- const getIndivisualLists = curry((query, f) => getters.getEnvelopes(f.accountId, f.id, query))
- const individualCursor = curry((query, f) =>
- prop('dateInt', last(getters.getEnvelopes(f.accountId, f.id, query)))
+ if (mailbox.isUnified) {
+ const getIndivisualLists = curry((query, m) => getters.getEnvelopes(m.databaseId, query))
+ const individualCursor = curry((query, m) =>
+ prop('dateInt', last(getters.getEnvelopes(m.databaseId, query)))
)
- const cursor = individualCursor(query, folder)
+ const cursor = individualCursor(query, mailbox)
if (cursor === undefined) {
throw new Error('Unified list has no tail')
}
const nextLocalUnifiedEnvelopePage = pipe(
- findIndividualFolders(getters.getFolders, folder.specialRole),
+ findIndividualMailboxes(getters.getMailboxes, mailbox.specialRole),
map(getIndivisualLists(query)),
combineEnvelopeLists,
filter(
@@ -317,39 +306,35 @@ export default {
return nextPage.length < PAGE_SIZE || (c <= head(nextPage).dateInt && c >= last(nextPage).dateInt)
})
- const foldersToFetch = (accounts) =>
+ const mailboxesToFetch = (accounts) =>
pipe(
- findIndividualFolders(getters.getFolders, folder.specialRole),
+ findIndividualMailboxes(getters.getMailboxes, mailbox.specialRole),
filter(needsFetch(query, nextLocalUnifiedEnvelopePage(accounts)))
)(accounts)
- const fs = foldersToFetch(getters.accounts)
+ const mbs = mailboxesToFetch(getters.accounts)
- if (rec && fs.length) {
+ if (rec && mbs.length) {
return pipe(
- map((f) =>
+ map((mb) =>
dispatch('fetchNextEnvelopePage', {
- accountId: f.accountId,
- folderId: f.id,
+ mailboxId: mb.databaseId,
query,
})
),
Promise.all.bind(Promise),
andThen(() =>
dispatch('fetchNextEnvelopePage', {
- accountId,
- folderId,
+ mailboxId,
query,
rec: false,
})
)
- )(fs)
+ )(mbs)
}
const page = nextLocalUnifiedEnvelopePage(getters.accounts)
page.map((envelope) =>
commit('addEnvelope', {
- accountId,
- folderId,
query,
envelope,
})
@@ -357,29 +342,27 @@ export default {
return page
}
- const list = folder.envelopeLists[normalizedEnvelopeListId(query)]
+ const list = mailbox.envelopeLists[normalizedEnvelopeListId(query)]
if (list === undefined) {
- console.warn("envelope list is not defined, can't fetch next page", accountId, folderId, query)
+ console.warn("envelope list is not defined, can't fetch next page", mailboxId, query)
return Promise.resolve([])
}
const lastEnvelopeId = last(list)
if (typeof lastEnvelopeId === 'undefined') {
- console.error('folder is empty', list)
- return Promise.reject(new Error('Local folder has no envelopes, cannot determine cursor'))
+ console.error('mailbox is empty', list)
+ return Promise.reject(new Error('Local mailbox has no envelopes, cannot determine cursor'))
}
- const lastEnvelope = getters.getEnvelopeById(lastEnvelopeId)
+ const lastEnvelope = getters.getEnvelope(lastEnvelopeId)
if (typeof lastEnvelope === 'undefined') {
- return Promise.reject(new Error('Cannot find last envelope. Required for the folder cursor'))
+ return Promise.reject(new Error('Cannot find last envelope. Required for the mailbox cursor'))
}
- return fetchEnvelopes(accountId, folderId, query, lastEnvelope.dateInt, PAGE_SIZE).then((envelopes) => {
- logger.debug(`fetched ${envelopes.length} messages for the next page of ${accountId}:${folderId}`, {
+ return fetchEnvelopes(mailboxId, query, lastEnvelope.dateInt, PAGE_SIZE).then((envelopes) => {
+ logger.debug(`fetched ${envelopes.length} messages for the next page of mailbox ${mailboxId}`, {
envelopes,
})
envelopes.forEach((envelope) =>
commit('addEnvelope', {
- accountId,
- folderId,
query,
envelope,
})
@@ -387,22 +370,22 @@ export default {
return envelopes
})
},
- syncEnvelopes({ commit, getters, dispatch }, { accountId, folderId, query, init = false }) {
- const folder = getters.getFolder(accountId, folderId)
+ syncEnvelopes({ commit, getters, dispatch }, { mailboxId, query, init = false }) {
+ // TODO: use mailboxId
+ const mailbox = getters.getMailbox(mailboxId)
- if (folder.isUnified) {
+ if (mailbox.isUnified) {
return Promise.all(
getters.accounts
.filter((account) => !account.isUnified)
.map((account) =>
Promise.all(
getters
- .getFolders(account.id)
- .filter((f) => f.specialRole === folder.specialRole)
- .map((folder) =>
+ .getMailboxes(account.id)
+ .filter((mb) => mb.specialRole === mailbox.specialRole)
+ .map((mailbox) =>
dispatch('syncEnvelopes', {
- accountId: account.id,
- folderId: folder.id,
+ mailboxId: mailbox.databaseId,
query,
init,
})
@@ -410,19 +393,18 @@ export default {
)
)
)
- } else if (folder.isPriorityInbox && query === undefined) {
+ } else if (mailbox.isPriorityInbox && query === undefined) {
return Promise.all(
getters.accounts
.filter((account) => !account.isUnified)
.map((account) =>
Promise.all(
getters
- .getFolders(account.id)
- .filter((f) => f.specialRole === folder.specialRole)
- .map((folder) =>
+ .getMailboxes(account.id)
+ .filter((mb) => mb.specialRole === mailbox.specialRole)
+ .map((mailbox) =>
dispatch('syncEnvelopes', {
- accountId: account.id,
- folderId: folder.id,
+ mailboxId: mailbox.databaseId,
query,
init,
})
@@ -432,20 +414,17 @@ export default {
)
}
- const uids = getters.getEnvelopes(accountId, folderId, query).map((env) => env.uid)
-
- return syncEnvelopes(accountId, folderId, uids, query, init)
+ const ids = getters.getEnvelopes(mailboxId, query).map((env) => env.databaseId)
+ return syncEnvelopes(mailbox.accountId, mailboxId, ids, query, init)
.then((syncData) => {
- const unifiedFolder = getters.getUnifiedFolder(folder.specialRole)
+ const unifiedMailbox = getters.getUnifiedMailbox(mailbox.specialRole)
syncData.newMessages.forEach((envelope) => {
commit('addEnvelope', {
- accountId,
- folderId,
envelope,
query,
})
- if (unifiedFolder) {
+ if (unifiedMailbox) {
commit('updateEnvelope', {
envelope,
})
@@ -456,11 +435,9 @@ export default {
envelope,
})
})
- syncData.vanishedMessages.forEach((uid) => {
+ syncData.vanishedMessages.forEach((id) => {
commit('removeEnvelope', {
- accountId,
- folderId,
- uid,
+ id,
})
// Already removed from unified inbox
})
@@ -471,11 +448,11 @@ export default {
return matchError(error, {
[SyncIncompleteError.getName()]() {
console.warn('(initial) sync is incomplete, retriggering')
- return dispatch('syncEnvelopes', { accountId, folderId, query, init })
+ return dispatch('syncEnvelopes', { mailboxId, query, init })
},
[MailboxLockedError.getName()](error) {
logger.info('Sync failed because the mailbox is locked, retriggering', { error })
- return wait(1500).then(() => dispatch('syncEnvelopes', { accountId, folderId, query, init }))
+ return wait(1500).then(() => dispatch('syncEnvelopes', { mailboxId, query, init }))
},
default(error) {
console.error('Could not sync envelopes: ' + error.message, error)
@@ -489,22 +466,20 @@ export default {
.filter((a) => !a.isUnified)
.map((account) => {
return Promise.all(
- getters.getFolders(account.id).map(async(folder) => {
- if (folder.specialRole !== 'inbox') {
+ getters.getMailboxes(account.id).map(async(mailbox) => {
+ if (mailbox.specialRole !== 'inbox') {
return
}
- const list = folder.envelopeLists[normalizedEnvelopeListId(undefined)]
+ const list = mailbox.envelopeLists[normalizedEnvelopeListId(undefined)]
if (list === undefined) {
await dispatch('fetchEnvelopes', {
- accountId: account.id,
- folderId: folder.id,
+ mailboxId: mailbox.databaseId,
})
}
return await dispatch('syncEnvelopes', {
- accountId: account.id,
- folderId: folder.id,
+ mailboxId: mailbox.databaseId,
})
})
)
@@ -520,19 +495,17 @@ export default {
logger.info('updating priority inbox')
for (const query of ['is:important not:starred', 'is:starred not:important', 'not:starred not:important']) {
logger.info("sync'ing priority inbox section", { query })
- const folder = getters.getFolder(UNIFIED_ACCOUNT_ID, UNIFIED_INBOX_ID)
- const list = folder.envelopeLists[normalizedEnvelopeListId(query)]
+ const mailbox = getters.getMailbox(UNIFIED_INBOX_ID)
+ const list = mailbox.envelopeLists[normalizedEnvelopeListId(query)]
if (list === undefined) {
await dispatch('fetchEnvelopes', {
- accountId: UNIFIED_ACCOUNT_ID,
- folderId: UNIFIED_INBOX_ID,
+ mailboxId: UNIFIED_INBOX_ID,
query,
})
}
await dispatch('syncEnvelopes', {
- accountId: UNIFIED_ACCOUNT_ID,
- folderId: UNIFIED_INBOX_ID,
+ mailboxId: UNIFIED_INBOX_ID,
query,
})
}
@@ -549,7 +522,7 @@ export default {
value: !oldState,
})
- setEnvelopeFlag(envelope.accountId, envelope.folderId, envelope.uid, 'flagged', !oldState).catch((e) => {
+ setEnvelopeFlag(envelope.databaseId, 'flagged', !oldState).catch((e) => {
console.error('could not toggle message flagged state', e)
// Revert change
@@ -569,7 +542,7 @@ export default {
value: !oldState,
})
- setEnvelopeFlag(envelope.accountId, envelope.folderId, envelope.uid, 'important', !oldState).catch((e) => {
+ setEnvelopeFlag(envelope.databaseId, 'important', !oldState).catch((e) => {
console.error('could not toggle message important state', e)
// Revert change
@@ -589,7 +562,7 @@ export default {
value: !oldState,
})
- setEnvelopeFlag(envelope.accountId, envelope.folderId, envelope.uid, 'seen', !oldState).catch((e) => {
+ setEnvelopeFlag(envelope.databaseId, 'seen', !oldState).catch((e) => {
console.error('could not toggle message seen state', e)
// Revert change
@@ -609,7 +582,7 @@ export default {
value: !oldState,
})
- setEnvelopeFlag(envelope.accountId, envelope.folderId, envelope.uid, 'junk', !oldState).catch((e) => {
+ setEnvelopeFlag(envelope.databaseId, 'junk', !oldState).catch((e) => {
console.error('could not toggle message junk state', e)
// Revert change
@@ -629,7 +602,7 @@ export default {
value: favFlag,
})
- setEnvelopeFlag(envelope.accountId, envelope.folderId, envelope.uid, 'flagged', favFlag).catch((e) => {
+ setEnvelopeFlag(envelope.databaseId, 'flagged', favFlag).catch((e) => {
console.error('could not favorite/unfavorite message ' + envelope.uid, e)
// Revert change
@@ -649,7 +622,7 @@ export default {
value: seenFlag,
})
- setEnvelopeFlag(envelope.accountId, envelope.folderId, envelope.uid, 'unseen', seenFlag).catch((e) => {
+ setEnvelopeFlag(envelope.databaseId, 'unseen', seenFlag).catch((e) => {
console.error('could not mark message ' + envelope.uid + ' seen/unseen', e)
// Revert change
@@ -660,51 +633,34 @@ export default {
})
})
},
- fetchMessage({ commit }, uuid) {
- const { accountId, folderId, uid } = parseUuid(uuid)
- return fetchMessage(accountId, folderId, uid).then((message) => {
- // Only commit if not undefined (not found)
- if (message) {
- commit('addMessage', {
- accountId,
- folderId,
- message,
- })
- }
+ async fetchMessage({ getters, commit }, id) {
+ const message = await fetchMessage(id)
+ // Only commit if not undefined (not found)
+ if (message) {
+ commit('addMessage', {
+ message,
+ })
+ }
- return message
- })
- },
- replaceDraft({ getters, commit }, { draft, uid, data }) {
- commit('updateDraft', {
- draft,
- data,
- newUid: uid,
- })
+ return message
},
- deleteMessage({ getters, commit }, { accountId, folderId, uid }) {
- commit('removeEnvelope', { accountId, folderId, uid })
-
- return deleteMessage(accountId, folderId, uid)
- .then(() => {
- const folder = getters.getFolder(accountId, folderId)
- if (!folder) {
- logger.error('could not find folder', { accountId, folderId })
- return
- }
- commit('removeMessage', { accountId, folder, uid })
- console.debug('message removed')
- })
- .catch((err) => {
- console.error('could not delete message', err)
- const envelope = getters.getEnvelope(accountId, folderId, uid)
- if (envelope) {
- commit('addEnvelope', { accountId, folderId, envelope })
- } else {
- logger.error('could not find envelope', { accountId, folderId, uid })
- }
- throw err
- })
+ async deleteMessage({ getters, commit }, { id }) {
+ commit('removeEnvelope', { id })
+
+ try {
+ await deleteMessage(id)
+ commit('removeMessage', { id })
+ console.debug('message removed')
+ } catch (err) {
+ console.error('could not delete message', err)
+ const envelope = getters.getEnvelope(id)
+ if (envelope) {
+ commit('addEnvelope', { envelope })
+ } else {
+ logger.error('could not find envelope', { id })
+ }
+ throw err
+ }
},
async createAlias({ commit }, { account, aliasToAdd }) {
const alias = await createAlias(account, aliasToAdd)
diff --git a/src/store/constants.js b/src/store/constants.js
index ca08968b1..ff683a2e4 100644
--- a/src/store/constants.js
+++ b/src/store/constants.js
@@ -18,10 +18,7 @@
* 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/>.
*/
-import { normalizedFolderId } from './normalization'
export const UNIFIED_ACCOUNT_ID = 0
-export const UNIFIED_INBOX_ID = btoa('inbox')
-export const UNIFIED_INBOX_UID = normalizedFolderId(UNIFIED_ACCOUNT_ID, UNIFIED_INBOX_ID)
-export const PRIORITY_INBOX_ID = btoa('priority')
-export const PRIORITY_INBOX_UID = UNIFIED_ACCOUNT_ID + '-' + PRIORITY_INBOX_ID
+export const UNIFIED_INBOX_ID = 'unified'
+export const PRIORITY_INBOX_ID = 'priority'
diff --git a/src/store/getters.js b/src/store/getters.js
index b6e6e29de..752840857 100644
--- a/src/store/getters.js
+++ b/src/store/getters.js
@@ -22,7 +22,7 @@
import { defaultTo, head } from 'ramda'
import { UNIFIED_ACCOUNT_ID } from './constants'
-import { normalizedEnvelopeListId, normalizedFolderId, normalizedMessageId } from './normalization'
+import { normalizedEnvelopeListId } from './normalization'
export const getters = {
getPreference: (state) => (key, def) => {
@@ -34,35 +34,32 @@ export const getters = {
accounts: (state) => {
return state.accountList.map((id) => state.accounts[id])
},
- getFolder: (state) => (accountId, folderId) => {
- return state.folders[normalizedFolderId(accountId, folderId)]
+ getMailbox: (state) => (id) => {
+ return state.mailboxes[id]
},
- getFolders: (state) => (accountId) => {
- return state.accounts[accountId].folders.map((folderId) => state.folders[folderId])
+ getMailboxes: (state) => (accountId) => {
+ return state.accounts[accountId].mailboxes.map((id) => state.mailboxes[id])
},
- getSubfolders: (state, getters) => (accountId, folderId) => {
- const folder = getters.getFolder(accountId, folderId)
+ getSubMailboxes: (state, getters) => (id) => {
+ const mailbox = getters.getMailbox(id)
- return folder.folders.map((id) => state.folders[id])
+ return mailbox.mailboxes.map((id) => state.mailboxes[id])
},
- getUnifiedFolder: (state) => (specialRole) => {
+ getUnifiedMailbox: (state) => (specialRole) => {
return head(
- state.accounts[UNIFIED_ACCOUNT_ID].folders
- .map((folderId) => state.folders[folderId])
- .filter((folder) => folder.specialRole === specialRole)
+ state.accounts[UNIFIED_ACCOUNT_ID].mailboxes
+ .map((id) => state.mailboxes[id])
+ .filter((mailbox) => mailbox.specialRole === specialRole)
)
},
- getEnvelope: (state) => (accountId, folderId, uid) => {
- return state.envelopes[normalizedMessageId(accountId, folderId, uid)]
- },
- getEnvelopeById: (state) => (id) => {
+ getEnvelope: (state) => (id) => {
return state.envelopes[id]
},
- getEnvelopes: (state, getters) => (accountId, folderId, query) => {
- const list = getters.getFolder(accountId, folderId).envelopeLists[normalizedEnvelopeListId(query)] || []
+ getEnvelopes: (state, getters) => (mailboxId, query) => {
+ const list = getters.getMailbox(mailboxId).envelopeLists[normalizedEnvelopeListId(query)] || []
return list.map((msgId) => state.envelopes[msgId])
},
- getMessage: (state) => (accountId, folderId, uid) => {
- return state.messages[normalizedMessageId(accountId, folderId, uid)]
+ getMessage: (state) => (id) => {
+ return state.messages[id]
},
}
diff --git a/src/store/index.js b/src/store/index.js
index df0915e25..35af89ce6 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -25,9 +25,7 @@ import Vuex from 'vuex'
import {
UNIFIED_ACCOUNT_ID,
UNIFIED_INBOX_ID,
- UNIFIED_INBOX_UID,
PRIORITY_INBOX_ID,
- PRIORITY_INBOX_UID,
} from './constants'
import actions from './actions'
import { getters } from './getters'
@@ -44,7 +42,7 @@ export default new Vuex.Store({
id: UNIFIED_ACCOUNT_ID,
accountId: UNIFIED_ACCOUNT_ID,
isUnified: true,
- folders: [PRIORITY_INBOX_UID, UNIFIED_INBOX_UID],
+ mailboxes: [PRIORITY_INBOX_ID, UNIFIED_INBOX_ID],
collapsed: false,
emailAddress: '',
name: '',
@@ -52,27 +50,29 @@ export default new Vuex.Store({
},
},
accountList: [UNIFIED_ACCOUNT_ID],
- folders: {
- [UNIFIED_INBOX_UID]: {
+ mailboxes: {
+ [UNIFIED_INBOX_ID]: {
id: UNIFIED_INBOX_ID,
+ databaseId: UNIFIED_INBOX_ID,
accountId: 0,
attributes: ['\\subscribed'],
isUnified: true,
specialUse: ['inbox'],
specialRole: 'inbox',
unread: 0,
- folders: [],
+ mailboxes: [],
envelopeLists: {},
},
- [PRIORITY_INBOX_UID]: {
+ [PRIORITY_INBOX_ID]: {
id: PRIORITY_INBOX_ID,
+ databaseId: PRIORITY_INBOX_ID,
accountId: 0,
attributes: ['\\subscribed'],
isPriorityInbox: true,
specialUse: ['inbox'],
specialRole: 'inbox',
unread: 0,
- folders: [],
+ mailboxes: [],
envelopeLists: {},
},
},
diff --git a/src/store/mutations.js b/src/store/mutations.js
index c2f20bfe0..64e57b303 100644
--- a/src/store/mutations.js
+++ b/src/store/mutations.js
@@ -25,16 +25,15 @@ import Vue from 'vue'
import { buildMailboxHierarchy } from '../imap/MailboxHierarchy'
import { havePrefix } from '../imap/MailboxPrefix'
-import { normalizedFolderId, normalizedMessageId, normalizedEnvelopeListId } from './normalization'
import { sortMailboxes } from '../imap/MailboxSorter'
+import { normalizedEnvelopeListId } from './normalization'
import { UNIFIED_ACCOUNT_ID } from './constants'
-const addFolderToState = (state, account) => (folder) => {
- const id = normalizedFolderId(account.id, folder.id)
- folder.accountId = account.id
- folder.envelopeLists = {}
- Vue.set(state.folders, id, folder)
- return id
+const addMailboxToState = (state, account) => (mailbox) => {
+ mailbox.accountId = account.id
+ mailbox.envelopeLists = {}
+ Vue.set(state.mailboxes, mailbox.databaseId, mailbox)
+ return mailbox.databaseId
}
const sortAccounts = (accounts) => {
@@ -55,16 +54,16 @@ export default {
sortAccounts(state.accountList.concat([account.id]).map((id) => state.accounts[id])).map((a) => a.id)
)
- // Save the folders to the store, but only keep IDs in the account's folder list
- const folders = buildMailboxHierarchy(sortMailboxes(account.folders || []), havePrefix(account.folders))
- Vue.set(account, 'folders', [])
- const addToState = addFolderToState(state, account)
- folders.forEach((folder) => {
- // Add all folders (including subfolders to state, but only toplevel to account
- const id = addToState(folder)
- Vue.set(folder, 'folders', folder.folders.map(addToState))
+ // Save the mailboxes to the store, but only keep IDs in the account's mailboxes list
+ const mailboxes = buildMailboxHierarchy(sortMailboxes(account.mailboxes), havePrefix(account.mailboxes))
+ Vue.set(account, 'mailboxes', [])
+ const addToState = addMailboxToState(state, account)
+ mailboxes.forEach((mailbox) => {
+ // Add all mailboxes (including submailboxes to state, but only toplevel to account
+ const id = addToState(mailbox)
+ Vue.set(mailbox, 'mailboxes', mailbox.mailboxes.map(addToState))
- account.folders.push(id)
+ account.mailboxes.push(id)
})
},
editAccount(state, account) {
@@ -87,61 +86,68 @@ export default {
expandAccount(state, accountId) {
state.accounts[accountId].collapsed = false
},
- addFolder(state, { account, folder }) {
+ addMailbox(state, { account, mailbox }) {
// Flatten the existing ones before updating the hierarchy
- const existing = account.folders.map((id) => state.folders[id])
- existing.forEach((folder) => {
- if (!folder.folders) {
+ const existing = account.mailboxes.map((id) => state.mailboxes[id])
+ existing.forEach((mailbox) => {
+ if (!mailbox.mailboxes) {
return
}
- folder.folders.map((id) => existing.push(state.folders[id]))
- folder.folders = []
+ mailbox.mailboxes.map((id) => existing.push(state.mailboxes[id]))
+ mailbox.mailboxes = []
})
- // Save the folders to the store, but only keep IDs in the account's folder list
- existing.push(folder)
- const folders = buildMailboxHierarchy(sortMailboxes(existing), havePrefix(existing))
- Vue.set(account, 'folders', [])
- const addToState = addFolderToState(state, account)
- folders.forEach((folder) => {
- // Add all folders (including subfolders to state, but only toplevel to account
- const id = addToState(folder)
- Vue.set(folder, 'folders', folder.folders.map(addToState))
+ // Save the mailboxes to the store, but only keep IDs in the account's mailboxes list
+ existing.push(mailbox)
+ const mailboxes = buildMailboxHierarchy(sortMailboxes(existing), havePrefix(existing))
+ Vue.set(account, 'mailboxes', [])
+ const addToState = addMailboxToState(state, account)
+ mailboxes.forEach((mailbox) => {
+ // Add all mailboxes (including submailboxes to state, but only toplevel to account
+ const id = addToState(mailbox)
+ Vue.set(mailbox, 'mailboxes', mailbox.mailboxes.map(addToState))
- account.folders.push(id)
+ account.mailboxes.push(id)
})
},
- removeFolder(state, { accountId, folderId }) {
- const account = state.accounts[accountId]
- const id = normalizedFolderId(accountId, folderId)
- Vue.delete(state.folders, id)
- account.folders = account.folders.filter((fId) => fId !== id)
- account.folders.forEach((fId) => {
- const folder = state.folders[fId]
- if (folder.folders) {
- folder.folders = folder.folders.filter((fId) => fId !== id)
+ removeMailbox(state, { id }) {
+ const mailbox = state.mailboxes[id]
+ if (mailbox === undefined) {
+ throw new Error(`Mailbox ${id} does not exist`)
+ }
+ const account = state.accounts[mailbox.accountId]
+ if (account === undefined) {
+ throw new Error(`Account ${mailbox.accountId} of mailbox ${id} is unknown`)
+ }
+ Vue.delete(state.mailboxes, id)
+ account.mailboxes = account.mailboxes.filter((mbId) => mbId !== id)
+ account.mailboxes.forEach((fId) => {
+ const mailbox = state.mailboxes[fId]
+ if (mailbox.mailboxes) {
+ mailbox.mailboxes = mailbox.mailboxes.filter((mbId) => mbId !== id)
}
})
},
- addEnvelope(state, { accountId, folderId, query, envelope }) {
- const folder = state.folders[normalizedFolderId(accountId, folderId)]
- Vue.set(state.envelopes, envelope.uuid, envelope)
+ addEnvelope(state, { query, envelope }) {
+ const mailbox = state.mailboxes[envelope.mailboxId]
+ Vue.set(state.envelopes, envelope.databaseId, envelope)
+ Vue.set(envelope, 'accountId', mailbox.accountId)
const listId = normalizedEnvelopeListId(query)
- const existing = folder.envelopeLists[listId] || []
- const uuidToDateInt = (uuid) => state.envelopes[uuid].dateInt
- const sortedUniqByDateInt = sortedUniqBy(uuidToDateInt)
- const orderByDateInt = orderBy(uuidToDateInt, 'desc')
- Vue.set(folder.envelopeLists, listId, sortedUniqByDateInt(orderByDateInt(existing.concat([envelope.uuid]))))
+ const existing = mailbox.envelopeLists[listId] || []
+ const idToDateInt = (id) => state.envelopes[id].dateInt
+ const sortedUniqByDateInt = sortedUniqBy(idToDateInt)
+ const orderByDateInt = orderBy(idToDateInt, 'desc')
+ Vue.set(mailbox.envelopeLists, listId, sortedUniqByDateInt(orderByDateInt(existing.concat([envelope.databaseId]))))
const unifiedAccount = state.accounts[UNIFIED_ACCOUNT_ID]
- unifiedAccount.folders
- .map((fId) => state.folders[fId])
- .filter((f) => f.specialRole && f.specialRole === folder.specialRole)
- .forEach((folder) => {
- const existing = folder.envelopeLists[listId] || []
+ unifiedAccount.mailboxes
+ .map((mbId) => state.mailboxes[mbId])
+ .filter((mb) => mb.specialRole && mb.specialRole === mailbox.specialRole)
+ .forEach((mailbox) => {
+ const existing = mailbox.envelopeLists[listId] || []
Vue.set(
- folder.envelopeLists,
+ mailbox.envelopeLists,
listId,
- sortedUniqByDateInt(orderByDateInt(existing.concat([envelope.uuid])))
+ sortedUniqByDateInt(orderByDateInt(existing.concat([envelope.databaseId])))
)
})
},
@@ -155,82 +161,56 @@ export default {
flagEnvelope(state, { envelope, flag, value }) {
envelope.flags[flag] = value
},
- removeEnvelope(state, { accountId, folderId, uid }) {
- const folder = state.folders[normalizedFolderId(accountId, folderId)]
- for (const listId in folder.envelopeLists) {
- if (!Object.hasOwnProperty.call(folder.envelopeLists, listId)) {
+ removeEnvelope(state, { id }) {
+ const envelope = state.envelopes[id]
+ if (!envelope) {
+ console.warn('envelope ' + id + ' is unknown, can\'t remove it')
+ return
+ }
+ const mailbox = state.mailboxes[envelope.mailboxId]
+ for (const listId in mailbox.envelopeLists) {
+ if (!Object.hasOwnProperty.call(mailbox.envelopeLists, listId)) {
continue
}
- const list = folder.envelopeLists[listId]
- const idx = list.indexOf(normalizedMessageId(accountId, folderId, uid))
+ const list = mailbox.envelopeLists[listId]
+ const idx = list.indexOf(id)
if (idx < 0) {
continue
}
- console.debug('envelope removed from mailbox', accountId, folder.id, uid, listId)
+ console.debug('envelope ' + id + ' removed from mailbox list ' + listId)
list.splice(idx, 1)
}
- state.accounts[UNIFIED_ACCOUNT_ID].folders
- .map((fId) => state.folders[fId])
- .filter((f) => f.specialRole && f.specialRole === folder.specialRole)
- .forEach((folder) => {
- for (const listId in folder.envelopeLists) {
- if (!Object.hasOwnProperty.call(folder.envelopeLists, listId)) {
+ state.accounts[UNIFIED_ACCOUNT_ID].mailboxes
+ .map((mailboxId) => state.mailboxes[mailboxId])
+ .filter((mb) => mb.specialRole && mb.specialRole === mailbox.specialRole)
+ .forEach((mailbox) => {
+ for (const listId in mailbox.envelopeLists) {
+ if (!Object.hasOwnProperty.call(mailbox.envelopeLists, listId)) {
continue
}
- const list = folder.envelopeLists[listId]
- const idx = list.indexOf(normalizedMessageId(accountId, folderId, uid))
+ const list = mailbox.envelopeLists[listId]
+ const idx = list.indexOf(id)
if (idx < 0) {
console.warn(
'envelope does not exist in unified mailbox',
- accountId,
- folder.id,
- uid,
+ mailbox.databaseId,
+ id,
listId,
list
)
continue
}
- console.debug('envelope removed from unified mailbox', accountId, folder.id, uid, listId)
+ console.debug('envelope removed from unified mailbox', mailbox.databaseId, id)
list.splice(idx, 1)
}
})
},
- addMessage(state, { accountId, folderId, message }) {
- const uuid = normalizedMessageId(accountId, folderId, message.uid)
- message.accountId = accountId
- message.folderId = folderId
- message.uuid = uuid
- Vue.set(state.messages, uuid, message)
- },
- updateDraft(state, { draft, data, newUid }) {
- // Update draft's UID
- const oldUid = draft.uid
- const uid = normalizedMessageId(draft.accountId, draft.folderId, newUid)
- console.debug('saving draft as UID ' + uid)
- draft.uid = uid
-
- // TODO: strategy to keep the full draft object in sync, not just the visible
- // changes
- draft.subject = data.subject
-
- // Update ref in folder's envelope list
- const envs = state.folders[normalizedFolderId(draft.accountId, draft.folderId)].envelopes
- const idx = envs.indexOf(oldUid)
- if (idx < 0) {
- console.warn('not replacing draft ' + oldUid + ' in envelope list because it did not exist')
- } else {
- envs[idx] = uid
- }
-
- // Move message/envelope objects to new keys
- Vue.delete(state.envelopes, oldUid)
- Vue.delete(state.messages, oldUid)
- Vue.set(state.envelopes, uid, draft)
- Vue.set(state.messages, uid, draft)
- },
- removeMessage(state, { accountId, folderId, uid }) {
- Vue.delete(state.messages, normalizedMessageId(accountId, folderId, uid))
+ addMessage(state, { message }) {
+ Vue.set(state.messages, message.databaseId, message)
+ },
+ removeMessage(state, { id }) {
+ Vue.delete(state.messages, id)
},
createAlias(state, { account, alias }) {
account.aliases.push(alias)
diff --git a/src/store/normalization.js b/src/store/normalization.js
index 1da1a671c..6a5ab0439 100644
--- a/src/store/normalization.js
+++ b/src/store/normalization.js
@@ -19,14 +19,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import { curry, defaultTo } from 'ramda'
-
-export const normalizedFolderId = curry((accountId, folderId) => {
- return `${accountId}-${folderId}`
-})
-
-export const normalizedMessageId = curry((accountId, folderId, uid) => {
- return `${accountId}-${folderId}-${uid}`
-})
+import { defaultTo } from 'ramda'
export const normalizedEnvelopeListId = defaultTo('')
diff --git a/src/tests/setup.js b/src/tests/setup.js
index 9245898f7..1862490f1 100644
--- a/src/tests/setup.js
+++ b/src/tests/setup.js
@@ -45,4 +45,5 @@ global.OC = {
return string
},
},
+ isUserAdmin: () => false,
}
diff --git a/src/tests/unit/components/Address.spec.js b/src/tests/unit/components/Address.spec.js
index 9fbcb4010..2ea954636 100644
--- a/src/tests/unit/components/Address.spec.js
+++ b/src/tests/unit/components/Address.spec.js
@@ -18,8 +18,7 @@ describe('Address', () => {
it('renders', () => {
$route.params = {
- accountId: 1,
- folderId: 'folder1',
+ mailboxId: 12,
}
const addr = shallowMount(Address, {
localVue,
@@ -33,8 +32,7 @@ describe('Address', () => {
})
expect(addr.vm.newMessageRoute.name).to.equal('message')
- expect(addr.vm.newMessageRoute.params.accountId).to.equal(1)
- expect(addr.vm.newMessageRoute.params.folderId).to.equal('folder1')
+ expect(addr.vm.newMessageRoute.params.mailboxId).to.equal(12)
expect(addr.vm.newMessageRoute.query.to).to.equal('user@domain.com')
})
})
diff --git a/src/tests/unit/i18n/MailboxTranslator.spec.js b/src/tests/unit/i18n/MailboxTranslator.spec.js
index 6f2182d06..450592411 100644
--- a/src/tests/unit/i18n/MailboxTranslator.spec.js
+++ b/src/tests/unit/i18n/MailboxTranslator.spec.js
@@ -23,24 +23,24 @@ import { translate } from '../../../i18n/MailboxTranslator'
describe('MailboxTranslator', () => {
it('translates the inbox', () => {
- const folder = {
+ const mailbox = {
id: btoa('INBOX'),
specialUse: ['inbox'],
}
- const name = translate(folder)
+ const name = translate(mailbox)
expect(name).to.equal('Inbox')
})
it('does not translate an arbitrary mailbox', () => {
- const folder = {
+ const mailbox = {
id: btoa('Newsletters'),
displayName: 'Newsletters',
specialUse: [],
}
- const name = translate(folder)
+ const name = translate(mailbox)
expect(name).to.equal('Newsletters')
})
diff --git a/src/tests/unit/imap/MailboxHierarchy.spec.js b/src/tests/unit/imap/MailboxHierarchy.spec.js
index 8fea48911..29b35381f 100644
--- a/src/tests/unit/imap/MailboxHierarchy.spec.js
+++ b/src/tests/unit/imap/MailboxHierarchy.spec.js
@@ -47,12 +47,12 @@ describe('mailboxHierarchyBuilder', () => {
{
id: btoa('INBOX'),
delimiter: '.',
- folders: [],
+ mailboxes: [],
},
{
id: btoa('Sent'),
delimiter: '.',
- folders: [],
+ mailboxes: [],
},
])
})
@@ -74,11 +74,11 @@ describe('mailboxHierarchyBuilder', () => {
{
id: btoa('Archive'),
delimiter: '.',
- folders: [
+ mailboxes: [
{
id: btoa('Archive.Sent'),
delimiter: '.',
- folders: [],
+ mailboxes: [],
},
],
},
@@ -106,23 +106,23 @@ describe('mailboxHierarchyBuilder', () => {
{
id: btoa('Archive'),
delimiter: '.',
- folders: [
+ mailboxes: [
{
id: btoa('Archive.Sent'),
delimiter: '.',
- folders: [],
+ mailboxes: [],
},
{
id: btoa('Archive.Sent.Old'),
delimiter: '.',
- folders: [],
+ mailboxes: [],
},
],
},
])
})
- it('does not use the flagged inbox as subfolder of inbox', () => {
+ it('does not use the flagged inbox as submailbox of inbox', () => {
const mb1 = {
id: btoa('INBOX'),
delimiter: '/',
@@ -143,17 +143,17 @@ describe('mailboxHierarchyBuilder', () => {
{
id: btoa('INBOX'),
delimiter: '/',
- folders: [],
+ mailboxes: [],
},
{
id: btoa('INBOX/FLAGGED'),
delimiter: '/',
- folders: [],
+ mailboxes: [],
},
{
id: btoa('Archive'),
delimiter: '/',
- folders: [],
+ mailboxes: [],
},
])
})
@@ -175,11 +175,11 @@ describe('mailboxHierarchyBuilder', () => {
{
id: btoa('INBOX.Archive'),
delimiter: '.',
- folders: [
+ mailboxes: [
{
id: btoa('INBOX.Archive.Sent'),
delimiter: '.',
- folders: [],
+ mailboxes: [],
},
],
},
diff --git a/src/tests/unit/store/actions.spec.js b/src/tests/unit/store/actions.spec.js
index 4e00fdc9f..9764c8c30 100644
--- a/src/tests/unit/store/actions.spec.js
+++ b/src/tests/unit/store/actions.spec.js
@@ -26,14 +26,11 @@ import orderBy from 'lodash/fp/orderBy'
import actions from '../../../store/actions'
import * as MessageService from '../../../service/MessageService'
import * as NotificationService from '../../../service/NotificationService'
-import { normalizedMessageId } from '../../../store/normalization'
import { UNIFIED_ACCOUNT_ID, UNIFIED_INBOX_ID } from '../../../store/constants'
-const mockEnvelope = curry((accountId, folderId, uid) => ({
- accountId,
- folderId,
+const mockEnvelope = curry((mailboxId, uid) => ({
+ mailboxId,
uid,
- uuid: normalizedMessageId(accountId, folderId, uid),
dateInt: uid * 10000,
}))
@@ -46,9 +43,9 @@ describe('Vuex store actions', () => {
dispatch: sinon.stub(),
getters: {
accounts: [],
- getFolder: sinon.stub(),
- getFolders: sinon.stub(),
- getEnvelopeById: sinon.stub(),
+ getMailbox: sinon.stub(),
+ getMailboxes: sinon.stub(),
+ getEnvelope: sinon.stub(),
getEnvelopes: sinon.stub(),
},
}
@@ -59,13 +56,12 @@ describe('Vuex store actions', () => {
})
it('combines unified inbox even if no inboxes are present', () => {
- context.getters.getFolder.returns({
+ context.getters.getMailbox.returns({
isUnified: true,
})
const envelopes = actions.fetchEnvelopes(context, {
- accountId: UNIFIED_ACCOUNT_ID,
- folderId: UNIFIED_INBOX_ID,
+ mailboxId: UNIFIED_INBOX_ID,
})
expect(envelopes).to.be.empty
@@ -74,60 +70,58 @@ describe('Vuex store actions', () => {
it('creates a unified page from one mailbox', async() => {
context.getters.accounts.push({
id: 13,
- accountId: 13,
})
- context.getters.getFolder.withArgs(UNIFIED_ACCOUNT_ID, UNIFIED_INBOX_ID).returns({
+ context.getters.getMailbox.withArgs(UNIFIED_INBOX_ID).returns({
isUnified: true,
specialRole: 'inbox',
+ databaseId: UNIFIED_INBOX_ID,
})
- context.getters.getFolders.withArgs(13).returns([
+ context.getters.getMailboxes.withArgs(13).returns([
{
id: 'INBOX',
+ databaseId: 21,
accountId: 13,
specialRole: 'inbox',
},
{
id: 'Drafts',
+ databaseId: 22,
accountId: 13,
specialRole: 'draft',
},
])
context.dispatch
.withArgs('fetchEnvelopes', {
- accountId: 13,
- folderId: 'INBOX',
+ mailboxId: 21,
query: undefined,
})
.returns([
{
- accountId: 13,
- folderId: 'INBOX',
- uid: '13-INBOX-123',
+ databaseId: 123,
+ mailboxId: 21,
+ uid: 321,
subject: 'msg1',
},
])
const envelopes = await actions.fetchEnvelopes(context, {
- accountId: UNIFIED_ACCOUNT_ID,
- folderId: UNIFIED_INBOX_ID,
+ mailboxId: UNIFIED_INBOX_ID,
})
expect(envelopes).to.deep.equal([
{
- accountId: 13,
- folderId: 'INBOX',
- uid: '13-INBOX-123',
+ databaseId: 123,
+ mailboxId: 21,
+ uid: 321,
subject: 'msg1',
},
])
expect(context.dispatch).to.have.been.calledOnce
expect(context.commit).to.have.been.calledWith('addEnvelope', {
- accountId: UNIFIED_ACCOUNT_ID,
- folderId: UNIFIED_INBOX_ID,
envelope: {
- accountId: 13,
- folderId: 'INBOX',
- uid: '13-INBOX-123',
+ databaseId: 123,
+ mailboxId: 21,
+ uid: 321,
subject: 'msg1',
},
query: undefined,
@@ -136,26 +130,25 @@ describe('Vuex store actions', () => {
it('fetches the next individual page', async() => {
context.getters.accounts.push({
- id: 13,
accountId: 13,
})
- context.getters.getFolder.withArgs(13, 'INBOX').returns({
- id: 'INBOX',
+ context.getters.getMailbox.withArgs(13).returns({
+ name: 'INBOX',
+ databaseId: 11,
accountId: 13,
specialRole: 'inbox',
envelopeLists: {
- '': reverse(range(21, 40).map(normalizedMessageId(13, 'INBOX'))),
+ '': reverse(range(21, 40)),
},
})
- context.getters.getEnvelopeById
- .withArgs(normalizedMessageId(13, 'INBOX', 21))
- .returns(mockEnvelope(13, 'INBOX', 1))
+ context.getters.getEnvelope
+ .withArgs(21)
+ .returns(mockEnvelope(11, 1))
sinon.stub(MessageService, 'fetchEnvelopes').returns(
Promise.resolve(
reverse(
range(1, 21).map((n) => ({
uid: n,
- uuid: normalizedMessageId(13, 'INBOX', n),
dateInt: n * 10000,
}))
)
@@ -163,15 +156,13 @@ describe('Vuex store actions', () => {
)
const page = await actions.fetchNextEnvelopePage(context, {
- accountId: 13,
- folderId: 'INBOX',
+ mailboxId: 13,
})
expect(page).to.deep.equal(
reverse(
range(1, 21).map((n) => ({
uid: n,
- uuid: normalizedMessageId(13, 'INBOX', n),
dateInt: n * 10000,
}))
)
@@ -186,57 +177,56 @@ describe('Vuex store actions', () => {
const msgs2 = reverse(range(5, 35))
context.getters.accounts.push({
id: 13,
- accountId: 13,
})
context.getters.accounts.push({
id: 26,
- accountId: 26,
})
- context.getters.getFolder.withArgs(UNIFIED_ACCOUNT_ID, UNIFIED_INBOX_ID).returns({
+ context.getters.getMailbox.withArgs(UNIFIED_INBOX_ID).returns({
isUnified: true,
specialRole: 'inbox',
accountId: UNIFIED_ACCOUNT_ID,
- id: UNIFIED_INBOX_ID,
+ databaseId: UNIFIED_INBOX_ID,
})
- context.getters.getFolders.withArgs(13).returns([
+ context.getters.getMailboxes.withArgs(13).returns([
{
- id: 'INBOX',
- accountId: 13,
+ name: 'INBOX',
+ databaseId: 11,
specialRole: 'inbox',
},
{
- id: 'Drafts',
- accountId: 13,
+ name: 'Drafts',
+ databaseId: 12,
specialRole: 'draft',
},
])
- context.getters.getFolders.withArgs(26).returns([
+ context.getters.getMailboxes.withArgs(26).returns([
{
- id: 'INBOX',
+ name: 'INBOX',
+ databaseId: 21,
accountId: 26,
specialRole: 'inbox',
},
{
- id: 'Drafts',
+ name: 'Drafts',
+ databaseId: 22,
accountId: 26,
specialRole: 'draft',
},
])
context.getters.getEnvelopes
- .withArgs(UNIFIED_ACCOUNT_ID, UNIFIED_INBOX_ID, undefined)
+ .withArgs(UNIFIED_INBOX_ID, undefined)
.returns(
orderBy(
prop('dateInt'),
'desc',
- page1.map(mockEnvelope(13, 'INBOX')).concat(page2.map(mockEnvelope(26, 'INBOX')))
+ page1.map(mockEnvelope(11)).concat(page2.map(mockEnvelope(21)))
)
)
- context.getters.getEnvelopes.withArgs(13, 'INBOX', undefined).returns(msgs1.map(mockEnvelope(13, 'INBOX')))
- context.getters.getEnvelopes.withArgs(26, 'INBOX', undefined).returns(msgs2.map(mockEnvelope(26, 'INBOX')))
+ context.getters.getEnvelopes.withArgs(11, undefined).returns(msgs1.map(mockEnvelope(11)))
+ context.getters.getEnvelopes.withArgs(21, undefined).returns(msgs2.map(mockEnvelope(21)))
const page = await actions.fetchNextEnvelopePage(context, {
- accountId: UNIFIED_ACCOUNT_ID,
- folderId: UNIFIED_INBOX_ID,
+ mailboxId: UNIFIED_INBOX_ID,
})
expect(context.dispatch).not.have.been.called
@@ -250,69 +240,68 @@ describe('Vuex store actions', () => {
const msgs2 = reverse(range(5, 35))
context.getters.accounts.push({
id: 13,
- accountId: 13,
})
context.getters.accounts.push({
id: 26,
- accountId: 26,
})
- context.getters.getFolder.withArgs(UNIFIED_ACCOUNT_ID, UNIFIED_INBOX_ID).returns({
+ context.getters.getMailbox.withArgs(UNIFIED_INBOX_ID).returns({
isUnified: true,
+ databaseId: UNIFIED_INBOX_ID,
specialRole: 'inbox',
accountId: UNIFIED_ACCOUNT_ID,
id: UNIFIED_INBOX_ID,
})
- context.getters.getFolders.withArgs(13).returns([
+ context.getters.getMailboxes.withArgs(13).returns([
{
- id: 'INBOX',
- accountId: 13,
+ name: 'INBOX',
+ databaseId: 11,
specialRole: 'inbox',
},
{
- id: 'Drafts',
- accountId: 13,
+ name: 'Drafts',
+ databaseId: 12,
specialRole: 'draft',
},
])
- context.getters.getFolders.withArgs(26).returns([
+ context.getters.getMailboxes.withArgs(26).returns([
{
- id: 'INBOX',
+ name: 'INBOX',
+ databaseId: 21,
accountId: 26,
specialRole: 'inbox',
},
{
- id: 'Drafts',
+ name: 'Drafts',
+ databaseId: 22,
accountId: 26,
specialRole: 'draft',
},
])
context.getters.getEnvelopes
- .withArgs(UNIFIED_ACCOUNT_ID, UNIFIED_INBOX_ID, undefined)
+ .withArgs(UNIFIED_INBOX_ID, undefined)
.returns(
orderBy(
prop('dateInt'),
'desc',
- page1.map(mockEnvelope(13, 'INBOX')).concat(page2.map(mockEnvelope(26, 'INBOX')))
+ page1.map(mockEnvelope(11)).concat(page2.map(mockEnvelope(12)))
)
)
- context.getters.getEnvelopes.withArgs(13, 'INBOX', undefined).returns(msgs1.map(mockEnvelope(13, 'INBOX')))
- context.getters.getEnvelopes.withArgs(26, 'INBOX', undefined).returns(msgs2.map(mockEnvelope(26, 'INBOX')))
+ context.getters.getEnvelopes.withArgs(11, undefined).returns(msgs1.map(mockEnvelope(11)))
+ context.getters.getEnvelopes.withArgs(21, undefined).returns(msgs2.map(mockEnvelope(21)))
await actions.fetchNextEnvelopePage(context, {
- accountId: UNIFIED_ACCOUNT_ID,
- folderId: UNIFIED_INBOX_ID,
+ mailboxId: UNIFIED_INBOX_ID,
})
expect(context.dispatch).have.been.calledTwice
expect(context.dispatch).have.been.calledWith('fetchNextEnvelopePage', {
- accountId: 26,
- folderId: 'INBOX',
+ mailboxId: 21,
query: undefined,
})
expect(context.dispatch).have.been.calledWith('fetchNextEnvelopePage', {
- accountId: UNIFIED_ACCOUNT_ID,
- folderId: UNIFIED_INBOX_ID,
+ mailboxId: UNIFIED_INBOX_ID,
query: undefined,
+ rec: false,
})
})
@@ -328,41 +317,41 @@ describe('Vuex store actions', () => {
it('fetches the inbox first', async() => {
context.getters.accounts.push({
id: 13,
- accountId: 13,
})
context.getters.accounts.push({
id: 26,
- accountId: 26,
})
- context.getters.getFolder.withArgs(UNIFIED_ACCOUNT_ID, UNIFIED_INBOX_ID).returns({
+ context.getters.getMailbox.withArgs(UNIFIED_INBOX_ID).returns({
isUnified: true,
specialRole: 'inbox',
accountId: UNIFIED_ACCOUNT_ID,
id: UNIFIED_INBOX_ID,
})
- context.getters.getFolders.withArgs(13).returns([
+ context.getters.getMailboxes.withArgs(13).returns([
{
- id: 'INBOX',
- accountId: 13,
+ name: 'INBOX',
+ databaseId: 11,
specialRole: 'inbox',
envelopeLists: {},
},
{
- id: 'Drafts',
- accountId: 13,
+ name: 'Drafts',
+ databaseId: 12,
specialRole: 'draft',
envelopeLists: {},
},
])
- context.getters.getFolders.withArgs(26).returns([
+ context.getters.getMailboxes.withArgs(26).returns([
{
- id: 'INBOX',
+ name: 'INBOX',
+ databaseId: 21,
accountId: 26,
specialRole: 'inbox',
envelopeLists: {},
},
{
- id: 'Drafts',
+ name: 'Drafts',
+ databaseId: 22,
accountId: 26,
specialRole: 'draft',
envelopeLists: {},
@@ -373,20 +362,16 @@ describe('Vuex store actions', () => {
expect(context.dispatch).have.callCount(4) // 2 fetch + 2 sync
expect(context.dispatch).have.been.calledWith('fetchEnvelopes', {
- accountId: 13,
- folderId: 'INBOX',
+ mailboxId: 11,
})
expect(context.dispatch).have.been.calledWith('syncEnvelopes', {
- accountId: 13,
- folderId: 'INBOX',
+ mailboxId: 11,
})
expect(context.dispatch).have.been.calledWith('fetchEnvelopes', {
- accountId: 26,
- folderId: 'INBOX',
+ mailboxId: 21,
})
expect(context.dispatch).have.been.calledWith('syncEnvelopes', {
- accountId: 26,
- folderId: 'INBOX',
+ mailboxId: 21,
})
// We can't detect new messages here
expect(NotificationService.showNewMessagesNotification).not.have.been.called
@@ -395,39 +380,41 @@ describe('Vuex store actions', () => {
it('syncs each individual mailbox', async() => {
context.getters.accounts.push({
id: 13,
- accountId: 13,
})
context.getters.accounts.push({
id: 26,
- accountId: 26,
})
- context.getters.getFolder.withArgs(UNIFIED_ACCOUNT_ID, UNIFIED_INBOX_ID).returns({
+ context.getters.getMailbox.withArgs(UNIFIED_INBOX_ID).returns({
isUnified: true,
specialRole: 'inbox',
accountId: UNIFIED_ACCOUNT_ID,
id: UNIFIED_INBOX_ID,
+ envelopeLists: {
+ '': [],
+ },
})
- context.getters.getFolders.withArgs(13).returns([
+ context.getters.getMailboxes.withArgs(13).returns([
{
- id: 'INBOX',
- accountId: 13,
+ name: 'INBOX',
+ databaseId: 11,
specialRole: 'inbox',
envelopeLists: {
'': [],
},
},
{
- id: 'Drafts',
- accountId: 13,
+ name: 'Drafts',
+ databaseId: 12,
specialRole: 'draft',
envelopeLists: {
'': [],
},
},
])
- context.getters.getFolders.withArgs(26).returns([
+ context.getters.getMailboxes.withArgs(26).returns([
{
- id: 'INBOX',
+ name: 'INBOX',
+ databaseId: 21,
accountId: 26,
specialRole: 'inbox',
envelopeLists: {
@@ -435,7 +422,8 @@ describe('Vuex store actions', () => {
},
},
{
- id: 'Drafts',
+ name: 'Drafts',
+ databaseId: 22,
accountId: 26,
specialRole: 'draft',
envelopeLists: {
@@ -445,21 +433,18 @@ describe('Vuex store actions', () => {
])
context.dispatch
.withArgs('syncEnvelopes', {
- accountId: 13,
- folderId: 'INBOX',
+ mailboxId: 11,
})
.returns(Promise.resolve([{ id: 123 }, { id: 321 }]))
await actions.syncInboxes(context)
- expect(context.dispatch).have.been.calledTwice
+ //expect(context.dispatch).have.been
expect(context.dispatch).have.been.calledWith('syncEnvelopes', {
- accountId: 13,
- folderId: 'INBOX',
+ mailboxId: 11,
})
expect(context.dispatch).have.been.calledWith('syncEnvelopes', {
- accountId: 26,
- folderId: 'INBOX',
+ mailboxId: 21,
})
// Here we expect notifications
expect(NotificationService.showNewMessagesNotification).have.been.called
diff --git a/src/tests/unit/store/getters.spec.js b/src/tests/unit/store/getters.spec.js
index fe5a3f962..b6e438f81 100644
--- a/src/tests/unit/store/getters.spec.js
+++ b/src/tests/unit/store/getters.spec.js
@@ -33,7 +33,7 @@ describe('Vuex store getters', () => {
state = {
accountList: [],
accounts: {},
- folders: {},
+ mailboxes: {},
envelopes: {},
messages: {},
}
@@ -68,5 +68,4 @@ describe('Vuex store getters', () => {
accountId: 13,
})
})
- it('gets account folders', () => {})
})
diff --git a/src/tests/unit/store/mutations.spec.js b/src/tests/unit/store/mutations.spec.js
index e2131064d..6099c9cac 100644
--- a/src/tests/unit/store/mutations.spec.js
+++ b/src/tests/unit/store/mutations.spec.js
@@ -22,10 +22,8 @@
import mutations from '../../../store/mutations'
import {
PRIORITY_INBOX_ID,
- PRIORITY_INBOX_UID,
UNIFIED_ACCOUNT_ID,
UNIFIED_INBOX_ID,
- UNIFIED_INBOX_UID,
} from '../../../store/constants'
describe('Vuex store mutations', () => {
@@ -35,28 +33,27 @@ describe('Vuex store mutations', () => {
[UNIFIED_ACCOUNT_ID]: {
accountId: UNIFIED_ACCOUNT_ID,
id: UNIFIED_ACCOUNT_ID,
- folders: [],
+ mailboxes: [],
},
},
envelopes: {},
- folders: {
- '13-INBOX': {
- id: 'INBOX',
+ mailboxes: {
+ 27: {
+ name: 'INBOX',
+ accountId: 13,
envelopeLists: {},
},
},
}
mutations.addEnvelope(state, {
- accountId: 13,
- folderId: 'INBOX',
query: undefined,
envelope: {
- accountId: 13,
- folderId: 'INBOX',
+ mailboxId: 27,
+ databaseId: 12345,
id: 123,
subject: 'henlo',
- uid: '13-INBOX-123',
+ uid: 321,
},
})
@@ -65,23 +62,25 @@ describe('Vuex store mutations', () => {
[UNIFIED_ACCOUNT_ID]: {
accountId: UNIFIED_ACCOUNT_ID,
id: UNIFIED_ACCOUNT_ID,
- folders: [],
+ mailboxes: [],
},
},
envelopes: {
- '13-INBOX-123': {
+ 12345: {
accountId: 13,
- folderId: 'INBOX',
- uid: '13-INBOX-123',
+ mailboxId: 27,
+ databaseId: 12345,
+ uid: 321,
id: 123,
subject: 'henlo',
},
},
- folders: {
- '13-INBOX': {
- id: 'INBOX',
+ mailboxes: {
+ 27: {
+ name: 'INBOX',
+ accountId: 13,
envelopeLists: {
- '': ['13-INBOX-123'],
+ '': [12345],
},
},
},
@@ -94,17 +93,19 @@ describe('Vuex store mutations', () => {
[UNIFIED_ACCOUNT_ID]: {
accountId: UNIFIED_ACCOUNT_ID,
id: UNIFIED_ACCOUNT_ID,
- folders: [UNIFIED_INBOX_UID],
+ mailboxes: [UNIFIED_INBOX_ID],
},
},
envelopes: {},
- folders: {
- '13-INBOX': {
- id: 'INBOX',
+ mailboxes: {
+ 27: {
+ name: 'INBOX',
+ databaseId: 27,
+ accountId: 2,
envelopeLists: {},
specialRole: 'inbox',
},
- [UNIFIED_INBOX_UID]: {
+ [UNIFIED_INBOX_ID]: {
specialRole: 'inbox',
envelopeLists: {},
},
@@ -112,15 +113,12 @@ describe('Vuex store mutations', () => {
}
mutations.addEnvelope(state, {
- accountId: 13,
- folderId: 'INBOX',
query: undefined,
envelope: {
- accountId: 13,
- folderId: 'INBOX',
- id: 123,
+ mailboxId: 27,
+ databaseId: 12345,
subject: 'henlo',
- uid: '13-INBOX-123',
+ uid: 321,
},
})
@@ -129,30 +127,32 @@ describe('Vuex store mutations', () => {
[UNIFIED_ACCOUNT_ID]: {
accountId: UNIFIED_ACCOUNT_ID,
id: UNIFIED_ACCOUNT_ID,
- folders: [UNIFIED_INBOX_UID],
+ mailboxes: [UNIFIED_INBOX_ID],
},
},
envelopes: {
- '13-INBOX-123': {
- accountId: 13,
- folderId: 'INBOX',
- uid: '13-INBOX-123',
- id: 123,
+ 12345: {
+ databaseId: 12345,
+ mailboxId: 27,
+ accountId: 2,
+ uid: 321,
subject: 'henlo',
},
},
- folders: {
- '13-INBOX': {
- id: 'INBOX',
+ mailboxes: {
+ 27: {
+ name: 'INBOX',
+ databaseId: 27,
+ accountId: 2,
specialRole: 'inbox',
envelopeLists: {
- '': ['13-INBOX-123'],
+ '': [12345],
},
},
- [UNIFIED_INBOX_UID]: {
+ [UNIFIED_INBOX_ID]: {
specialRole: 'inbox',
envelopeLists: {
- '': ['13-INBOX-123'],
+ '': [12345],
},
},
},
@@ -165,49 +165,46 @@ describe('Vuex store mutations', () => {
[UNIFIED_ACCOUNT_ID]: {
accountId: UNIFIED_ACCOUNT_ID,
id: UNIFIED_ACCOUNT_ID,
- folders: [UNIFIED_INBOX_UID, PRIORITY_INBOX_UID],
+ mailboxes: [UNIFIED_INBOX_ID, PRIORITY_INBOX_ID],
},
},
envelopes: {
- '13-INBOX-123': {
- accountId: 13,
- folderId: 'INBOX',
+ 12345: {
+ mailboxId: 27,
id: 123,
- uid: '13-INBOX-123',
+ uid: 12345,
},
},
- folders: {
- '13-INBOX': {
+ mailboxes: {
+ 27: {
id: 'INBOX',
specialUse: ['inbox'],
specialRole: 'inbox',
envelopeLists: {
- '': ['13-INBOX-123'],
+ '': [12345],
},
},
- [UNIFIED_INBOX_UID]: {
+ [UNIFIED_INBOX_ID]: {
id: UNIFIED_INBOX_ID,
specialUse: ['inbox'],
specialRole: 'inbox',
envelopeLists: {
- '': ['13-INBOX-123'],
+ '': [12345],
},
},
- [PRIORITY_INBOX_UID]: {
+ [PRIORITY_INBOX_ID]: {
id: PRIORITY_INBOX_ID,
specialUse: ['inbox'],
specialRole: 'inbox',
envelopeLists: {
- 'is:starred not:important': ['13-INBOX-123'],
+ 'is:starred not:important': [12345],
},
},
},
}
mutations.removeEnvelope(state, {
- accountId: 13,
- folderId: 'INBOX',
- id: 123,
+ id: 12345,
})
expect(state).to.deep.equal({
@@ -215,19 +212,18 @@ describe('Vuex store mutations', () => {
[UNIFIED_ACCOUNT_ID]: {
accountId: UNIFIED_ACCOUNT_ID,
id: UNIFIED_ACCOUNT_ID,
- folders: [UNIFIED_INBOX_UID, PRIORITY_INBOX_UID],
+ mailboxes: [UNIFIED_INBOX_ID, PRIORITY_INBOX_ID],
},
},
envelopes: {
- '13-INBOX-123': {
- accountId: 13,
- folderId: 'INBOX',
+ 12345: {
+ mailboxId: 27,
id: 123,
- uid: '13-INBOX-123',
+ uid: 12345,
},
},
- folders: {
- '13-INBOX': {
+ mailboxes: {
+ 27: {
id: 'INBOX',
specialUse: ['inbox'],
specialRole: 'inbox',
@@ -235,7 +231,7 @@ describe('Vuex store mutations', () => {
'': [],
},
},
- [UNIFIED_INBOX_UID]: {
+ [UNIFIED_INBOX_ID]: {
id: UNIFIED_INBOX_ID,
specialUse: ['inbox'],
specialRole: 'inbox',
@@ -243,7 +239,7 @@ describe('Vuex store mutations', () => {
'': [],
},
},
- [PRIORITY_INBOX_UID]: {
+ [PRIORITY_INBOX_ID]: {
id: PRIORITY_INBOX_ID,
specialUse: ['inbox'],
specialRole: 'inbox',
@@ -255,27 +251,27 @@ describe('Vuex store mutations', () => {
})
})
- it('removes a folder', () => {
+ it('removes a mailbox', () => {
const state = {
accounts: {
13: {
accountId: 13,
id: 13,
- folders: ['13-INBOX'],
+ mailboxes: [27],
},
},
- folders: {
- '13-INBOX': {
+ mailboxes: {
+ 27: {
id: 'INBOX',
+ accountId: 13,
specialUse: ['inbox'],
specialRole: 'inbox',
},
},
}
- mutations.removeFolder(state, {
- accountId: 13,
- folderId: 'INBOX',
+ mutations.removeMailbox(state, {
+ id: 27,
})
expect(state).to.deep.equal({
@@ -283,41 +279,42 @@ describe('Vuex store mutations', () => {
13: {
accountId: 13,
id: 13,
- folders: [],
+ mailboxes: [],
},
},
- folders: {},
+ mailboxes: {},
})
})
- it('removes a subfolder', () => {
+ it('removes a sub-mailbox', () => {
const state = {
accounts: {
13: {
accountId: 13,
id: 13,
- folders: ['13-INBOX'],
+ mailboxes: [27],
},
},
- folders: {
- '13-INBOX': {
+ mailboxes: {
+ 27: {
id: 'INBOX',
+ accountId: 13,
specialUse: ['inbox'],
specialRole: 'inbox',
- folders: ['13-INBOX.sub'],
+ mailboxes: [28],
},
- '13-INBOX.sub': {
+ 28: {
id: 'INBOX.sub',
+ accountId: 13,
specialUse: ['inbox'],
specialRole: 'inbox',
- folders: [],
+ mailboxes: [],
},
},
}
- mutations.removeFolder(state, {
- accountId: 13,
- folderId: 'INBOX.sub',
+ mutations.removeMailbox(state, {
+ id: 28,
})
expect(state).to.deep.equal({
@@ -325,15 +322,16 @@ describe('Vuex store mutations', () => {
13: {
accountId: 13,
id: 13,
- folders: ['13-INBOX'],
+ mailboxes: [27],
},
},
- folders: {
- '13-INBOX': {
+ mailboxes: {
+ 27: {
id: 'INBOX',
+ accountId: 13,
specialUse: ['inbox'],
specialRole: 'inbox',
- folders: [],
+ mailboxes: [],
},
},
})
diff --git a/src/tests/unit/store/normalization.spec.js b/src/tests/unit/store/normalization.spec.js
deleted file mode 100644
index 29ea16bf0..000000000
--- a/src/tests/unit/store/normalization.spec.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * @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/>.
- */
-
-import { normalizedFolderId, normalizedMessageId } from '../../../store/normalization'
-
-describe('Vuex store normalization', () => {
- it('creates a unique folder ID', () => {
- const accountId = 13
- const folderId = 'INBOX'
-
- const id = normalizedFolderId(accountId, folderId)
-
- expect(id).to.equal('13-INBOX')
- })
-
- it('creates a unique message ID', () => {
- const accountId = 13
- const folderId = 'INBOX'
- const messageId = 123
-
- const id = normalizedMessageId(accountId, folderId, messageId)
-
- expect(id).to.equal('13-INBOX-123')
- })
-})
diff --git a/src/tests/unit/util/EnvelopeUidParser.spec.js b/src/tests/unit/util/EnvelopeUidParser.spec.js
deleted file mode 100644
index d35fbe5fe..000000000
--- a/src/tests/unit/util/EnvelopeUidParser.spec.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * @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/>.
- */
-
-import { parseUuid } from '../../../util/EnvelopeUidParser'
-
-describe('EnvelopeUidParser', () => {
- it('parses a simple UID', () => {
- const uuid = '1-SU5CT1g=-123'
-
- const parsed = parseUuid(uuid)
-
- expect(parsed.accountId).to.equal(1)
- expect(parsed.folderId).to.equal('SU5CT1g=')
- expect(parsed.uid).to.equal(123)
- })
-
- it('parses the default account UID', () => {
- const uuid = '-2-SU5CT1g=-123'
-
- const parsed = parseUuid(uuid)
-
- expect(parsed.accountId).to.equal(-2)
- expect(parsed.folderId).to.equal('SU5CT1g=')
- expect(parsed.uid).to.equal(123)
- })
-})
diff --git a/src/util/EnvelopeUidParser.js b/src/util/EnvelopeUidParser.js
deleted file mode 100644
index 29741f454..000000000
--- a/src/util/EnvelopeUidParser.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * @copyright 2018 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author 2018 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/>.
- */
-
-const reg = /^(-?\d+)-((?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4}))-(\d+)$/
-
-export const parseUuid = (str) => {
- const match = reg.exec(str)
-
- if (match === null) {
- console.error(`UID ${str} is invalid`)
- throw new Error(`UID ${str} is invalid`)
- }
-
- return {
- accountId: parseInt(match[1], 10),
- folderId: match[2],
- uid: parseInt(match[3], 10),
- }
-}
diff --git a/src/views/Dashboard.vue b/src/views/Dashboard.vue
index d4516ede1..e6afd2c2d 100644
--- a/src/views/Dashboard.vue
+++ b/src/views/Dashboard.vue
@@ -50,14 +50,17 @@
</template>
<script>
-import { fetchEnvelopes } from '../service/MessageService'
import { loadState } from '@nextcloud/initial-state'
import { generateUrl, imagePath } from '@nextcloud/router'
-import Avatar from '../components/Avatar'
import { DashboardWidget, DashboardWidgetItem } from '@nextcloud/vue-dashboard'
import orderBy from 'lodash/fp/orderBy'
import prop from 'lodash/fp/prop'
+import Avatar from '../components/Avatar'
+import { fetchEnvelopes } from '../service/MessageService'
+import logger from '../logger'
+import { fetchAll } from '../service/MailboxService'
+
const accounts = loadState('mail', 'mail-accounts')
const orderByDateInt = orderBy(prop('dateInt'), 'desc')
@@ -72,15 +75,13 @@ export default {
return {
messages: [],
accounts,
+ loading: true,
fetchedAccounts: 0,
emptyImage: imagePath('mail', 'newsletter.svg'),
accountSetupUrl: generateUrl('/apps/mail/#/setup'),
}
},
computed: {
- loading() {
- return this.fetchedAccounts < this.accounts.length
- },
importantMessages() {
if (!this.messages) {
return []
@@ -89,9 +90,8 @@ export default {
},
getWidgetItem() {
return (item) => {
- const { uid, accountId, mailbox } = item
return {
- targetUrl: generateUrl(`/apps/mail/#/accounts/${accountId}/folders/${mailbox}/message/${accountId}-${mailbox}-${uid}`),
+ targetUrl: generateUrl(`/apps/mail/box/priority/thread/${item.databaseId}`),
mainText: item.from ? item.from[0].label : '',
subText: item.subject,
message: item,
@@ -99,15 +99,33 @@ export default {
}
},
},
- mounted() {
- // TODO: check if there is a more sane way to query this and if other mailboxes should be fetched as well
- this.accounts.forEach((account) => {
- fetchEnvelopes(account.accountId, btoa('INBOX'), 'is:important', undefined, 10).then((messages) => {
- messages = messages.map((message) => ({ ...message, accountId: account.accountId, mailbox: btoa('INBOX') }))
- this.messages = this.messages !== null ? [...this.messages, ...messages] : messages
- this.fetchedAccounts++
+ async mounted() {
+ const accountInboxes = await Promise.all(this.accounts.map(async(account) => {
+ logger.debug('account', {
+ account,
})
+
+ const mailboxes = await fetchAll(account.accountId)
+
+ logger.debug('mailboxes', {
+ mailboxes,
+ })
+
+ return mailboxes.filter(mb => mb.specialRole === 'inbox')
+ }))
+ const inboxes = accountInboxes.flat()
+
+ logger.debug(`found ${inboxes.length} inboxes`, {
+ inboxes,
})
+
+ await Promise.all(inboxes.map(async(mailbox) => {
+ const messages = await fetchEnvelopes(mailbox.databaseId, 'is:important', undefined, 10)
+ this.messages = this.messages !== null ? [...this.messages, ...messages] : messages
+ this.fetchedAccounts++
+ }))
+
+ this.loading = false
},
}
</script>
diff --git a/src/views/Home.vue b/src/views/Home.vue
index f5b30c047..37292b331 100644
--- a/src/views/Home.vue
+++ b/src/views/Home.vue
@@ -1,7 +1,7 @@
<template>
<Content v-shortkey.once="['c']" app-name="mail" @shortkey.native="onNewMessage">
<Navigation />
- <MailboxMessage v-if="activeAccount" :account="activeAccount" :folder="activeFolder" />
+ <MailboxMessage v-if="activeAccount" :account="activeAccount" :mailbox="activeMailbox" />
</Content>
</template>
@@ -23,10 +23,10 @@ export default {
mixins: [isMobile],
computed: {
activeAccount() {
- return this.$store.getters.getAccount(this.$route.params.accountId)
+ return this.$store.getters.getAccount(this.activeMailbox?.accountId)
},
- activeFolder() {
- return this.$store.getters.getFolder(this.$route.params.accountId, this.$route.params.folderId)
+ activeMailbox() {
+ return this.$store.getters.getMailbox(this.$route.params.mailboxId)
},
menu() {
return this.buildMenu()
@@ -36,13 +36,12 @@ export default {
$route(to, from) {
if (
from.name === 'message'
- && to.name === 'folder'
+ && to.name === 'mailbox'
&& !this.isMobile
- && Number.parseInt(from.params.accountId, 10) === Number.parseInt(to.params.accountId, 10)
- && from.params.folderId === to.params.folderId
+ && from.params.mailboxId === to.params.mailboxId
&& from.params.filter === to.params.filter
) {
- logger.warn("navigation from a message to just the folder. we don't want that, do we? let's go back", {
+ logger.warn("navigation from a message to just the mailbox. we don't want that, do we? let's go back", {
to,
from,
})
@@ -56,16 +55,15 @@ export default {
if (this.$route.name === 'home' && accounts.length > 1) {
// Show first account
const firstAccount = accounts[0]
- // FIXME: this assumes that there's at least one folder
- const firstFolder = this.$store.getters.getFolders(firstAccount.id)[0]
+ // FIXME: this assumes that there's at least one mailbox
+ const firstMailbox = this.$store.getters.getMailboxes(firstAccount.id)[0]
- console.debug('loading first folder of first account', firstAccount.id, firstFolder.id)
+ console.debug('loading first mailbox of first account', firstAccount.id, firstMailbox.databaseId)
this.$router.replace({
- name: 'folder',
+ name: 'mailbox',
params: {
- accountId: firstAccount.id,
- folderId: firstFolder.id,
+ mailboxId: firstMailbox.databaseId,
},
})
} else if (this.$route.name === 'home' && accounts.length === 1) {
@@ -81,17 +79,16 @@ export default {
// Show first account
const firstAccount = accounts[0]
- // FIXME: this assumes that there's at least one folder
- const firstFolder = this.$store.getters.getFolders(firstAccount.id)[0]
+ // FIXME: this assumes that there's at least one mailbox
+ const firstMailbox = this.$store.getters.getMailboxes(firstAccount.id)[0]
- console.debug('loading composer with first account and folder', firstAccount.id, firstFolder.id)
+ console.debug('loading composer with first account and mailbox', firstAccount.id, firstMailbox.id)
this.$router.replace({
name: 'message',
params: {
- accountId: firstAccount.id,
- folderId: firstFolder.id,
- messageUuid: 'new',
+ mailboxId: firstMailbox.databaseId,
+ threadId: 'new',
},
query: {
to: this.$route.query.to,
@@ -109,9 +106,8 @@ export default {
this.$router.push({
name: 'message',
params: {
- accountId: this.$route.params.accountId,
- folderId: this.$route.params.folderId,
- messageUuid: 'new',
+ mailboxId: this.$route.params.mailboxId,
+ threadId: 'new',
},
})
},
diff --git a/tests/Integration/Db/MailAccountTest.php b/tests/Integration/Db/MailAccountTest.php
index bc4140010..595868754 100644
--- a/tests/Integration/Db/MailAccountTest.php
+++ b/tests/Integration/Db/MailAccountTest.php
@@ -48,6 +48,7 @@ class MailAccountTest extends TestCase {
$a->setOrder(13);
$this->assertEquals([
+ 'id' => 12345,
'accountId' => 12345,
'name' => 'Peter Parker',
'emailAddress' => 'peter.parker@marvel.com',
@@ -69,6 +70,7 @@ class MailAccountTest extends TestCase {
public function testMailAccountConstruct() {
$expected = [
+ 'id' => 12345,
'accountId' => 12345,
'accountName' => 'Peter Parker',
'emailAddress' => 'peter.parker@marvel.com',
diff --git a/tests/Integration/Framework/ImapTest.php b/tests/Integration/Framework/ImapTest.php
index 7e9f93cd2..4b9288f72 100644
--- a/tests/Integration/Framework/ImapTest.php
+++ b/tests/Integration/Framework/ImapTest.php
@@ -123,7 +123,7 @@ trait ImapTest {
*
* @return int id of the new message
*/
- public function saveMessage($mailbox, SimpleMessage $message, MailAccount $account = null) {
+ public function saveMessage(string $mailbox, SimpleMessage $message, MailAccount $account = null) {
$client = $this->getClient($account);
$headers = [
@@ -201,7 +201,7 @@ trait ImapTest {
* @param int $number
* @param string $mailbox
*/
- public function assertMessageCount($number, $mailbox) {
+ public function assertMessageCount(int $number, string $mailbox) {
$client = $this->getTestClient();
$query = new Horde_Imap_Client_Fetch_Query();
diff --git a/tests/Integration/MailboxSynchronizationTest.php b/tests/Integration/MailboxSynchronizationTest.php
index fe54bdab7..c79f3e474 100644
--- a/tests/Integration/MailboxSynchronizationTest.php
+++ b/tests/Integration/MailboxSynchronizationTest.php
@@ -27,7 +27,7 @@ use Horde_Imap_Client;
use OC;
use OCA\Mail\Account;
use OCA\Mail\Contracts\IMailManager;
-use OCA\Mail\Controller\FoldersController;
+use OCA\Mail\Controller\MailboxesController;
use OCA\Mail\Service\AccountService;
use OCA\Mail\Service\Sync\SyncService;
use OCA\Mail\Tests\Integration\Framework\ImapTest;
@@ -37,13 +37,13 @@ class MailboxSynchronizationTest extends TestCase {
use ImapTest,
ImapTestAccount;
- /** @var FoldersController */
+ /** @var MailboxesController */
private $foldersController;
protected function setUp(): void {
parent::setUp();
- $this->foldersController = new FoldersController(
+ $this->foldersController = new MailboxesController(
'mail',
OC::$server->getRequest(),
OC::$server->query(AccountService::class),
@@ -55,21 +55,28 @@ class MailboxSynchronizationTest extends TestCase {
public function testSyncEmptyMailbox() {
$account = $this->createTestAccount();
- $mailbox = 'INBOX';
+ /** @var IMailManager $mailManager */
+ $mailManager = OC::$server->query(IMailManager::class);
+ $mailBoxes = $mailManager->getMailboxes(new Account($account));
+ $inbox = null;
+ foreach ($mailBoxes as $mailBox) {
+ if ($mailBox->getName() === 'INBOX') {
+ $inbox = $mailBox;
+ break;
+ }
+ }
/** @var SyncService $syncService */
$syncService = OC::$server->query(SyncService::class);
$syncService->syncMailbox(
new Account($account),
- $mailbox,
+ $inbox,
Horde_Imap_Client::SYNC_NEWMSGSUIDS | Horde_Imap_Client::SYNC_FLAGSUIDS | Horde_Imap_Client::SYNC_VANISHEDUIDS,
[],
false
);
- $mailbox = 'INBOX';
$jsonResponse = $this->foldersController->sync(
- $account->getId(),
- base64_encode($mailbox),
+ $inbox->getId(),
[]
);
@@ -87,10 +94,19 @@ class MailboxSynchronizationTest extends TestCase {
$account = $this->createTestAccount();
/** @var SyncService $syncService */
$syncService = OC::$server->query(SyncService::class);
- $mailbox = 'INBOX';
+ /** @var IMailManager $mailManager */
+ $mailManager = OC::$server->query(IMailManager::class);
+ $mailBoxes = $mailManager->getMailboxes(new Account($account));
+ $inbox = null;
+ foreach ($mailBoxes as $mailBox) {
+ if ($mailBox->getName() === 'INBOX') {
+ $inbox = $mailBox;
+ break;
+ }
+ }
$syncService->syncMailbox(
new Account($account),
- $mailbox,
+ $inbox,
Horde_Imap_Client::SYNC_NEWMSGSUIDS | Horde_Imap_Client::SYNC_FLAGSUIDS | Horde_Imap_Client::SYNC_VANISHEDUIDS,
[],
false
@@ -100,11 +116,10 @@ class MailboxSynchronizationTest extends TestCase {
->from('ralph@buffington@domain.tld')
->to('user@domain.tld')
->finish();
- $newUid = $this->saveMessage($mailbox, $message, $account);
+ $newUid = $this->saveMessage($inbox->getName(), $message, $account);
$jsonResponse = $this->foldersController->sync(
- $account->getId(),
- base64_encode($mailbox),
+ $inbox->getId(),
[]
);
$syncJson = $jsonResponse->getData()->jsonSerialize();
@@ -124,19 +139,29 @@ class MailboxSynchronizationTest extends TestCase {
->from('ralph@buffington@domain.tld')
->to('user@domain.tld')
->finish();
- $id = $this->saveMessage($mailbox, $message, $account);
+ $uid = $this->saveMessage($mailbox, $message, $account);
+ /** @var IMailManager $mailManager */
+ $mailManager = OC::$server->query(IMailManager::class);
+ $mailBoxes = $mailManager->getMailboxes(new Account($account));
+ $inbox = null;
+ foreach ($mailBoxes as $mailBox) {
+ if ($mailBox->getName() === 'INBOX') {
+ $inbox = $mailBox;
+ break;
+ }
+ }
$syncService->syncMailbox(
new Account($account),
- $mailbox,
+ $inbox,
Horde_Imap_Client::SYNC_NEWMSGSUIDS | Horde_Imap_Client::SYNC_FLAGSUIDS | Horde_Imap_Client::SYNC_VANISHEDUIDS,
[],
false
);
- $this->flagMessage($mailbox, $id, $account);
+ $this->flagMessage($mailbox, $uid, $account);
+ $id = $mailManager->getMessageIdForUid($inbox, $uid);
$jsonResponse = $this->foldersController->sync(
- $account->getId(),
- base64_encode($mailbox),
+ $inbox->getId(),
[
$id
]);
@@ -156,11 +181,21 @@ class MailboxSynchronizationTest extends TestCase {
->to('user@domain.tld')
->finish();
$id = $this->saveMessage($mailbox, $message, $account);
+ /** @var IMailManager $mailManager */
+ $mailManager = OC::$server->query(IMailManager::class);
+ $mailBoxes = $mailManager->getMailboxes(new Account($account));
+ $inbox = null;
+ foreach ($mailBoxes as $mailBox) {
+ if ($mailBox->getName() === 'INBOX') {
+ $inbox = $mailBox;
+ break;
+ }
+ }
/** @var SyncService $syncService */
$syncService = OC::$server->query(SyncService::class);
$syncService->syncMailbox(
new Account($account),
- $mailbox,
+ $inbox,
Horde_Imap_Client::SYNC_NEWMSGSUIDS | Horde_Imap_Client::SYNC_FLAGSUIDS | Horde_Imap_Client::SYNC_VANISHEDUIDS,
[],
false
@@ -168,8 +203,7 @@ class MailboxSynchronizationTest extends TestCase {
$this->deleteMessage($mailbox, $id, $account);
$jsonResponse = $this->foldersController->sync(
- $account->getId(),
- base64_encode($mailbox),
+ $inbox->getId(),
[
$id
]);
diff --git a/tests/Integration/Service/MailTransmissionIntegrationTest.php b/tests/Integration/Service/MailTransmissionIntegrationTest.php
index fcfed63f8..95813954b 100644
--- a/tests/Integration/Service/MailTransmissionIntegrationTest.php
+++ b/tests/Integration/Service/MailTransmissionIntegrationTest.php
@@ -1,5 +1,7 @@
<?php
+declare(strict_types=1);
+
/**
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
*
@@ -29,6 +31,7 @@ use OCA\Mail\Contracts\IMailTransmission;
use OCA\Mail\Db\MailAccount;
use OCA\Mail\Db\MailAccountMapper;
use OCA\Mail\Db\MailboxMapper;
+use OCA\Mail\Db\Message;
use OCA\Mail\IMAP\IMAPClientFactory;
use OCA\Mail\IMAP\MessageMapper;
use OCA\Mail\Model\NewMessageData;
@@ -169,7 +172,7 @@ class MailTransmissionIntegrationTest extends TestCase {
$message = NewMessageData::fromRequest($this->account, 'recipient@domain.com', null, null, '', 'hello there', []);
$reply = new RepliedMessageData($this->account, $inbox, $originalUID);
- $uid = $this->transmission->sendMessage($message, $reply);
+ $this->transmission->sendMessage($message, $reply);
$this->assertMailboxExists('Sent');
$this->assertMessageCount(1, 'Sent');
@@ -194,7 +197,7 @@ class MailTransmissionIntegrationTest extends TestCase {
public function testSaveNewDraft() {
$message = NewMessageData::fromRequest($this->account, 'recipient@domain.com', null, null, 'greetings', 'hello there', [], false);
- $uid = $this->transmission->saveDraft($message);
+ [,,$uid] = $this->transmission->saveDraft($message);
// There should be a new mailbox …
$this->assertMailboxExists('Drafts');
// … and it should have exactly one message …
@@ -205,9 +208,11 @@ class MailTransmissionIntegrationTest extends TestCase {
public function testReplaceDraft() {
$message1 = NewMessageData::fromRequest($this->account, 'recipient@domain.com', null, null, 'greetings', 'hello t', []);
- $uid = $this->transmission->saveDraft($message1);
+ [,,$uid] = $this->transmission->saveDraft($message1);
$message2 = NewMessageData::fromRequest($this->account, 'recipient@domain.com', null, null, 'greetings', 'hello there', []);
- $this->transmission->saveDraft($message2, $uid);
+ $previous = new Message();
+ $previous->setUid($uid);
+ $this->transmission->saveDraft($message2, $previous);
$this->assertMessageCount(1, 'Drafts');
}
diff --git a/tests/Unit/Controller/AccountsControllerTest.php b/tests/Unit/Controller/AccountsControllerTest.php
index 106444440..bfd50a799 100644
--- a/tests/Unit/Controller/AccountsControllerTest.php
+++ b/tests/Unit/Controller/AccountsControllerTest.php
@@ -31,6 +31,7 @@ use OCA\Mail\Account;
use OCA\Mail\Contracts\IMailManager;
use OCA\Mail\Contracts\IMailTransmission;
use OCA\Mail\Controller\AccountsController;
+use OCA\Mail\Db\Mailbox;
use OCA\Mail\Exception\ClientException;
use OCA\Mail\Model\NewMessageData;
use OCA\Mail\Model\RepliedMessageData;
@@ -39,6 +40,7 @@ use OCA\Mail\Service\AliasesService;
use OCA\Mail\Service\AutoConfig\AutoConfig;
use OCA\Mail\Service\SetupService;
use OCA\Mail\Service\GroupsIntegration;
+use OCA\Mail\Service\Sync\SyncService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
@@ -98,6 +100,9 @@ class AccountsControllerTest extends TestCase {
/** @var IMailManager|MockObject */
private $mailManager;
+ /** @var SyncService|MockObject */
+ private $syncService;
+
protected function setUp(): void {
parent::setUp();
@@ -117,6 +122,7 @@ class AccountsControllerTest extends TestCase {
$this->transmission = $this->createMock(IMailTransmission::class);
$this->setupService = $this->createMock(SetupService::class);
$this->mailManager = $this->createMock(IMailManager::class);
+ $this->syncService = $this->createMock(SyncService::class);
$this->controller = new AccountsController(
$this->appName,
@@ -129,7 +135,8 @@ class AccountsControllerTest extends TestCase {
$this->aliasesService,
$this->transmission,
$this->setupService,
- $this->mailManager
+ $this->mailManager,
+ $this->syncService
);
$this->account = $this->createMock(Account::class);
$this->accountId = 123;
@@ -461,7 +468,7 @@ class AccountsControllerTest extends TestCase {
$this->assertEquals($expected, $resp);
}
- public function draftDataProvider() {
+ public function draftDataProvider(): array {
return [
[false, false],
[true, true],
@@ -470,28 +477,33 @@ class AccountsControllerTest extends TestCase {
];
}
- public function testDraft() {
+ public function testDraft(): void {
$subject = 'Hello';
$body = 'Hi!';
$to = 'user1@example.com';
$cc = '"user2" <user2@example.com>, user3@example.com';
$bcc = 'user4@example.com';
- $uid = 123;
- $newUID = 124;
-
+ $id = 123;
+ $newId = 1245;
+ $newUid = 124;
+ $account = $this->createMock(Account::class);
+ $mailbox = new Mailbox();
$this->accountService->expects($this->once())
->method('find')
->with($this->userId, $this->accountId)
->will($this->returnValue($this->account));
$this->transmission->expects($this->once())
->method('saveDraft')
- ->willReturn($newUID);
+ ->willReturn([$account, $mailbox, $newUid]);
+ $this->mailManager->expects($this->once())
+ ->method('getMessageIdForUid')
+ ->willReturn($newId);
+
+ $actual = $this->controller->draft($this->accountId, $subject, $body, $to, $cc, $bcc, true, $id);
$expected = new JSONResponse([
- 'uid' => $newUID,
+ 'id' => $newId,
]);
- $actual = $this->controller->draft($this->accountId, $subject, $body, $to, $cc, $bcc, true, $uid);
-
$this->assertEquals($expected, $actual);
}
}
diff --git a/tests/Unit/Controller/FoldersControllerTest.php b/tests/Unit/Controller/MailboxesControllerTest.php
index 3ef4fd653..30499a6fd 100644
--- a/tests/Unit/Controller/FoldersControllerTest.php
+++ b/tests/Unit/Controller/MailboxesControllerTest.php
@@ -23,12 +23,12 @@ declare(strict_types=1);
namespace OCA\Mail\Tests\Unit\Controller;
+use OCA\Mail\Db\Mailbox;
use OCA\Mail\Service\Sync\SyncService;
use PHPUnit\Framework\MockObject\MockObject;
-use function base64_encode;
use OCA\Mail\Account;
use OCA\Mail\Contracts\IMailManager;
-use OCA\Mail\Controller\FoldersController;
+use OCA\Mail\Controller\MailboxesController;
use OCA\Mail\Exception\NotImplemented;
use OCA\Mail\Folder;
use OCA\Mail\IMAP\FolderStats;
@@ -37,7 +37,7 @@ use ChristophWurst\Nextcloud\Testing\TestCase;
use OCP\AppFramework\Http\JSONResponse;
use OCP\IRequest;
-class FoldersControllerTest extends TestCase {
+class MailboxesControllerTest extends TestCase {
/** @var string */
private $appName = 'mail';
@@ -54,7 +54,7 @@ class FoldersControllerTest extends TestCase {
/** @var IMailManager|MockObject */
private $mailManager;
- /** @var FoldersController */
+ /** @var MailboxesController */
private $controller;
/** @var SyncService|MockObject */
@@ -67,7 +67,7 @@ class FoldersControllerTest extends TestCase {
$this->accountService = $this->createMock(AccountService::class);
$this->mailManager = $this->createMock(IMailManager::class);
$this->syncService = $this->createMock(SyncService::class);
- $this->controller = new FoldersController(
+ $this->controller = new MailboxesController(
$this->appName,
$this->request,
$this->accountService,
@@ -103,7 +103,7 @@ class FoldersControllerTest extends TestCase {
$expected = new JSONResponse([
'id' => 28,
'email' => 'user@example.com',
- 'folders' => [
+ 'mailboxes' => [
$folder,
],
'delimiter' => '.',
@@ -119,20 +119,20 @@ class FoldersControllerTest extends TestCase {
public function testCreate() {
$account = $this->createMock(Account::class);
- $folder = $this->createMock(Folder::class);
+ $mailbox = new Mailbox();
$accountId = 28;
$this->accountService->expects($this->once())
->method('find')
->with($this->equalTo($this->userId), $this->equalTo($accountId))
->willReturn($account);
$this->mailManager->expects($this->once())
- ->method('createFolder')
+ ->method('createMailbox')
->with($this->equalTo($account), $this->equalTo('new'))
- ->willReturn($folder);
+ ->willReturn($mailbox);
$response = $this->controller->create($accountId, 'new');
- $expected = new JSONResponse($folder);
+ $expected = new JSONResponse($mailbox);
$this->assertEquals($expected, $response);
}
@@ -140,16 +140,22 @@ class FoldersControllerTest extends TestCase {
$account = $this->createMock(Account::class);
$stats = $this->createMock(FolderStats::class);
$accountId = 28;
+ $mailbox = new Mailbox();
+ $mailbox->setAccountId($accountId);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->with('john', 13)
+ ->willReturn($mailbox);
$this->accountService->expects($this->once())
->method('find')
->with($this->equalTo($this->userId), $this->equalTo($accountId))
->willReturn($account);
$this->mailManager->expects($this->once())
- ->method('getFolderStats')
- ->with($this->equalTo($account), $this->equalTo('INBOX'))
+ ->method('getMailboxStats')
+ ->with($this->equalTo($account), $mailbox)
->willReturn($stats);
- $response = $this->controller->stats($accountId, base64_encode('INBOX'));
+ $response = $this->controller->stats(13);
$expected = new JSONResponse($stats);
$this->assertEquals($expected, $response);
diff --git a/tests/Unit/Controller/MessagesControllerTest.php b/tests/Unit/Controller/MessagesControllerTest.php
index 4683f827c..6b4f724df 100644
--- a/tests/Unit/Controller/MessagesControllerTest.php
+++ b/tests/Unit/Controller/MessagesControllerTest.php
@@ -178,18 +178,35 @@ class MessagesControllerTest extends TestCase {
public function testGetHtmlBody() {
$accountId = 17;
+ $mailboxId = 13;
$folderId = 'testfolder';
$messageId = 4321;
- $message = $this->createMock(IMAPMessage::class);
-
+ $this->account
+ ->method('getId')
+ ->willReturn($accountId);
+ $mailbox = new \OCA\Mail\Db\Mailbox();
+ $message = new \OCA\Mail\Db\Message();
+ $message->setMailboxId($mailboxId);
+ $message->setUid(123);
+ $mailbox->setAccountId($accountId);
+ $mailbox->setName($folderId);
+ $this->mailManager->expects($this->once())
+ ->method('getMessage')
+ ->with($this->userId, $messageId)
+ ->willReturn($message);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->with($this->userId, $mailboxId)
+ ->willReturn($mailbox);
$this->accountService->expects($this->once())
->method('find')
->with($this->equalTo($this->userId), $this->equalTo($accountId))
->will($this->returnValue($this->account));
+ $imapMessage = $this->createMock(IMAPMessage::class);
$this->mailManager->expects($this->once())
- ->method('getMessage')
- ->with($this->account, $folderId, $messageId, true)
- ->willReturn($message);
+ ->method('getImapMessage')
+ ->with($this->account, $mailbox, 123, true)
+ ->willReturn($imapMessage);
$expectedResponse = new HtmlResponse('');
$expectedResponse->cacheFor(3600);
@@ -203,34 +220,46 @@ class MessagesControllerTest extends TestCase {
$expectedResponse->setContentSecurityPolicy($policy);
}
- $actualResponse = $this->controller->getHtmlBody($accountId,
- base64_encode($folderId), $messageId);
+ $actualResponse = $this->controller->getHtmlBody($messageId);
$this->assertEquals($expectedResponse, $actualResponse);
}
public function testDownloadAttachment() {
$accountId = 17;
- $folderId = base64_encode('my folder');
- $messageId = 123;
+ $mailboxId = 987;
+ $id = 123;
+ $uid = 321;
$attachmentId = 3;
// Attachment data
$contents = 'abcdef';
$name = 'cat.jpg';
$type = 'image/jpg';
-
+ $message = new \OCA\Mail\Db\Message();
+ $message->setMailboxId($mailboxId);
+ $message->setUid($uid);
+ $mailbox = new \OCA\Mail\Db\Mailbox();
+ $mailbox->setName('INBOX');
+ $mailbox->setAccountId($accountId);
+ $this->mailManager->expects($this->once())
+ ->method('getMessage')
+ ->with($this->userId, $id)
+ ->willReturn($message);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->with($this->userId, $mailboxId)
+ ->willReturn($mailbox);
$this->accountService->expects($this->once())
->method('find')
->with($this->equalTo($this->userId), $this->equalTo($accountId))
->will($this->returnValue($this->account));
$this->account->expects($this->once())
->method('getMailbox')
- ->with(base64_decode($folderId))
- ->will($this->returnValue($this->mailbox));
+ ->willReturn($this->mailbox);
$this->mailbox->expects($this->once())
->method('getAttachment')
- ->with($messageId, $attachmentId)
+ ->with($uid, $attachmentId)
->will($this->returnValue($this->attachment));
$this->attachment->expects($this->once())
->method('getContents')
@@ -243,30 +272,46 @@ class MessagesControllerTest extends TestCase {
->will($this->returnValue($type));
$expected = new AttachmentDownloadResponse($contents, $name, $type);
- $response = $this->controller->downloadAttachment($accountId, $folderId,
- $messageId, $attachmentId);
+ $response = $this->controller->downloadAttachment(
+ $id,
+ $attachmentId
+ );
$this->assertEquals($expected, $response);
}
public function testSaveSingleAttachment() {
$accountId = 17;
- $folderId = base64_encode('my folder');
- $messageId = 123;
+ $mailboxId = 987;
+ $id = 123;
+ $uid = 321;
$attachmentId = '2.2';
$targetPath = 'Downloads';
-
+ $message = new \OCA\Mail\Db\Message();
+ $message->setMailboxId($mailboxId);
+ $message->setUid($uid);
+ $mailbox = new \OCA\Mail\Db\Mailbox();
+ $mailbox->setName('INBOX');
+ $mailbox->setAccountId($accountId);
+ $this->mailManager->expects($this->once())
+ ->method('getMessage')
+ ->with($this->userId, $id)
+ ->willReturn($message);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->with($this->userId, $mailboxId)
+ ->willReturn($mailbox);
$this->accountService->expects($this->once())
->method('find')
->with($this->equalTo($this->userId), $this->equalTo($accountId))
->will($this->returnValue($this->account));
$this->account->expects($this->once())
->method('getMailbox')
- ->with(base64_decode($folderId))
+ ->with('INBOX')
->will($this->returnValue($this->mailbox));
$this->mailbox->expects($this->once())
->method('getAttachment')
- ->with($messageId, $attachmentId)
+ ->with($uid, $attachmentId)
->will($this->returnValue($this->attachment));
$this->attachment->expects($this->once())
->method('getName')
@@ -291,30 +336,47 @@ class MessagesControllerTest extends TestCase {
->will($this->returnValue('abcdefg'));
$expected = new JSONResponse();
- $response = $this->controller->saveAttachment($accountId, $folderId,
- $messageId, $attachmentId, $targetPath);
+ $response = $this->controller->saveAttachment(
+ $id,
+ $attachmentId,
+ $targetPath
+ );
$this->assertEquals($expected, $response);
}
public function testSaveAllAttachments() {
$accountId = 17;
- $folderId = base64_encode('my folder');
- $messageId = 123;
+ $mailboxId = 987;
+ $id = 123;
+ $uid = 321;
$attachmentId = '0';
$targetPath = 'Downloads';
-
+ $message = new \OCA\Mail\Db\Message();
+ $message->setMailboxId($mailboxId);
+ $message->setUid($uid);
+ $mailbox = new \OCA\Mail\Db\Mailbox();
+ $mailbox->setName('INBOX');
+ $mailbox->setAccountId($accountId);
+ $this->mailManager->expects($this->once())
+ ->method('getMessage')
+ ->with($this->userId, $id)
+ ->willReturn($message);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->with($this->userId, $mailboxId)
+ ->willReturn($mailbox);
$this->accountService->expects($this->once())
->method('find')
->with($this->equalTo($this->userId), $this->equalTo($accountId))
->will($this->returnValue($this->account));
$this->account->expects($this->once())
->method('getMailbox')
- ->with(base64_decode($folderId))
+ ->with('INBOX')
->will($this->returnValue($this->mailbox));
$this->mailbox->expects($this->once())
->method('getMessage')
- ->with($messageId)
+ ->with($id)
->will($this->returnValue($this->message));
$this->message->attachments = [
[
@@ -324,7 +386,7 @@ class MessagesControllerTest extends TestCase {
$this->mailbox->expects($this->once())
->method('getAttachment')
- ->with($messageId, $attachmentId)
+ ->with($uid, $attachmentId)
->will($this->returnValue($this->attachment));
$this->attachment->expects($this->once())
->method('getName')
@@ -350,9 +412,7 @@ class MessagesControllerTest extends TestCase {
$expected = new JSONResponse();
$response = $this->controller->saveAttachment(
- $accountId,
- $folderId,
- $messageId,
+ $id,
$attachmentId,
$targetPath
);
@@ -362,25 +422,36 @@ class MessagesControllerTest extends TestCase {
public function testSetFlagsUnseen() {
$accountId = 17;
- $folderId = base64_encode('my folder');
- $messageId = 123;
+ $mailboxId = 987;
+ $id = 123;
$flags = [
'unseen' => false
];
-
+ $message = new \OCA\Mail\Db\Message();
+ $message->setUid(444);
+ $message->setMailboxId($mailboxId);
+ $mailbox = new \OCA\Mail\Db\Mailbox();
+ $mailbox->setName('INBOX');
+ $mailbox->setAccountId($accountId);
+ $this->mailManager->expects($this->once())
+ ->method('getMessage')
+ ->with($this->userId, $id)
+ ->willReturn($message);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->with($this->userId, $mailboxId)
+ ->willReturn($mailbox);
$this->accountService->expects($this->once())
->method('find')
->with($this->equalTo($this->userId), $this->equalTo($accountId))
->will($this->returnValue($this->account));
$this->mailManager->expects($this->once())
->method('flagMessage')
- ->with($this->account, 'my folder', $messageId, 'unseen', false);
+ ->with($this->account, 'INBOX', 444, 'unseen', false);
$expected = new JSONResponse();
$response = $this->controller->setFlags(
- $accountId,
- $folderId,
- $messageId,
+ $id,
$flags
);
@@ -389,25 +460,36 @@ class MessagesControllerTest extends TestCase {
public function testSetFlagsFlagged() {
$accountId = 17;
- $folderId = base64_encode('my folder');
- $messageId = 123;
+ $mailboxId = 987;
+ $id = 123;
$flags = [
'flagged' => true
];
-
+ $message = new \OCA\Mail\Db\Message();
+ $message->setUid(444);
+ $message->setMailboxId($mailboxId);
+ $mailbox = new \OCA\Mail\Db\Mailbox();
+ $mailbox->setName('INBOX');
+ $mailbox->setAccountId($accountId);
+ $this->mailManager->expects($this->once())
+ ->method('getMessage')
+ ->with($this->userId, $id)
+ ->willReturn($message);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->with($this->userId, $mailboxId)
+ ->willReturn($mailbox);
$this->accountService->expects($this->once())
->method('find')
->with($this->equalTo($this->userId), $this->equalTo($accountId))
->will($this->returnValue($this->account));
$this->mailManager->expects($this->once())
->method('flagMessage')
- ->with($this->account, 'my folder', $messageId, 'flagged', true);
+ ->with($this->account, 'INBOX', 444, 'flagged', true);
$expected = new JSONResponse();
$response = $this->controller->setFlags(
- $accountId,
- $folderId,
- $messageId,
+ $id,
$flags
);
@@ -416,27 +498,54 @@ class MessagesControllerTest extends TestCase {
public function testDestroy() {
$accountId = 17;
- $folderId = base64_encode('my folder');
- $messageId = 123;
-
+ $mailboxId = 987;
+ $id = 123;
+ $message = new \OCA\Mail\Db\Message();
+ $message->setUid(444);
+ $message->setMailboxId($mailboxId);
+ $mailbox = new \OCA\Mail\Db\Mailbox();
+ $mailbox->setName('INBOX');
+ $mailbox->setAccountId($accountId);
+ $this->mailManager->expects($this->once())
+ ->method('getMessage')
+ ->with($this->userId, $id)
+ ->willReturn($message);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->with($this->userId, $mailboxId)
+ ->willReturn($mailbox);
$this->accountService->expects($this->once())
->method('find')
->with($this->equalTo($this->userId), $this->equalTo($accountId))
->will($this->returnValue($this->account));
$this->mailManager->expects($this->once())
->method('deleteMessage')
- ->with($this->account, base64_decode($folderId), $messageId);
+ ->with($this->account, 'INBOX', 444);
$expected = new JSONResponse();
- $result = $this->controller->destroy($accountId, $folderId, $messageId);
+ $result = $this->controller->destroy($id);
$this->assertEquals($expected, $result);
}
public function testDestroyWithAccountNotFound() {
$accountId = 17;
- $folderId = base64_encode('my folder');
- $messageId = 123;
+ $mailboxId = 987;
+ $id = 123;
+ $message = new \OCA\Mail\Db\Message();
+ $message->setUid(444);
+ $message->setMailboxId($mailboxId);
+ $mailbox = new \OCA\Mail\Db\Mailbox();
+ $mailbox->setName('INBOX');
+ $mailbox->setAccountId($accountId);
+ $this->mailManager->expects($this->once())
+ ->method('getMessage')
+ ->with($this->userId, $id)
+ ->willReturn($message);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->with($this->userId, $mailboxId)
+ ->willReturn($mailbox);
$this->accountService->expects($this->once())
->method('find')
->with($this->equalTo($this->userId), $this->equalTo($accountId))
@@ -444,23 +553,37 @@ class MessagesControllerTest extends TestCase {
$expected = new JSONResponse(null, Http::STATUS_FORBIDDEN);
- $this->assertEquals($expected, $this->controller->destroy($accountId, $folderId, $messageId));
+ $this->assertEquals($expected, $this->controller->destroy($id));
}
public function testDestroyWithFolderOrMessageNotFound() {
$accountId = 17;
- $folderId = base64_encode('my folder');
- $messageId = 123;
+ $mailboxId = 987;
+ $id = 123;
+ $message = new \OCA\Mail\Db\Message();
+ $message->setUid(444);
+ $message->setMailboxId($mailboxId);
+ $mailbox = new \OCA\Mail\Db\Mailbox();
+ $mailbox->setName('INBOX');
+ $mailbox->setAccountId($accountId);
+ $this->mailManager->expects($this->once())
+ ->method('getMessage')
+ ->with($this->userId, $id)
+ ->willReturn($message);
+ $this->mailManager->expects($this->once())
+ ->method('getMailbox')
+ ->with($this->userId, $mailboxId)
+ ->willReturn($mailbox);
$this->accountService->expects($this->once())
->method('find')
->with($this->equalTo($this->userId), $this->equalTo($accountId))
->will($this->returnValue($this->account));
$this->mailManager->expects($this->once())
->method('deleteMessage')
- ->with($this->account, base64_decode($folderId), $messageId)
+ ->with($this->account, 'INBOX', 444)
->willThrowException(new ServiceException());
$this->expectException(ServiceException::class);
- $this->controller->destroy($accountId, $folderId, $messageId);
+ $this->controller->destroy($id);
}
}
diff --git a/tests/Unit/Controller/PageControllerTest.php b/tests/Unit/Controller/PageControllerTest.php
index b2ee973bb..cad8c87a3 100644
--- a/tests/Unit/Controller/PageControllerTest.php
+++ b/tests/Unit/Controller/PageControllerTest.php
@@ -173,7 +173,7 @@ class PageControllerTest extends TestCase {
'a11',
'a12',
],
- 'folders' => [
+ 'mailboxes' => [
[
'id' => 'inbox',
],
@@ -185,7 +185,7 @@ class PageControllerTest extends TestCase {
'a21',
'a22',
],
- 'folders' => [],
+ 'mailboxes' => [],
],
];
diff --git a/tests/Unit/Listener/DeleteDraftListenerTest.php b/tests/Unit/Listener/DeleteDraftListenerTest.php
index bafe771db..045214368 100644
--- a/tests/Unit/Listener/DeleteDraftListenerTest.php
+++ b/tests/Unit/Listener/DeleteDraftListenerTest.php
@@ -26,6 +26,7 @@ use ChristophWurst\Nextcloud\Testing\TestCase;
use OCA\Mail\Account;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\MailboxMapper;
+use OCA\Mail\Db\Message;
use OCA\Mail\Events\DraftSavedEvent;
use OCA\Mail\Events\MessageSentEvent;
use OCA\Mail\IMAP\IMAPClientFactory;
@@ -110,10 +111,13 @@ class DeleteDraftListenerTest extends TestCase {
$account = $this->createMock(Account::class);
/** @var NewMessageData|MockObject $newMessageData */
$newMessageData = $this->createMock(NewMessageData::class);
+ $draft = new Message();
+ $uid = 123;
+ $draft->setUid($uid);
$event = new DraftSavedEvent(
$account,
$newMessageData,
- 123
+ $draft
);
/** @var \Horde_Imap_Client_Socket|MockObject $client */
$client = $this->createMock(\Horde_Imap_Client_Socket::class);
@@ -149,7 +153,7 @@ class DeleteDraftListenerTest extends TestCase {
->with(
$client,
$mailbox,
- 123,
+ $uid,
\Horde_Imap_Client::FLAG_DELETED
);
$client->expects($this->once())
@@ -190,11 +194,14 @@ class DeleteDraftListenerTest extends TestCase {
$message = $this->createMock(IMessage::class);
/** @var \Horde_Mime_Mail|MockObject $mail */
$mail = $this->createMock(\Horde_Mime_Mail::class);
+ $draft = new Message();
+ $uid = 123;
+ $draft->setUid($uid);
$event = new MessageSentEvent(
$account,
$newMessageData,
$repliedMessageData,
- 123,
+ $draft,
$message,
$mail
);
@@ -215,7 +222,7 @@ class DeleteDraftListenerTest extends TestCase {
->with(
$client,
$mailbox,
- 123,
+ $uid,
\Horde_Imap_Client::FLAG_DELETED
);
$client->expects($this->once())
diff --git a/tests/Unit/Listener/DraftMailboxCreatorListenerTest.php b/tests/Unit/Listener/DraftMailboxCreatorListenerTest.php
index 885e6596c..b06063908 100644
--- a/tests/Unit/Listener/DraftMailboxCreatorListenerTest.php
+++ b/tests/Unit/Listener/DraftMailboxCreatorListenerTest.php
@@ -29,6 +29,7 @@ use ChristophWurst\Nextcloud\Testing\TestCase;
use OCA\Mail\Account;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\MailboxMapper;
+use OCA\Mail\Db\Message;
use OCA\Mail\Events\SaveDraftEvent;
use OCA\Mail\IMAP\IMAPClientFactory;
use OCA\Mail\IMAP\MailboxSync;
@@ -85,10 +86,12 @@ class DraftMailboxCreatorListenerTest extends TestCase {
$account = $this->createMock(Account::class);
/** @var NewMessageData|MockObject $newMessageData */
$newMessageData = $this->createMock(NewMessageData::class);
+ $draft = new Message();
+ $draft->setUid(123);
$event = new SaveDraftEvent(
$account,
$newMessageData,
- 123
+ $draft
);
/** @var \Horde_Imap_Client_Socket|MockObject $client */
$client = $this->createMock(\Horde_Imap_Client_Socket::class);
@@ -113,10 +116,12 @@ class DraftMailboxCreatorListenerTest extends TestCase {
$account = $this->createMock(Account::class);
/** @var NewMessageData|MockObject $newMessageData */
$newMessageData = $this->createMock(NewMessageData::class);
+ $draft = new Message();
+ $draft->setUid(123);
$event = new SaveDraftEvent(
$account,
$newMessageData,
- 123
+ $draft
);
/** @var \Horde_Imap_Client_Socket|MockObject $client */
$client = $this->createMock(\Horde_Imap_Client_Socket::class);
diff --git a/tests/Unit/Listener/FlagRepliedMessageListenerTest.php b/tests/Unit/Listener/FlagRepliedMessageListenerTest.php
index fae3b3705..151965aa7 100644
--- a/tests/Unit/Listener/FlagRepliedMessageListenerTest.php
+++ b/tests/Unit/Listener/FlagRepliedMessageListenerTest.php
@@ -29,6 +29,7 @@ use ChristophWurst\Nextcloud\Testing\TestCase;
use OCA\Mail\Account;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\MailboxMapper;
+use OCA\Mail\Db\Message;
use OCA\Mail\Events\MessageSentEvent;
use OCA\Mail\IMAP\IMAPClientFactory;
use OCA\Mail\IMAP\MessageMapper;
@@ -91,11 +92,13 @@ class FlagRepliedMessageListenerTest extends TestCase {
$message = $this->createMock(IMessage::class);
/** @var \Horde_Mime_Mail|MockObject $mail */
$mail = $this->createMock(\Horde_Mime_Mail::class);
+ $draft = new Message();
+ $draft->setUid(123);
$event = new MessageSentEvent(
$account,
$newMessageData,
null,
- 123,
+ $draft,
$message,
$mail
);
@@ -118,11 +121,13 @@ class FlagRepliedMessageListenerTest extends TestCase {
$message = $this->createMock(IMessage::class);
/** @var \Horde_Mime_Mail|MockObject $mail */
$mail = $this->createMock(\Horde_Mime_Mail::class);
+ $draft = new Message();
+ $draft->setUid(123);
$event = new MessageSentEvent(
$account,
$newMessageData,
$repliedMessageData,
- 123,
+ $draft,
$message,
$mail
);
@@ -152,11 +157,13 @@ class FlagRepliedMessageListenerTest extends TestCase {
$message = $this->createMock(IMessage::class);
/** @var \Horde_Mime_Mail|MockObject $mail */
$mail = $this->createMock(\Horde_Mime_Mail::class);
+ $draft = new Message();
+ $draft->setUid(123);
$event = new MessageSentEvent(
$account,
$newMessageData,
$repliedMessageData,
- 123,
+ $draft,
$message,
$mail
);
diff --git a/tests/Unit/Listener/SaveSentMessageListenerTest.php b/tests/Unit/Listener/SaveSentMessageListenerTest.php
index b5a443c03..85da65b6f 100644
--- a/tests/Unit/Listener/SaveSentMessageListenerTest.php
+++ b/tests/Unit/Listener/SaveSentMessageListenerTest.php
@@ -29,6 +29,7 @@ use ChristophWurst\Nextcloud\Testing\TestCase;
use OCA\Mail\Account;
use OCA\Mail\Db\Mailbox;
use OCA\Mail\Db\MailboxMapper;
+use OCA\Mail\Db\Message;
use OCA\Mail\Events\MessageSentEvent;
use OCA\Mail\Exception\ServiceException;
use OCA\Mail\IMAP\IMAPClientFactory;
@@ -101,11 +102,13 @@ class SaveSentMessageListenerTest extends TestCase {
$message = $this->createMock(IMessage::class);
/** @var \Horde_Mime_Mail|MockObject $mail */
$mail = $this->createMock(\Horde_Mime_Mail::class);
+ $draft = new Message();
+ $draft->setUid(123);
$event = new MessageSentEvent(
$account,
$newMessageData,
$repliedMessageData,
- 123,
+ $draft,
$message,
$mail
);
@@ -153,11 +156,13 @@ class SaveSentMessageListenerTest extends TestCase {
$message = $this->createMock(IMessage::class);
/** @var \Horde_Mime_Mail|MockObject $mail */
$mail = $this->createMock(\Horde_Mime_Mail::class);
+ $draft = new Message();
+ $draft->setUid(123);
$event = new MessageSentEvent(
$account,
$newMessageData,
$repliedMessageData,
- 123,
+ $draft,
$message,
$mail
);
@@ -207,11 +212,13 @@ class SaveSentMessageListenerTest extends TestCase {
$message = $this->createMock(IMessage::class);
/** @var \Horde_Mime_Mail|MockObject $mail */
$mail = $this->createMock(\Horde_Mime_Mail::class);
+ $draft = new Message();
+ $draft->setUid(123);
$event = new MessageSentEvent(
$account,
$newMessageData,
$repliedMessageData,
- 123,
+ $draft,
$message,
$mail
);
@@ -244,11 +251,13 @@ class SaveSentMessageListenerTest extends TestCase {
$message = $this->createMock(IMessage::class);
/** @var \Horde_Mime_Mail|MockObject $mail */
$mail = $this->createMock(\Horde_Mime_Mail::class);
+ $draft = new Message();
+ $draft->setUid(123);
$event = new MessageSentEvent(
$account,
$newMessageData,
$repliedMessageData,
- 123,
+ $draft,
$message,
$mail
);
diff --git a/tests/Unit/Model/IMAPMessageTest.php b/tests/Unit/Model/IMAPMessageTest.php
index fb0a7c5b4..657b997f8 100644
--- a/tests/Unit/Model/IMAPMessageTest.php
+++ b/tests/Unit/Model/IMAPMessageTest.php
@@ -74,7 +74,7 @@ class IMAPMessageTest extends TestCase {
$message = new IMAPMessage($conn, 'INBOX', 123, null, true, $htmlService);
- $htmlBody = $message->getHtmlBody(0, 0, 123);
+ $htmlBody = $message->getHtmlBody(123);
$this->assertTrue(strlen($htmlBody) > 1000);
$plainTextBody = $message->getPlainBody();
diff --git a/tests/Unit/Service/MailManagerTest.php b/tests/Unit/Service/MailManagerTest.php
index 521726575..eaac0a94e 100644
--- a/tests/Unit/Service/MailManagerTest.php
+++ b/tests/Unit/Service/MailManagerTest.php
@@ -127,10 +127,15 @@ class MailManagerTest extends TestCase {
$this->folderMapper->expects($this->once())
->method('detectFolderSpecialUse')
->with($this->equalTo([$folder]));
+ $mailbox = new Mailbox();
+ $this->mailboxMapper->expects($this->once())
+ ->method('find')
+ ->with($account, 'new')
+ ->willReturn($mailbox);
- $created = $this->manager->createFolder($account, 'new');
+ $created = $this->manager->createMailbox($account, 'new');
- $this->assertEquals($folder, $created);
+ $this->assertEquals($mailbox, $created);
}
public function testGetFolderStats() {
@@ -144,8 +149,13 @@ class MailManagerTest extends TestCase {
->method('getFoldersStatusAsObject')
->with($this->equalTo($client), $this->equalTo('INBOX'))
->willReturn($stats);
+ $mailbox = new Mailbox();
+ $mailbox->setName('INBOX');
- $actual = $this->manager->getFolderStats($account, 'INBOX');
+ $actual = $this->manager->getMailboxStats(
+ $account,
+ $mailbox
+ );
$this->assertEquals($stats, $actual);
}
diff --git a/tests/Unit/Service/MailTransmissionTest.php b/tests/Unit/Service/MailTransmissionTest.php
index b50f32930..796dd7f63 100644
--- a/tests/Unit/Service/MailTransmissionTest.php
+++ b/tests/Unit/Service/MailTransmissionTest.php
@@ -245,7 +245,7 @@ class MailTransmissionTest extends TestCase {
->with($client, $draftsMailbox, $this->anything())
->willReturn(13);
- $newId = $this->transmission->saveDraft($messageData);
+ [,,$newId] = $this->transmission->saveDraft($messageData);
$this->assertEquals(13, $newId);
}
diff --git a/tests/Unit/Service/Search/MailSearchTest.php b/tests/Unit/Service/Search/MailSearchTest.php
index 107a0ef32..453685146 100644
--- a/tests/Unit/Service/Search/MailSearchTest.php
+++ b/tests/Unit/Service/Search/MailSearchTest.php
@@ -89,14 +89,11 @@ class MailSearchTest extends TestCase {
$mailbox = new Mailbox();
$mailbox->setSyncNewToken('abc');
$mailbox->setSyncChangedToken('def');
- $this->mailboxMapper->expects($this->once())
- ->method('find')
- ->willReturn($mailbox);
$this->expectException(MailboxNotCachedException::class);
$this->search->findMessages(
$account,
- 'INBOX',
+ $mailbox,
null,
null,
null
@@ -107,14 +104,11 @@ class MailSearchTest extends TestCase {
$account = $this->createMock(Account::class);
$mailbox = new Mailbox();
$mailbox->setSyncNewLock(123);
- $this->mailboxMapper->expects($this->once())
- ->method('find')
- ->willReturn($mailbox);
$this->expectException(MailboxLockedException::class);
$this->search->findMessages(
$account,
- 'INBOX',
+ $mailbox,
null,
null,
null
@@ -127,13 +121,10 @@ class MailSearchTest extends TestCase {
$mailbox->setSyncNewToken('abc');
$mailbox->setSyncChangedToken('def');
$mailbox->setSyncVanishedToken('ghi');
- $this->mailboxMapper->expects($this->once())
- ->method('find')
- ->willReturn($mailbox);
$messages = $this->search->findMessages(
$account,
- 'INBOX',
+ $mailbox,
null,
null,
null
@@ -148,9 +139,6 @@ class MailSearchTest extends TestCase {
$mailbox->setSyncNewToken('abc');
$mailbox->setSyncChangedToken('def');
$mailbox->setSyncVanishedToken('ghi');
- $this->mailboxMapper->expects($this->once())
- ->method('find')
- ->willReturn($mailbox);
$query = new SearchQuery();
$query->addFlag('seen');
$this->filterStringParser->expects($this->once())
@@ -158,11 +146,7 @@ class MailSearchTest extends TestCase {
->with('my search')
->willReturn($query);
$this->messageMapper->expects($this->once())
- ->method('findUidsByQuery')
- ->with($mailbox, $query, null)
- ->willReturn([1, 2]);
- $this->messageMapper->expects($this->once())
- ->method('findByUids')
+ ->method('findByIds')
->willReturn([
$this->createMock(Message::class),
$this->createMock(Message::class),
@@ -175,7 +159,7 @@ class MailSearchTest extends TestCase {
$messages = $this->search->findMessages(
$account,
- 'INBOX',
+ $mailbox,
'my search',
null,
null
@@ -190,9 +174,6 @@ class MailSearchTest extends TestCase {
$mailbox->setSyncNewToken('abc');
$mailbox->setSyncChangedToken('def');
$mailbox->setSyncVanishedToken('ghi');
- $this->mailboxMapper->expects($this->once())
- ->method('find')
- ->willReturn($mailbox);
$query = new SearchQuery();
$query->addTextToken('my');
$query->addTextToken('search');
@@ -205,11 +186,7 @@ class MailSearchTest extends TestCase {
->with($account, $mailbox, $query)
->willReturn([2, 3]);
$this->messageMapper->expects($this->once())
- ->method('findUidsByQuery')
- ->with($mailbox, $query, null, [2, 3])
- ->willReturn([1, 2]);
- $this->messageMapper->expects($this->once())
- ->method('findByUids')
+ ->method('findByIds')
->willReturn([
$this->createMock(Message::class),
$this->createMock(Message::class),
@@ -220,7 +197,7 @@ class MailSearchTest extends TestCase {
$messages = $this->search->findMessages(
$account,
- 'INBOX',
+ $mailbox,
'my search',
null,
null