diff --git a/lib/Db/Message.php b/lib/Db/Message.php
index 14f3c4dc2b..0a4bdc9726 100644
--- a/lib/Db/Message.php
+++ b/lib/Db/Message.php
@@ -142,6 +142,8 @@ class Message extends Entity implements JsonSerializable {
/** @var bool */
private $fetchAvatarFromClient = false;
+ /** @var array */
+ private $attachments = [];
public function __construct() {
$this->from = new AddressList([]);
@@ -312,6 +314,14 @@ public function getAvatar(): ?Avatar {
return $this->avatar;
}
+ public function setAttachments(array $attachments): void {
+ $this->attachments = $attachments;
+ }
+
+ public function getAttachments(): array {
+ return $this->attachments;
+ }
+
#[\Override]
#[ReturnTypeWillChange]
public function jsonSerialize() {
@@ -357,6 +367,7 @@ public function jsonSerialize() {
'mentionsMe' => $this->getMentionsMe(),
'avatar' => $this->avatar?->jsonSerialize(),
'fetchAvatarFromClient' => $this->fetchAvatarFromClient,
+ 'attachments' => $this->getAttachments(),
];
}
}
diff --git a/lib/IMAP/PreviewEnhancer.php b/lib/IMAP/PreviewEnhancer.php
index 89f9f7c999..0021be7cdd 100644
--- a/lib/IMAP/PreviewEnhancer.php
+++ b/lib/IMAP/PreviewEnhancer.php
@@ -15,6 +15,7 @@
use OCA\Mail\Db\Message;
use OCA\Mail\Db\MessageMapper as DbMapper;
use OCA\Mail\IMAP\MessageMapper as ImapMapper;
+use OCA\Mail\Service\Attachment\AttachmentService;
use OCA\Mail\Service\Avatar\Avatar;
use OCA\Mail\Service\AvatarService;
use Psr\Log\LoggerInterface;
@@ -39,11 +40,14 @@ class PreviewEnhancer {
/** @var AvatarService */
private $avatarService;
- public function __construct(IMAPClientFactory $clientFactory,
+ public function __construct(
+ IMAPClientFactory $clientFactory,
ImapMapper $imapMapper,
DbMapper $dbMapper,
LoggerInterface $logger,
- AvatarService $avatarService) {
+ AvatarService $avatarService,
+ private AttachmentService $attachmentService,
+ ) {
$this->clientFactory = $clientFactory;
$this->imapMapper = $imapMapper;
$this->mapper = $dbMapper;
@@ -65,6 +69,12 @@ public function process(Account $account, Mailbox $mailbox, array $messages, boo
return array_merge($carry, [$message->getUid()]);
}, []);
+ $client = $this->clientFactory->getClient($account);
+
+ foreach ($messages as $message) {
+ $attachments = $this->attachmentService->getAttachmentNames($account, $mailbox, $message, $client);
+ $message->setAttachments($attachments);
+ }
if ($preLoadAvatars) {
foreach ($messages as $message) {
@@ -87,7 +97,7 @@ public function process(Account $account, Mailbox $mailbox, array $messages, boo
return $messages;
}
- $client = $this->clientFactory->getClient($account);
+
try {
$data = $this->imapMapper->getBodyStructureData(
$client,
diff --git a/lib/Model/IMAPMessage.php b/lib/Model/IMAPMessage.php
index ec7cdd95e0..70ad9ae8d5 100644
--- a/lib/Model/IMAPMessage.php
+++ b/lib/Model/IMAPMessage.php
@@ -287,6 +287,7 @@ public function getSentDate(): Horde_Imap_Client_DateTime {
return $this->imapDate;
}
+
/**
* @param int $id
*
@@ -386,7 +387,7 @@ public function setContent(string $content) {
*/
#[\Override]
public function getAttachments(): array {
- throw new Exception('not implemented');
+ return $this->attachments;
}
/**
diff --git a/lib/Service/Attachment/AttachmentService.php b/lib/Service/Attachment/AttachmentService.php
index 6bc208de3e..7f9991ae04 100644
--- a/lib/Service/Attachment/AttachmentService.php
+++ b/lib/Service/Attachment/AttachmentService.php
@@ -18,7 +18,10 @@
use OCA\Mail\Db\LocalAttachment;
use OCA\Mail\Db\LocalAttachmentMapper;
use OCA\Mail\Db\LocalMessage;
+use OCA\Mail\Db\Mailbox;
+use OCA\Mail\Db\Message;
use OCA\Mail\Exception\AttachmentNotFoundException;
+use OCA\Mail\Exception\ServiceException;
use OCA\Mail\Exception\UploadException;
use OCA\Mail\IMAP\MessageMapper;
use OCP\AppFramework\Db\DoesNotExistException;
@@ -26,6 +29,7 @@
use OCP\Files\Folder;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
+use OCP\ICacheFactory;
use Psr\Log\LoggerInterface;
class AttachmentService implements IAttachmentService {
@@ -51,6 +55,10 @@ class AttachmentService implements IAttachmentService {
* @var LoggerInterface
*/
private $logger;
+ /**
+ * @var ICache
+ */
+ private $cache;
/**
* @param Folder $userFolder
@@ -60,6 +68,7 @@ public function __construct($userFolder,
AttachmentStorage $storage,
IMailManager $mailManager,
MessageMapper $imapMessageMapper,
+ ICacheFactory $cacheFactory,
LoggerInterface $logger) {
$this->mapper = $mapper;
$this->storage = $storage;
@@ -67,6 +76,7 @@ public function __construct($userFolder,
$this->messageMapper = $imapMessageMapper;
$this->userFolder = $userFolder;
$this->logger = $logger;
+ $this->cache = $cacheFactory->createLocal('mail.attachment_names');
}
/**
@@ -247,6 +257,32 @@ public function handleAttachments(Account $account, array $attachments, \Horde_I
return array_values(array_filter($attachmentIds));
}
+ public function getAttachmentNames(Account $account, Mailbox $mailbox, Message $message, \Horde_Imap_Client_Socket $client): array {
+ $attachments = [];
+ $uniqueCacheId = $account->getUserId() . $account->getId() . $mailbox->getId() . $message->getUid();
+ $cached = $this->cache->get($uniqueCacheId);
+ if ($cached) {
+ return $cached;
+ }
+ try {
+ $imapMessage = $this->mailManager->getImapMessage(
+ $client,
+ $account,
+ $mailbox,
+ $message->getUid(),
+ true
+ );
+ $attachments = $imapMessage->getAttachments();
+ } catch (ServiceException $e) {
+ $this->logger->error('Could not get attachment names', ['exception' => $e, 'messageId' => $message->getUid()]);
+ }
+ $result = array_map(static function (array $attachment) {
+ return ['name' => $attachment['fileName'],'mime' => $attachment['mime']];
+ }, $attachments);
+ $this->cache->set($uniqueCacheId, $result);
+ return $result;
+ }
+
/**
* Add a message as attachment
*
diff --git a/src/components/AttachmentTag.vue b/src/components/AttachmentTag.vue
new file mode 100644
index 0000000000..cf8c7aad1f
--- /dev/null
+++ b/src/components/AttachmentTag.vue
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
diff --git a/src/components/Envelope.vue b/src/components/Envelope.vue
index 60ae0a6343..01d3b64536 100644
--- a/src/components/Envelope.vue
+++ b/src/components/Envelope.vue
@@ -399,8 +399,10 @@
{{ translateTagDisplayName(tag) }}
-
+
+
+ (envelope?.attachments)).flat()
+ },
draggableLabel() {
let label = this.data.subject
const sender = this.data.from[0]?.label ?? this.data.from[0]?.email
diff --git a/src/components/icons/FileIcon.vue b/src/components/icons/FileIcon.vue
new file mode 100644
index 0000000000..2ec4c0b8f1
--- /dev/null
+++ b/src/components/icons/FileIcon.vue
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/store/constants.js b/src/store/constants.js
index d34e342e58..ee76ba8f4e 100644
--- a/src/store/constants.js
+++ b/src/store/constants.js
@@ -18,3 +18,6 @@ export const STATUS_IMAP_SENT_MAILBOX_FAIL = 11
export const STATUS_SMTP_ERROR = 13
export const FOLLOW_UP_TAG_LABEL = '$follow_up'
+export const FILE_EXTENSIONS_WORD_PROCESSING = ['doc', 'docx', 'dot', 'odt', 'dotx', 'odt', 'ott']
+export const FILE_EXTENSIONS_SPREADSHEET = ['xls', 'xlsx', 'ods']
+export const FILE_EXTENSIONS_PRESENTATION = ['ppt', 'pptx', 'odp', 'otp', 'pps', 'ppsx', 'pot', 'potx']