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.php5
-rwxr-xr-xlib/Controller/MessagesController.php32
-rw-r--r--lib/Service/ItineraryService.php28
-rw-r--r--src/components/Message.vue8
-rw-r--r--src/components/ThreadEnvelope.vue25
-rw-r--r--src/service/MessageService.js17
-rw-r--r--src/store/actions.js10
-rw-r--r--src/store/mutations.js8
8 files changed, 113 insertions, 20 deletions
diff --git a/appinfo/routes.php b/appinfo/routes.php
index 6242fe0e2..39b1bf824 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -175,6 +175,11 @@ return [
'verb' => 'GET'
],
[
+ 'name' => 'messages#getItineraries',
+ 'url' => '/api/messages/{id}/itineraries',
+ 'verb' => 'GET'
+ ],
+ [
'name' => 'messages#getSource',
'url' => '/api/messages/{id}/source',
'verb' => 'GET'
diff --git a/lib/Controller/MessagesController.php b/lib/Controller/MessagesController.php
index e3cc7a3e7..f2f083d38 100755
--- a/lib/Controller/MessagesController.php
+++ b/lib/Controller/MessagesController.php
@@ -11,6 +11,7 @@ declare(strict_types=1);
* @author Lukas Reschke <lukas@owncloud.com>
* @author Thomas Imbreckx <zinks@iozero.be>
* @author Thomas Müller <thomas.mueller@tmit.eu>
+ * @author Richard Steinmetz <richard@steinmetz.cloud>
*
* Mail
*
@@ -248,11 +249,10 @@ class MessagesController extends Controller {
$message->getUid(),
true
)->getFullMessage($id);
- $json['itineraries'] = $this->itineraryService->extract(
- $account,
- $mailbox->getName(),
- $message->getUid()
- );
+ $itineraries = $this->itineraryService->getCached($account, $mailbox, $message->getUid());
+ if ($itineraries) {
+ $json['itineraries'] = $itineraries;
+ }
$json['attachments'] = array_map(function ($a) use ($id) {
return $this->enrichDownloadUrl(
$id,
@@ -272,6 +272,28 @@ class MessagesController extends Controller {
return $response;
}
+ /**
+ * @NoAdminRequired
+ * @TrapError
+ *
+ * @param int $id
+ *
+ * @return JSONResponse
+ *
+ * @throws ClientException
+ */
+ public function getItineraries(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([], Http::STATUS_FORBIDDEN);
+ }
+
+ return new JsonResponse($this->itineraryService->extract($account, $mailbox, $message->getUid()));
+ }
+
private function isSenderTrusted(Message $message): bool {
$from = $message->getFrom();
$first = $from->first();
diff --git a/lib/Service/ItineraryService.php b/lib/Service/ItineraryService.php
index a4c0ee7bd..b7fd29acc 100644
--- a/lib/Service/ItineraryService.php
+++ b/lib/Service/ItineraryService.php
@@ -6,6 +6,7 @@ declare(strict_types=1);
* @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ * @author 2021 Richard Steinmetz <richard@steinmetz.cloud>
*
* @license GNU AGPL version 3 or any later version
*
@@ -27,7 +28,7 @@ namespace OCA\Mail\Service;
use ChristophWurst\KItinerary\Itinerary;
use OCA\Mail\Account;
-use OCA\Mail\Db\MailboxMapper;
+use OCA\Mail\Db\Mailbox;
use OCA\Mail\IMAP\IMAPClientFactory;
use OCA\Mail\IMAP\MessageMapper;
use OCA\Mail\Integration\KItinerary\ItineraryExtractor;
@@ -43,9 +44,6 @@ class ItineraryService {
/** @var IMAPClientFactory */
private $clientFactory;
- /** @var MailboxMapper */
- private $mailboxMapper;
-
/** @var MessageMapper */
private $messageMapper;
@@ -59,27 +57,34 @@ class ItineraryService {
private $logger;
public function __construct(IMAPClientFactory $clientFactory,
- MailboxMapper $mailboxMapper,
MessageMapper $messageMapper,
ItineraryExtractor $extractor,
ICacheFactory $cacheFactory,
LoggerInterface $logger) {
$this->clientFactory = $clientFactory;
- $this->mailboxMapper = $mailboxMapper;
$this->messageMapper = $messageMapper;
$this->extractor = $extractor;
$this->cache = $cacheFactory->createLocal();
$this->logger = $logger;
}
- public function extract(Account $account, string $mailbox, int $id): Itinerary {
- $mailbox = $this->mailboxMapper->find($account, $mailbox);
+ private function buildCacheKey(Account $account, Mailbox $mailbox, int $id): string {
+ return 'mail_itinerary_' . $account->getId() . '_' . $mailbox->getName() . '_' . $id;
+ }
- $cacheKey = 'mail_itinerary_' . $account->getId() . '_' . $mailbox->getName() . '_' . $id;
- if ($cached = ($this->cache->get($cacheKey))) {
+ public function getCached(Account $account, Mailbox $mailbox, int $id): ?Itinerary {
+ if ($cached = ($this->cache->get($this->buildCacheKey($account, $mailbox, $id)))) {
return Itinerary::fromJson($cached);
}
+ return null;
+ }
+
+ public function extract(Account $account, Mailbox $mailbox, int $id): Itinerary {
+ if ($cached = ($this->getCached($account, $mailbox, $id))) {
+ return $cached;
+ }
+
$client = $this->clientFactory->getClient($account);
$itinerary = new Itinerary();
@@ -104,7 +109,8 @@ class ItineraryService {
$final = $this->extractor->extract(json_encode($itinerary));
$this->logger->debug('Reduced ' . count($itinerary) . ' itinerary entries to ' . count($final) . ' entries');
- $this->cache->set($cacheKey, json_encode($final));
+ $cache_key = $this->buildCacheKey($account, $mailbox, $id);
+ $this->cache->set($cache_key, json_encode($final));
return $final;
}
diff --git a/src/components/Message.vue b/src/components/Message.vue
index 8be67c500..d059296d0 100644
--- a/src/components/Message.vue
+++ b/src/components/Message.vue
@@ -2,6 +2,7 @@
- @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
-
- @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ - @author 2021 Richard Steinmetz <richard@steinmetz.cloud>
-
- @license GNU AGPL version 3 or any later version
-
@@ -23,8 +24,8 @@
<div :class="[message.hasHtmlBody ? 'mail-message-body mail-message-body-html' : 'mail-message-body']"
role="region"
:aria-label="t('mail','Message body')">
- <div v-if="message.itineraries.length > 0" class="message-itinerary">
- <Itinerary :entries="message.itineraries" :message-id="message.messageId" />
+ <div v-if="itineraries.length > 0" class="message-itinerary">
+ <Itinerary :entries="itineraries" :message-id="message.messageId" />
</div>
<MessageHTMLBody v-if="message.hasHtmlBody"
:url="htmlUrl"
@@ -90,6 +91,9 @@ export default {
isEncrypted() {
return isPgpgMessage(this.message.hasHtmlBody ? html(this.message.body) : plain(this.message.body))
},
+ itineraries() {
+ return this.message.itineraries ?? []
+ },
},
}
</script>
diff --git a/src/components/ThreadEnvelope.vue b/src/components/ThreadEnvelope.vue
index a1a7e6fda..08b913961 100644
--- a/src/components/ThreadEnvelope.vue
+++ b/src/components/ThreadEnvelope.vue
@@ -2,6 +2,7 @@
- @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
-
- @author 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
+ - @author 2021 Richard Steinmetz <richard@steinmetz.cloud>
-
- @license GNU AGPL version 3 or any later version
-
@@ -255,8 +256,8 @@ export default {
logger.debug(`fetching thread message ${this.envelope.databaseId}`)
try {
- const message = this.message = await this.$store.dispatch('fetchMessage', this.envelope.databaseId)
- logger.debug(`message ${this.envelope.databaseId} fetched`, { message })
+ this.message = await this.$store.dispatch('fetchMessage', this.envelope.databaseId)
+ logger.debug(`message ${this.envelope.databaseId} fetched`, { message: this.message })
if (!this.envelope.flags.seen) {
logger.info('Starting timer to mark message as seen/read')
@@ -270,6 +271,26 @@ export default {
} catch (error) {
logger.error('Could not fetch message', { error })
}
+
+ // Fetch itineraries if they haven't been included in the message data
+ if (this.message && !this.message.itineraries) {
+ await this.fetchItineraries()
+ }
+ },
+ async fetchItineraries() {
+ // Sanity check before actually making the request
+ if (!this.message.hasHtmlBody && this.message.attachments.length === 0) {
+ return
+ }
+
+ logger.debug(`Fetching itineraries for message ${this.envelope.databaseId}`)
+
+ try {
+ const itineraries = await this.$store.dispatch('fetchItineraries', this.envelope.databaseId)
+ logger.debug(`Itineraries of message ${this.envelope.databaseId} fetched`, { itineraries })
+ } catch (error) {
+ logger.error(`Could not fetch itineraries of message ${this.envelope.databaseId}`, { error })
+ }
},
scrollToCurrentEnvelope() {
// Account for global navigation bar and thread header
diff --git a/src/service/MessageService.js b/src/service/MessageService.js
index 049227243..8473ae56b 100644
--- a/src/service/MessageService.js
+++ b/src/service/MessageService.js
@@ -166,6 +166,23 @@ export async function fetchMessage(id) {
}
}
+export async function fetchMessageItineraries(id) {
+ const url = generateUrl('/apps/mail/api/messages/{id}/itineraries', {
+ id,
+ })
+
+ 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) {
const url = generateUrl('/apps/mail/api/accounts/{accountId}/draft', {
accountId,
diff --git a/src/store/actions.js b/src/store/actions.js
index ee3d99032..3bc0ea0da 100644
--- a/src/store/actions.js
+++ b/src/store/actions.js
@@ -2,6 +2,7 @@
* @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ * @author 2021 Richard Steinmetz <richard@steinmetz.cloud>
*
* @license GNU AGPL version 3 or any later version
*
@@ -63,6 +64,7 @@ import {
fetchEnvelope,
fetchEnvelopes,
fetchMessage,
+ fetchMessageItineraries,
fetchThread,
moveMessage,
removeEnvelopeTag,
@@ -751,6 +753,14 @@ export default {
}
return message
},
+ async fetchItineraries({ commit }, id) {
+ const itineraries = await fetchMessageItineraries(id)
+ commit('addMessageItineraries', {
+ id,
+ itineraries,
+ })
+ return itineraries
+ },
async deleteMessage({ getters, commit }, { id }) {
commit('removeEnvelope', { id })
diff --git a/src/store/mutations.js b/src/store/mutations.js
index f6fdd76b0..cfe22fb6b 100644
--- a/src/store/mutations.js
+++ b/src/store/mutations.js
@@ -2,6 +2,7 @@
* @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
+ * @author 2021 Richard Steinmetz <richard@steinmetz.cloud>
*
* @license GNU AGPL version 3 or any later version
*
@@ -300,6 +301,13 @@ export default {
addMessage(state, { message }) {
Vue.set(state.messages, message.databaseId, message)
},
+ addMessageItineraries(state, { id, itineraries }) {
+ const message = state.messages[id]
+ if (!message) {
+ return
+ }
+ Vue.set(message, 'itineraries', itineraries)
+ },
addEnvelopeThread(state, { id, thread }) {
// Store the envelopes, merge into any existing object if one exists
thread.forEach(e => {