1<?php 2 3declare(strict_types=1); 4 5/** 6 * @author Alexander Weidinger <alexwegoo@gmail.com> 7 * @author Christoph Wurst <christoph@winzerhof-wurst.at> 8 * @author Christoph Wurst <wurst.christoph@gmail.com> 9 * @author Jakob Sack <jakob@owncloud.org> 10 * @author Jan-Christoph Borchardt <hey@jancborchardt.net> 11 * @author Lukas Reschke <lukas@owncloud.com> 12 * @author Thomas Imbreckx <zinks@iozero.be> 13 * @author Thomas Müller <thomas.mueller@tmit.eu> 14 * 15 * Mail 16 * 17 * This code is free software: you can redistribute it and/or modify 18 * it under the terms of the GNU Affero General Public License, version 3, 19 * as published by the Free Software Foundation. 20 * 21 * This program is distributed in the hope that it will be useful, 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 * GNU Affero General Public License for more details. 25 * 26 * You should have received a copy of the GNU Affero General Public License, version 3, 27 * along with this program. If not, see <http://www.gnu.org/licenses/> 28 * 29 */ 30 31namespace OCA\Mail\Controller; 32 33use Exception; 34use OC\Security\CSP\ContentSecurityPolicyNonceManager; 35use OCA\Mail\Contracts\IMailManager; 36use OCA\Mail\Contracts\IMailSearch; 37use OCA\Mail\Contracts\IMailTransmission; 38use OCA\Mail\Contracts\ITrustedSenderService; 39use OCA\Mail\Db\Message; 40use OCA\Mail\Exception\ClientException; 41use OCA\Mail\Exception\ServiceException; 42use OCA\Mail\Http\AttachmentDownloadResponse; 43use OCA\Mail\Http\HtmlResponse; 44use OCA\Mail\Service\AccountService; 45use OCA\Mail\Service\ItineraryService; 46use OCP\AppFramework\Controller; 47use OCP\AppFramework\Db\DoesNotExistException; 48use OCP\AppFramework\Http; 49use OCP\AppFramework\Http\ContentSecurityPolicy; 50use OCP\AppFramework\Http\JSONResponse; 51use OCP\AppFramework\Http\Response; 52use OCP\AppFramework\Http\TemplateResponse; 53use OCP\AppFramework\Http\ZipResponse; 54use OCP\Files\Folder; 55use OCP\Files\IMimeTypeDetector; 56use OCP\IL10N; 57use OCP\IRequest; 58use OCP\IURLGenerator; 59use Psr\Log\LoggerInterface; 60use function array_map; 61 62class MessagesController extends Controller { 63 64 /** @var AccountService */ 65 private $accountService; 66 67 /** @var IMailManager */ 68 private $mailManager; 69 70 /** @var IMailSearch */ 71 private $mailSearch; 72 73 /** @var ItineraryService */ 74 private $itineraryService; 75 76 /** @var string */ 77 private $currentUserId; 78 79 /** @var LoggerInterface */ 80 private $logger; 81 82 /** @var Folder */ 83 private $userFolder; 84 85 /** @var IMimeTypeDetector */ 86 private $mimeTypeDetector; 87 88 /** @var IL10N */ 89 private $l10n; 90 91 /** @var IURLGenerator */ 92 private $urlGenerator; 93 94 /** @var ContentSecurityPolicyNonceManager */ 95 private $nonceManager; 96 97 /** @var ITrustedSenderService */ 98 private $trustedSenderService; 99 100 /** @var IMailTransmission */ 101 private $mailTransmission; 102 103 /** 104 * @param string $appName 105 * @param IRequest $request 106 * @param AccountService $accountService 107 * @param IMailManager $mailManager 108 * @param IMailSearch $mailSearch 109 * @param ItineraryService $itineraryService 110 * @param string $UserId 111 * @param $userFolder 112 * @param LoggerInterface $logger 113 * @param IL10N $l10n 114 * @param IMimeTypeDetector $mimeTypeDetector 115 * @param IURLGenerator $urlGenerator 116 * @param ContentSecurityPolicyNonceManager $nonceManager 117 * @param ITrustedSenderService $trustedSenderService 118 * @param IMailTransmission $mailTransmission 119 */ 120 public function __construct(string $appName, 121 IRequest $request, 122 AccountService $accountService, 123 IMailManager $mailManager, 124 IMailSearch $mailSearch, 125 ItineraryService $itineraryService, 126 string $UserId, 127 $userFolder, 128 LoggerInterface $logger, 129 IL10N $l10n, 130 IMimeTypeDetector $mimeTypeDetector, 131 IURLGenerator $urlGenerator, 132 ContentSecurityPolicyNonceManager $nonceManager, 133 ITrustedSenderService $trustedSenderService, 134 IMailTransmission $mailTransmission) { 135 parent::__construct($appName, $request); 136 137 $this->accountService = $accountService; 138 $this->mailManager = $mailManager; 139 $this->mailSearch = $mailSearch; 140 $this->itineraryService = $itineraryService; 141 $this->currentUserId = $UserId; 142 $this->userFolder = $userFolder; 143 $this->logger = $logger; 144 $this->l10n = $l10n; 145 $this->mimeTypeDetector = $mimeTypeDetector; 146 $this->urlGenerator = $urlGenerator; 147 $this->mailManager = $mailManager; 148 $this->nonceManager = $nonceManager; 149 $this->trustedSenderService = $trustedSenderService; 150 $this->mailTransmission = $mailTransmission; 151 } 152 153 /** 154 * @NoAdminRequired 155 * @TrapError 156 * 157 * @param int $mailboxId 158 * @param int $cursor 159 * @param string $filter 160 * @param int|null $limit 161 * 162 * @return JSONResponse 163 * 164 * @throws ClientException 165 * @throws ServiceException 166 */ 167 168 public function index(int $mailboxId, 169 int $cursor = null, 170 string $filter = null, 171 int $limit = null): JSONResponse { 172 try { 173 $mailbox = $this->mailManager->getMailbox($this->currentUserId, $mailboxId); 174 $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId()); 175 } catch (DoesNotExistException $e) { 176 return new JSONResponse([], Http::STATUS_FORBIDDEN); 177 } 178 179 $this->logger->debug("loading messages of folder <$mailboxId>"); 180 181 return new JSONResponse( 182 $this->mailSearch->findMessages( 183 $account, 184 $mailbox, 185 $filter === '' ? null : $filter, 186 $cursor, 187 $limit 188 ) 189 ); 190 } 191 192 /** 193 * @NoAdminRequired 194 * @TrapError 195 * 196 * @param int $accountId 197 * @param string $folderId 198 * @param int $id 199 * 200 * @return JSONResponse 201 * 202 * @throws ClientException 203 * @throws ServiceException 204 */ 205 public function show(int $id): JSONResponse { 206 try { 207 $message = $this->mailManager->getMessage($this->currentUserId, $id); 208 $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId()); 209 $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId()); 210 } catch (DoesNotExistException $e) { 211 return new JSONResponse([], Http::STATUS_FORBIDDEN); 212 } 213 214 $this->logger->debug("loading message <$id>"); 215 216 return new JSONResponse( 217 $this->mailSearch->findMessage( 218 $account, 219 $mailbox, 220 $message 221 ) 222 ); 223 } 224 225 /** 226 * @NoAdminRequired 227 * @TrapError 228 * 229 * @param int $id 230 * 231 * @return JSONResponse 232 * 233 * @throws ClientException 234 * @throws ServiceException 235 */ 236 public function getBody(int $id): JSONResponse { 237 try { 238 $message = $this->mailManager->getMessage($this->currentUserId, $id); 239 $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId()); 240 $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId()); 241 } catch (DoesNotExistException $e) { 242 return new JSONResponse([], Http::STATUS_FORBIDDEN); 243 } 244 245 $json = $this->mailManager->getImapMessage( 246 $account, 247 $mailbox, 248 $message->getUid(), 249 true 250 )->getFullMessage($id); 251 $json['itineraries'] = $this->itineraryService->extract( 252 $account, 253 $mailbox->getName(), 254 $message->getUid() 255 ); 256 $json['attachments'] = array_map(function ($a) use ($id) { 257 return $this->enrichDownloadUrl( 258 $id, 259 $a 260 ); 261 }, $json['attachments']); 262 $json['accountId'] = $account->getId(); 263 $json['mailboxId'] = $mailbox->getId(); 264 $json['databaseId'] = $message->getId(); 265 $json['isSenderTrusted'] = $this->isSenderTrusted($message); 266 267 $response = new JSONResponse($json); 268 269 // Enable caching 270 $response->cacheFor(60 * 60); 271 272 return $response; 273 } 274 275 private function isSenderTrusted(Message $message): bool { 276 $from = $message->getFrom(); 277 $first = $from->first(); 278 if ($first === null) { 279 return false; 280 } 281 $email = $first->getEmail(); 282 if ($email === null) { 283 return false; 284 } 285 return $this->trustedSenderService->isTrusted( 286 $this->currentUserId, 287 $email 288 ); 289 } 290 291 /** 292 * @NoAdminRequired 293 * @NoCSRFRequired 294 * @TrapError 295 * 296 * @param int $id 297 * 298 * @return JSONResponse 299 * @throws ClientException 300 */ 301 public function getThread(int $id): JSONResponse { 302 try { 303 $message = $this->mailManager->getMessage($this->currentUserId, $id); 304 $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId()); 305 $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId()); 306 } catch (DoesNotExistException $e) { 307 return new JSONResponse([], Http::STATUS_FORBIDDEN); 308 } 309 310 return new JSONResponse($this->mailManager->getThread($account, $message->getThreadRootId())); 311 } 312 313 /** 314 * @NoAdminRequired 315 * @TrapError 316 * 317 * @param int $id 318 * @param int $destFolderId 319 * 320 * @return JSONResponse 321 * 322 * @throws ClientException 323 * @throws ServiceException 324 */ 325 public function move(int $id, int $destFolderId): JSONResponse { 326 try { 327 $message = $this->mailManager->getMessage($this->currentUserId, $id); 328 $srcMailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId()); 329 $dstMailbox = $this->mailManager->getMailbox($this->currentUserId, $destFolderId); 330 $srcAccount = $this->accountService->find($this->currentUserId, $srcMailbox->getAccountId()); 331 $dstAccount = $this->accountService->find($this->currentUserId, $dstMailbox->getAccountId()); 332 } catch (DoesNotExistException $e) { 333 return new JSONResponse([], Http::STATUS_FORBIDDEN); 334 } 335 336 $this->mailManager->moveMessage( 337 $srcAccount, 338 $srcMailbox->getName(), 339 $message->getUid(), 340 $dstAccount, 341 $dstMailbox->getName() 342 ); 343 return new JSONResponse(); 344 } 345 346 /** 347 * @NoAdminRequired 348 * @TrapError 349 * 350 * @param int $id 351 * 352 * @return JSONResponse 353 * 354 * @throws ClientException 355 * @throws ServiceException 356 */ 357 public function mdn(int $id): JSONResponse { 358 try { 359 $message = $this->mailManager->getMessage($this->currentUserId, $id); 360 $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId()); 361 $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId()); 362 } catch (DoesNotExistException $e) { 363 return new JSONResponse([], Http::STATUS_FORBIDDEN); 364 } 365 366 if ($message->getFlagMdnsent()) { 367 return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED); 368 } 369 370 try { 371 $this->mailTransmission->sendMdn($account, $mailbox, $message); 372 $this->mailManager->flagMessage($account, $mailbox->getName(), $message->getUid(), 'mdnsent', true); 373 } catch (ServiceException $ex) { 374 $this->logger->error('Sending mdn failed: ' . $ex->getMessage()); 375 throw $ex; 376 } 377 378 return new JSONResponse(); 379 } 380 381 /** 382 * @NoAdminRequired 383 * @NoCSRFRequired 384 * @TrapError 385 * 386 * @param int $accountId 387 * @param string $folderId 388 * @param int $messageId 389 * 390 * @return JSONResponse 391 * @throws ServiceException 392 */ 393 public function getSource(int $id): JSONResponse { 394 try { 395 $message = $this->mailManager->getMessage($this->currentUserId, $id); 396 $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId()); 397 $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId()); 398 } catch (DoesNotExistException $e) { 399 return new JSONResponse([], Http::STATUS_FORBIDDEN); 400 } 401 402 $response = new JSONResponse([ 403 'source' => $this->mailManager->getSource( 404 $account, 405 $mailbox->getName(), 406 $message->getUid() 407 ) 408 ]); 409 410 // Enable caching 411 $response->cacheFor(60 * 60); 412 413 return $response; 414 } 415 416 /** 417 * @NoAdminRequired 418 * @NoCSRFRequired 419 * @TrapError 420 * 421 * @param int $id 422 * @param bool $plain do not inject scripts if true (default=false) 423 * 424 * @return HtmlResponse|TemplateResponse 425 * 426 * @throws ClientException 427 */ 428 public function getHtmlBody(int $id, bool $plain = false): Response { 429 try { 430 try { 431 $message = $this->mailManager->getMessage($this->currentUserId, $id); 432 $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId()); 433 $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId()); 434 } catch (DoesNotExistException $e) { 435 return new TemplateResponse( 436 $this->appName, 437 'error', 438 ['message' => 'Not allowed'], 439 'none' 440 ); 441 } 442 443 $html = $this->mailManager->getImapMessage( 444 $account, 445 $mailbox, 446 $message->getUid(), 447 true 448 )->getHtmlBody( 449 $id 450 ); 451 $htmlResponse = $plain ? 452 HtmlResponse::plain($html) : 453 HtmlResponse::withResizer( 454 $html, 455 $this->nonceManager->getNonce(), 456 $this->urlGenerator->getAbsoluteURL( 457 $this->urlGenerator->linkTo('mail', 'js/htmlresponse.js') 458 ) 459 ); 460 461 // Harden the default security policy 462 $policy = new ContentSecurityPolicy(); 463 $policy->allowEvalScript(false); 464 $policy->disallowScriptDomain('\'self\''); 465 $policy->disallowConnectDomain('\'self\''); 466 $policy->disallowFontDomain('\'self\''); 467 $policy->disallowMediaDomain('\'self\''); 468 $htmlResponse->setContentSecurityPolicy($policy); 469 470 // Enable caching 471 $htmlResponse->cacheFor(60 * 60); 472 473 return $htmlResponse; 474 } catch (Exception $ex) { 475 return new TemplateResponse( 476 $this->appName, 477 'error', 478 ['message' => $ex->getMessage()], 479 'none' 480 ); 481 } 482 } 483 484 /** 485 * @NoAdminRequired 486 * @NoCSRFRequired 487 * @TrapError 488 * 489 * @param int $accountId 490 * @param string $folderId 491 * @param int $id 492 * @param string $attachmentId 493 * 494 * @return Response 495 * 496 * @throws ClientException 497 * @throws ServiceException 498 */ 499 public function downloadAttachment(int $id, 500 string $attachmentId): Response { 501 try { 502 $message = $this->mailManager->getMessage($this->currentUserId, $id); 503 $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId()); 504 $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId()); 505 } catch (DoesNotExistException $e) { 506 return new JSONResponse([], Http::STATUS_FORBIDDEN); 507 } 508 $folder = $account->getMailbox($mailbox->getName()); 509 $attachment = $folder->getAttachment($message->getUid(), $attachmentId); 510 511 // Body party and embedded messages do not have a name 512 if ($attachment->getName() === null) { 513 return new AttachmentDownloadResponse( 514 $attachment->getContents(), 515 $this->l10n->t('Embedded message %s', [ 516 $attachmentId, 517 ]) . '.eml', 518 $attachment->getType() 519 ); 520 } 521 return new AttachmentDownloadResponse( 522 $attachment->getContents(), 523 $attachment->getName(), 524 $attachment->getType() 525 ); 526 } 527 528 /** 529 * @NoAdminRequired 530 * @NoCSRFRequired 531 * @TrapError 532 * 533 * @param int $id the message id 534 * @param string $attachmentId 535 * 536 * @return ZipResponse|JSONResponse 537 * 538 * @throws ClientException 539 * @throws ServiceException 540 * @throws DoesNotExistException 541 */ 542 public function downloadAttachments(int $id): Response { 543 try { 544 $message = $this->mailManager->getMessage($this->currentUserId, $id); 545 $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId()); 546 $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId()); 547 } catch (DoesNotExistException $e) { 548 return new JSONResponse([], Http::STATUS_FORBIDDEN); 549 } 550 551 $attachments = $this->mailManager->getMailAttachments($account, $mailbox, $message); 552 $zip = new ZipResponse($this->request, 'attachments'); 553 554 foreach ($attachments as $attachment) { 555 $fileName = $attachment['name']; 556 $fh = fopen("php://temp", 'r+'); 557 fputs($fh, $attachment['content']); 558 $size = (int)$attachment['size']; 559 rewind($fh); 560 $zip->addResource($fh, $fileName, $size); 561 } 562 return $zip; 563 } 564 565 /** 566 * @NoAdminRequired 567 * @TrapError 568 * 569 * @param int $id 570 * @param string $attachmentId 571 * @param string $targetPath 572 * 573 * @return JSONResponse 574 * 575 * @throws ClientException 576 * @throws ServiceException 577 */ 578 public function saveAttachment(int $id, 579 string $attachmentId, 580 string $targetPath) { 581 try { 582 $message = $this->mailManager->getMessage($this->currentUserId, $id); 583 $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId()); 584 $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId()); 585 } catch (DoesNotExistException $e) { 586 return new JSONResponse([], Http::STATUS_FORBIDDEN); 587 } 588 $folder = $account->getMailbox($mailbox->getName()); 589 590 if ($attachmentId === '0') { 591 // Save all attachments 592 /* @var $m IMAPMessage */ 593 $m = $folder->getMessage($message->getUid()); 594 $attachmentIds = array_map(function ($a) { 595 return $a['id']; 596 }, $m->attachments); 597 } else { 598 $attachmentIds = [$attachmentId]; 599 } 600 601 foreach ($attachmentIds as $aid) { 602 $attachment = $folder->getAttachment($message->getUid(), $aid); 603 604 $fileName = $attachment->getName() ?? $this->l10n->t('Embedded message %s', [ 605 $aid, 606 ]) . '.eml'; 607 $fileParts = pathinfo($fileName); 608 $fileName = $fileParts['filename']; 609 $fileExtension = $fileParts['extension']; 610 $fullPath = "$targetPath/$fileName.$fileExtension"; 611 $counter = 2; 612 while ($this->userFolder->nodeExists($fullPath)) { 613 $fullPath = "$targetPath/$fileName ($counter).$fileExtension"; 614 $counter++; 615 } 616 617 $newFile = $this->userFolder->newFile($fullPath); 618 $newFile->putContent($attachment->getContents()); 619 } 620 return new JSONResponse(); 621 } 622 623 /** 624 * @NoAdminRequired 625 * @TrapError 626 * 627 * @param int $id 628 * @param array $flags 629 * 630 * @return JSONResponse 631 * 632 * @throws ClientException 633 * @throws ServiceException 634 */ 635 public function setFlags(int $id, array $flags): JSONResponse { 636 try { 637 $message = $this->mailManager->getMessage($this->currentUserId, $id); 638 $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId()); 639 $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId()); 640 } catch (DoesNotExistException $e) { 641 return new JSONResponse([], Http::STATUS_FORBIDDEN); 642 } 643 644 foreach ($flags as $flag => $value) { 645 $value = filter_var($value, FILTER_VALIDATE_BOOLEAN); 646 $this->mailManager->flagMessage($account, $mailbox->getName(), $message->getUid(), $flag, $value); 647 } 648 return new JSONResponse(); 649 } 650 651 /** 652 * @NoAdminRequired 653 * @TrapError 654 * 655 * @param int $id 656 * @param string $imapLabel 657 * 658 * @return JSONResponse 659 * 660 * @throws ClientException 661 * @throws ServiceException 662 */ 663 public function setTag(int $id, string $imapLabel): JSONResponse { 664 try { 665 $message = $this->mailManager->getMessage($this->currentUserId, $id); 666 $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId()); 667 $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId()); 668 } catch (DoesNotExistException $e) { 669 return new JSONResponse([], Http::STATUS_FORBIDDEN); 670 } 671 672 try { 673 $tag = $this->mailManager->getTagByImapLabel($imapLabel, $this->currentUserId); 674 } catch (ClientException $e) { 675 return new JSONResponse([], Http::STATUS_FORBIDDEN); 676 } 677 678 $this->mailManager->tagMessage($account, $mailbox->getName(), $message, $tag, true); 679 return new JSONResponse($tag); 680 } 681 682 /** 683 * @NoAdminRequired 684 * @TrapError 685 * 686 * @param int $id 687 * @param string $imapLabel 688 * 689 * @return JSONResponse 690 * 691 * @throws ClientException 692 * @throws ServiceException 693 */ 694 public function removeTag(int $id, string $imapLabel): JSONResponse { 695 try { 696 $message = $this->mailManager->getMessage($this->currentUserId, $id); 697 $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId()); 698 $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId()); 699 } catch (DoesNotExistException $e) { 700 return new JSONResponse([], Http::STATUS_FORBIDDEN); 701 } 702 703 try { 704 $tag = $this->mailManager->getTagByImapLabel($imapLabel, $this->currentUserId); 705 } catch (ClientException $e) { 706 return new JSONResponse([], Http::STATUS_FORBIDDEN); 707 } 708 709 $this->mailManager->tagMessage($account, $mailbox->getName(), $message, $tag, false); 710 return new JSONResponse($tag); 711 } 712 713 /** 714 * @NoAdminRequired 715 * @TrapError 716 * 717 * @param int $accountId 718 * @param string $folderId 719 * @param int $id 720 * 721 * @return JSONResponse 722 * 723 * @throws ClientException 724 * @throws ServiceException 725 */ 726 public function destroy(int $id): JSONResponse { 727 try { 728 $message = $this->mailManager->getMessage($this->currentUserId, $id); 729 $mailbox = $this->mailManager->getMailbox($this->currentUserId, $message->getMailboxId()); 730 $account = $this->accountService->find($this->currentUserId, $mailbox->getAccountId()); 731 } catch (DoesNotExistException $e) { 732 return new JSONResponse([], Http::STATUS_FORBIDDEN); 733 } 734 735 $this->logger->debug("deleting message <$id>"); 736 737 $this->mailManager->deleteMessage( 738 $account, 739 $mailbox->getName(), 740 $message->getUid() 741 ); 742 return new JSONResponse(); 743 } 744 745 /** 746 * @param int $id 747 * @param array $attachment 748 * 749 * @return array 750 */ 751 private function enrichDownloadUrl(int $id, 752 array $attachment) { 753 $downloadUrl = $this->urlGenerator->linkToRoute('mail.messages.downloadAttachment', 754 [ 755 'id' => $id, 756 'attachmentId' => $attachment['id'], 757 ]); 758 $downloadUrl = $this->urlGenerator->getAbsoluteURL($downloadUrl); 759 $attachment['downloadUrl'] = $downloadUrl; 760 $attachment['mimeUrl'] = $this->mimeTypeDetector->mimeTypeIcon($attachment['mime']); 761 762 $attachment['isImage'] = $this->attachmentIsImage($attachment); 763 $attachment['isCalendarEvent'] = $this->attachmentIsCalendarEvent($attachment); 764 765 return $attachment; 766 } 767 768 /** 769 * Determines if the content of this attachment is an image 770 * 771 * @param array $attachment 772 * 773 * @return boolean 774 */ 775 private function attachmentIsImage(array $attachment): bool { 776 return in_array( 777 $attachment['mime'], [ 778 'image/jpeg', 779 'image/png', 780 'image/gif' 781 ]); 782 } 783 784 /** 785 * @param array $attachment 786 * 787 * @return boolean 788 */ 789 private function attachmentIsCalendarEvent(array $attachment): bool { 790 return in_array($attachment['mime'], ['text/calendar', 'application/ics'], true); 791 } 792} 793