From 185eb96876f07d7eb1b039143fca23be577b5c9c Mon Sep 17 00:00:00 2001 From: Hamza Date: Thu, 28 Aug 2025 17:28:07 +0100 Subject: [PATCH 1/2] enh: provide attachement names for messages Signed-off-by: Hamza --- lib/Contracts/IAttachmentService.php | 1 + lib/Db/Message.php | 11 ++++++ lib/IMAP/PreviewEnhancer.php | 16 +++++++-- lib/Model/IMAPMessage.php | 3 +- lib/Service/Attachment/AttachmentService.php | 35 ++++++++++++++++++++ 5 files changed, 62 insertions(+), 4 deletions(-) diff --git a/lib/Contracts/IAttachmentService.php b/lib/Contracts/IAttachmentService.php index 38d6ee9a4f..243cdd186a 100644 --- a/lib/Contracts/IAttachmentService.php +++ b/lib/Contracts/IAttachmentService.php @@ -34,4 +34,5 @@ public function getAttachment(string $userId, int $id): array; * @param int $id */ public function deleteAttachment(string $userId, int $id); + } diff --git a/lib/Db/Message.php b/lib/Db/Message.php index 0972915b85..e7e1f0a222 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() { @@ -359,6 +369,7 @@ static function (Tag $tag) { '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 eadc094cac..36a1cc2d80 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 3a973492f7..003c0add40 100644 --- a/lib/Model/IMAPMessage.php +++ b/lib/Model/IMAPMessage.php @@ -283,6 +283,7 @@ public function getSentDate(): Horde_Imap_Client_DateTime { return $this->imapDate; } + /** * @param int $id * @@ -384,7 +385,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 97655a09af..6799950314 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'); } /** @@ -249,6 +259,31 @@ 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 = []; + $cached = $this->cache->get($message->getUid()); + 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 $attachment['fileName']; + }, $attachments); + $this->cache->set($message->getUid(), $result); + return $result; + } + /** * Add a message as attachment * From 0ddc79c3cbec5f6970e888bdd89adaf18f5e9cfe Mon Sep 17 00:00:00 2001 From: Hamza Date: Fri, 29 Aug 2025 12:03:16 +0100 Subject: [PATCH 2/2] fixup! enh: provide attachement names for messages Signed-off-by: Hamza --- lib/Service/Attachment/AttachmentService.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/Service/Attachment/AttachmentService.php b/lib/Service/Attachment/AttachmentService.php index 6799950314..dd3abe9ca5 100644 --- a/lib/Service/Attachment/AttachmentService.php +++ b/lib/Service/Attachment/AttachmentService.php @@ -261,7 +261,8 @@ public function handleAttachments(Account $account, array $attachments, \Horde_I public function getAttachmentNames(Account $account, Mailbox $mailbox, Message $message, \Horde_Imap_Client_Socket $client): array { $attachments = []; - $cached = $this->cache->get($message->getUid()); + $uniqueCacheId = $account->getUserId() . $account->getId() . $mailbox->getId() . $message->getUid(); + $cached = $this->cache->get($uniqueCacheId); if ($cached) { return $cached; } @@ -278,9 +279,9 @@ public function getAttachmentNames(Account $account, Mailbox $mailbox, Message $ $this->logger->error('Could not get attachment names', ['exception' => $e, 'messageId' => $message->getUid()]); } $result = array_map(static function (array $attachment) { - return $attachment['fileName']; + return ['name' => $attachment['fileName'],'mime' => $attachment['mime']]; }, $attachments); - $this->cache->set($message->getUid(), $result); + $this->cache->set($uniqueCacheId, $result); return $result; }