1<?php 2/* Copyright (c) 1998-2012 ILIAS open source, Extended GPL, see docs/LICENSE */ 3 4use ILIAS\BackgroundTasks\Implementation\Bucket\BasicBucket; 5 6/** 7 * @author Stefan Meyer <meyer@leifos.com> 8 * @author Michael Jansen <mjansen@databay.de> 9 */ 10class ilMail 11{ 12 const ILIAS_HOST = 'ilias'; 13 14 /** @var ilLanguage */ 15 protected $lng; 16 17 /** @var ilDBInterface */ 18 protected $db; 19 20 /** @var ilFileDataMail */ 21 protected $mfile; 22 23 /** @var ilMailOptions */ 24 protected $mail_options; 25 26 /** @var ilMailbox */ 27 protected $mailbox; 28 29 /** @var int */ 30 public $user_id; 31 32 /** @var string */ 33 protected $table_mail; 34 35 /** @var string */ 36 protected $table_mail_saved; 37 38 /** @var array */ 39 protected $mail_data = array(); 40 41 /** @var int */ 42 protected $mail_obj_ref_id; 43 44 /** @var bool */ 45 protected $save_in_sentbox; 46 47 /** @var bool */ 48 protected $appendInstallationSignature = false; 49 50 /** @var ilAppEventHandler */ 51 private $eventHandler; 52 53 /** @var ilMailAddressTypeFactory */ 54 private $mailAddressTypeFactory; 55 56 /** @var ilMailRfc822AddressParserFactory */ 57 private $mailAddressParserFactory; 58 59 /** @var mixed|null */ 60 protected $contextId = null; 61 62 /** @var array */ 63 protected $contextParameters = []; 64 65 /** @var ilLogger */ 66 protected $logger; 67 68 /** @var ilMailOptions[] */ 69 protected $mailOptionsByUsrIdMap = []; 70 71 /** @var ilObjUser[] */ 72 protected $userInstancesByIdMap = []; 73 74 /** @var callable|null */ 75 protected $usrIdByLoginCallable = null; 76 77 /** @var int */ 78 protected $maxRecipientCharacterLength = 998; 79 80 /** @var ilMailMimeSenderFactory */ 81 protected $senderFactory; 82 83 /** 84 * @param integer $a_user_id 85 * @param ilMailAddressTypeFactory|null $mailAddressTypeFactory 86 * @param ilMailRfc822AddressParserFactory|null $mailAddressParserFactory 87 * @param ilAppEventHandler|null $eventHandler 88 * @param ilLogger|null $logger 89 * @param ilDBInterface|null $db 90 * @param ilLanguage|null $lng 91 * @param ilFileDataMail|null $mailFileData 92 * @param ilMailOptions|null $mailOptions 93 * @param ilMailbox|null $mailBox 94 * @param ilMailMimeSenderFactory|null $senderFactory 95 * @param callable|null $usrIdByLoginCallable 96 * @param int|null $mailAdminNodeRefId 97 */ 98 public function __construct( 99 $a_user_id, 100 ilMailAddressTypeFactory $mailAddressTypeFactory = null, 101 ilMailRfc822AddressParserFactory $mailAddressParserFactory = null, 102 ilAppEventHandler $eventHandler = null, 103 ilLogger $logger = null, 104 ilDBInterface $db = null, 105 ilLanguage $lng = null, 106 ilFileDataMail $mailFileData = null, 107 ilMailOptions $mailOptions = null, 108 ilMailbox $mailBox = null, 109 ilMailMimeSenderFactory $senderFactory = null, 110 callable $usrIdByLoginCallable = null, 111 int $mailAdminNodeRefId = null 112 ) { 113 global $DIC; 114 115 if ($logger === null) { 116 $logger = ilLoggerFactory::getLogger('mail'); 117 } 118 if ($mailAddressTypeFactory === null) { 119 $mailAddressTypeFactory = new ilMailAddressTypeFactory(null, $logger); 120 } 121 if ($mailAddressParserFactory === null) { 122 $mailAddressParserFactory = new ilMailRfc822AddressParserFactory(); 123 } 124 if ($eventHandler === null) { 125 $eventHandler = $DIC->event(); 126 } 127 if ($db === null) { 128 $db = $DIC->database(); 129 } 130 if ($lng === null) { 131 $lng = $DIC->language(); 132 } 133 if ($mailFileData === null) { 134 $mailFileData = new ilFileDataMail($a_user_id); 135 } 136 if ($mailOptions === null) { 137 $mailOptions = new ilMailOptions($a_user_id); 138 } 139 if ($mailBox === null) { 140 $mailBox = new ilMailbox($a_user_id); 141 } 142 if ($senderFactory === null) { 143 $senderFactory = $GLOBALS["DIC"]["mail.mime.sender.factory"]; 144 } 145 if ($usrIdByLoginCallable === null) { 146 $usrIdByLoginCallable = function (string $login) { 147 return ilObjUser::_lookupId($login); 148 }; 149 } 150 151 $this->user_id = (int) $a_user_id; 152 $this->mailAddressParserFactory = $mailAddressParserFactory; 153 $this->mailAddressTypeFactory = $mailAddressTypeFactory; 154 $this->eventHandler = $eventHandler; 155 $this->logger = $logger; 156 $this->db = $db; 157 $this->lng = $lng; 158 $this->mfile = $mailFileData; 159 $this->mail_options = $mailOptions; 160 $this->mailbox = $mailBox; 161 $this->senderFactory = $senderFactory; 162 $this->usrIdByLoginCallable = $usrIdByLoginCallable; 163 164 $this->mail_obj_ref_id = $mailAdminNodeRefId; 165 if (null === $this->mail_obj_ref_id) { 166 $this->readMailObjectReferenceId(); 167 } 168 169 $this->lng->loadLanguageModule('mail'); 170 $this->table_mail = 'mail'; 171 $this->table_mail_saved = 'mail_saved'; 172 $this->setSaveInSentbox(false); 173 } 174 175 /** 176 * @param string $contextId 177 * @return ilMail 178 */ 179 public function withContextId(string $contextId) : self 180 { 181 $clone = clone $this; 182 183 $clone->contextId = $contextId; 184 185 return $clone; 186 } 187 188 /** 189 * @param array $parameters 190 * @return ilMail 191 */ 192 public function withContextParameters(array $parameters) : self 193 { 194 $clone = clone $this; 195 196 $clone->contextParameters = $parameters; 197 198 return $clone; 199 } 200 201 /** 202 * @return bool 203 */ 204 protected function isSystemMail() : bool 205 { 206 return $this->user_id == ANONYMOUS_USER_ID; 207 } 208 209 /** 210 * @param string $newRecipient 211 * @param string $existingRecipients 212 * @return bool 213 */ 214 public function existsRecipient(string $newRecipient, string $existingRecipients) : bool 215 { 216 $newAddresses = new ilMailAddressListImpl($this->parseAddresses($newRecipient)); 217 $addresses = new ilMailAddressListImpl($this->parseAddresses($existingRecipients)); 218 219 $list = new ilMailDiffAddressList($newAddresses, $addresses); 220 221 $diffedAddresses = $list->value(); 222 223 return count($diffedAddresses) === 0; 224 } 225 226 /** 227 * @param bool $saveInSentbox 228 */ 229 public function setSaveInSentbox(bool $saveInSentbox) : void 230 { 231 $this->save_in_sentbox = (bool) $saveInSentbox; 232 } 233 234 /** 235 * @return bool 236 */ 237 public function getSaveInSentbox() : bool 238 { 239 return (bool) $this->save_in_sentbox; 240 } 241 242 /** 243 * Read and set the mail object ref id (administration node) 244 */ 245 protected function readMailObjectReferenceId() : void 246 { 247 $this->mail_obj_ref_id = (int) ilMailGlobalServices::getMailObjectRefId(); 248 } 249 250 /** 251 * @return int 252 */ 253 public function getMailObjectReferenceId() : int 254 { 255 return $this->mail_obj_ref_id; 256 } 257 258 /** 259 * Prepends the full name of each ILIAS login name (if user has a public profile) found 260 * in the passed string and brackets the ILIAS login name afterwards. 261 * @param string $recipients A string containing to, cc or bcc recipients 262 * @return string 263 */ 264 public function formatNamesForOutput(string $recipients) : string 265 { 266 global $DIC; 267 268 $recipients = trim($recipients); 269 if (0 === strlen($recipients)) { 270 return $this->lng->txt('not_available'); 271 } 272 273 $names = []; 274 275 $recipients = array_filter(array_map('trim', explode(',', $recipients))); 276 foreach ($recipients as $recipient) { 277 $usrId = ilObjUser::_lookupId($recipient); 278 if ($usrId > 0) { 279 $pp = ilObjUser::_lookupPref($usrId, 'public_profile'); 280 if ($pp === 'g' || ($pp === 'y' && !$DIC->user()->isAnonymous())) { 281 $user = $this->getUserInstanceById($usrId); 282 $names[] = $user->getFullname() . ' [' . $recipient . ']'; 283 continue; 284 } 285 } 286 287 $names[] = $recipient; 288 } 289 290 return implode(', ', $names); 291 } 292 293 /** 294 * @param int $mailId 295 * @return array|null 296 */ 297 public function getPreviousMail(int $mailId) : ?array 298 { 299 $this->db->setLimit(1, 0); 300 301 $query = implode(' ', [ 302 "SELECT b.* FROM {$this->table_mail} a", 303 "INNER JOIN {$this->table_mail} b ON b.folder_id = a.folder_id", 304 'AND b.user_id = a.user_id AND b.send_time > a.send_time', 305 'WHERE a.user_id = %s AND a.mail_id = %s ORDER BY b.send_time ASC', 306 ]); 307 $res = $this->db->queryF( 308 $query, 309 ['integer', 'integer'], 310 [$this->user_id, $mailId] 311 ); 312 313 $this->mail_data = $this->fetchMailData($this->db->fetchAssoc($res)); 314 315 return $this->mail_data; 316 } 317 318 /** 319 * @param int $mailId 320 * @return array|null 321 */ 322 public function getNextMail(int $mailId) : ?array 323 { 324 $this->db->setLimit(1, 0); 325 326 $query = implode(' ', [ 327 "SELECT b.* FROM {$this->table_mail} a", 328 "INNER JOIN {$this->table_mail} b ON b.folder_id = a.folder_id", 329 'AND b.user_id = a.user_id AND b.send_time < a.send_time', 330 'WHERE a.user_id = %s AND a.mail_id = %s ORDER BY b.send_time DESC', 331 ]); 332 $res = $this->db->queryF( 333 $query, 334 ['integer', 'integer'], 335 [$this->user_id, $mailId] 336 ); 337 338 $this->mail_data = $this->fetchMailData($this->db->fetchAssoc($res)); 339 340 return $this->mail_data; 341 } 342 343 /** 344 * @param int $a_folder_id The id of the folder 345 * @param array $filter An optional filter array 346 * @return array 347 */ 348 public function getMailsOfFolder($a_folder_id, $filter = []) : array 349 { 350 $mails = []; 351 352 $query = 353 "SELECT sender_id, m_subject, mail_id, m_status, send_time " . 354 "FROM {$this->table_mail} " . 355 "LEFT JOIN object_data ON obj_id = sender_id " . 356 "WHERE user_id = %s AND folder_id = %s " . 357 "AND ((sender_id > 0 AND sender_id IS NOT NULL AND obj_id IS NOT NULL) OR (sender_id = 0 OR sender_id IS NULL))"; 358 359 if (isset($filter['status']) && strlen($filter['status']) > 0) { 360 $query .= ' AND m_status = ' . $this->db->quote($filter['status'], 'text'); 361 } 362 363 $query .= " ORDER BY send_time DESC"; 364 365 $res = $this->db->queryF( 366 $query, 367 ['integer', 'integer'], 368 [$this->user_id, $a_folder_id] 369 ); 370 371 while ($row = $this->db->fetchAssoc($res)) { 372 $mails[] = $this->fetchMailData($row); 373 } 374 375 return array_filter($mails); 376 } 377 378 /** 379 * @param int $folderId 380 * @return int 381 */ 382 public function countMailsOfFolder(int $folderId) : int 383 { 384 $res = $this->db->queryF( 385 "SELECT COUNT(*) FROM {$this->table_mail} WHERE user_id = %s AND folder_id = %s", 386 ['integer', 'integer'], 387 [$this->user_id, $folderId] 388 ); 389 390 return $this->db->numRows($res); 391 } 392 393 /** 394 * @param int $folderId 395 */ 396 public function deleteMailsOfFolder(int $folderId) : void 397 { 398 $mails = $this->getMailsOfFolder($folderId); 399 foreach ($mails as $mail_data) { 400 $this->deleteMails([$mail_data['mail_id']]); 401 } 402 } 403 404 /** 405 * @param int $mailId 406 * @return array|null 407 */ 408 public function getMail(int $mailId) : ?array 409 { 410 $res = $this->db->queryF( 411 "SELECT * FROM {$this->table_mail} WHERE user_id = %s AND mail_id = %s", 412 ['integer', 'integer'], 413 [$this->user_id, $mailId] 414 ); 415 416 $this->mail_data = $this->fetchMailData($this->db->fetchAssoc($res)); 417 418 return $this->mail_data; 419 } 420 421 /** 422 * @param int[] $mailIds 423 */ 424 public function markRead(array $mailIds) : void 425 { 426 $values = []; 427 $types = []; 428 429 $query = "UPDATE {$this->table_mail} SET m_status = %s WHERE user_id = %s "; 430 array_push($types, 'text', 'integer'); 431 array_push($values, 'read', $this->user_id); 432 433 if (count($mailIds) > 0) { 434 $query .= ' AND ' . $this->db->in('mail_id', $mailIds, false, 'integer'); 435 } 436 437 $this->db->manipulateF($query, $types, $values); 438 } 439 440 /** 441 * @param int[] $mailIds 442 */ 443 public function markUnread(array $mailIds) : void 444 { 445 $values = array(); 446 $types = array(); 447 448 $query = "UPDATE {$this->table_mail} SET m_status = %s WHERE user_id = %s "; 449 array_push($types, 'text', 'integer'); 450 array_push($values, 'unread', $this->user_id); 451 452 if (count($mailIds) > 0) { 453 $query .= ' AND ' . $this->db->in('mail_id', $mailIds, false, 'integer'); 454 } 455 456 $this->db->manipulateF($query, $types, $values); 457 } 458 459 /** 460 * @param int[] $mailIds 461 * @param int $folderId 462 * @return bool 463 */ 464 public function moveMailsToFolder(array $mailIds, int $folderId) : bool 465 { 466 $values = []; 467 $types = []; 468 469 $mailIds = array_filter(array_map('intval', $mailIds)); 470 471 if (0 === count($mailIds)) { 472 return false; 473 } 474 475 $query = 476 "UPDATE {$this->table_mail} " . 477 "INNER JOIN mail_obj_data " . 478 "ON mail_obj_data.obj_id = %s AND mail_obj_data.user_id = %s " . 479 "SET {$this->table_mail}.folder_id = mail_obj_data.obj_id " . 480 "WHERE {$this->table_mail}.user_id = %s"; 481 array_push($types, 'integer', 'integer', 'integer'); 482 array_push($values, $folderId, $this->user_id, $this->user_id); 483 484 $query .= ' AND ' . $this->db->in('mail_id', $mailIds, false, 'integer'); 485 486 $affectedRows = $this->db->manipulateF($query, $types, $values); 487 488 return $affectedRows > 0; 489 } 490 491 /** 492 * @param int[] $mailIds 493 */ 494 public function deleteMails(array $mailIds) : void 495 { 496 $mailIds = array_filter(array_map('intval', $mailIds)); 497 foreach ($mailIds as $id) { 498 $this->db->manipulateF( 499 "DELETE FROM {$this->table_mail} WHERE user_id = %s AND mail_id = %s", 500 ['integer', 'integer'], 501 [$this->user_id, $id] 502 ); 503 $this->mfile->deassignAttachmentFromDirectory($id); 504 } 505 } 506 507 /** 508 * @param array|null $row 509 * @return array|null 510 */ 511 protected function fetchMailData(?array $row) : ?array 512 { 513 if (!is_array($row) || empty($row)) { 514 return null; 515 } 516 517 $row['attachments'] = unserialize(stripslashes($row['attachments'])); 518 $row['tpl_ctx_params'] = (array) (@json_decode($row['tpl_ctx_params'], true)); 519 520 return $row; 521 } 522 523 /** 524 * @param int $usrId 525 * @param int $folderId 526 * @return int 527 */ 528 public function getNewDraftId(int $usrId, int $folderId) : int 529 { 530 $nextId = (int) $this->db->nextId($this->table_mail); 531 $this->db->insert($this->table_mail, [ 532 'mail_id' => ['integer', $nextId], 533 'user_id' => ['integer', $usrId], 534 'folder_id' => ['integer', $folderId], 535 'sender_id' => ['integer', $usrId] 536 ]); 537 538 return $nextId; 539 } 540 541 public function updateDraft( 542 $a_folder_id, 543 $a_attachments, 544 $a_rcp_to, 545 $a_rcp_cc, 546 $a_rcp_bcc, 547 $a_m_email, 548 $a_m_subject, 549 $a_m_message, 550 $a_draft_id = 0, 551 $a_use_placeholders = 0, 552 $a_tpl_context_id = null, 553 $a_tpl_context_params = [] 554 ) { 555 $this->db->update( 556 $this->table_mail, 557 [ 558 'folder_id' => ['integer', $a_folder_id], 559 'attachments' => ['clob', serialize($a_attachments)], 560 'send_time' => ['timestamp', date('Y-m-d H:i:s', time())], 561 'rcp_to' => ['clob', $a_rcp_to], 562 'rcp_cc' => ['clob', $a_rcp_cc], 563 'rcp_bcc' => ['clob', $a_rcp_bcc], 564 'm_status' => ['text', 'read'], 565 'm_email' => ['integer', $a_m_email], 566 'm_subject' => ['text', $a_m_subject], 567 'm_message' => ['clob', $a_m_message], 568 'use_placeholders' => ['integer', $a_use_placeholders], 569 'tpl_ctx_id' => ['text', $a_tpl_context_id], 570 'tpl_ctx_params' => ['blob', @json_encode((array) $a_tpl_context_params)] 571 ], 572 [ 573 'mail_id' => ['integer', $a_draft_id] 574 ] 575 ); 576 577 return $a_draft_id; 578 } 579 580 /** 581 * @param integer $folderId 582 * @param integer $senderUsrId 583 * @param array $attachments 584 * @param string $to 585 * @param string $cc 586 * @param string $bcc 587 * @param string $status 588 * @param integer $email 589 * @param string $subject 590 * @param string $message 591 * @param integer $usrId 592 * @param integer $usePlaceholders 593 * @param string|null $templateContextId 594 * @param array|null $templateContextParameters 595 * @return int 596 */ 597 private function sendInternalMail( 598 $folderId, 599 $senderUsrId, 600 $attachments, 601 $to, 602 $cc, 603 $bcc, 604 $status, 605 $email, 606 $subject, 607 $message, 608 $usrId = 0, 609 $usePlaceholders = 0, 610 $templateContextId = null, 611 $templateContextParameters = [] 612 ) : int { 613 $usrId = $usrId ? $usrId : $this->user_id; 614 615 if ($usePlaceholders) { 616 $message = $this->replacePlaceholders($message, $usrId); 617 } 618 $message = $this->formatLinebreakMessage((string) $message); 619 $message = str_ireplace(["<br />", "<br>", "<br/>"], "\n", $message); 620 621 if (!$usrId) { 622 $usrId = '0'; 623 } 624 if (!$folderId) { 625 $folderId = '0'; 626 } 627 if (!$senderUsrId) { 628 $senderUsrId = null; 629 } 630 if (!$attachments) { 631 $attachments = null; 632 } 633 if (!$to) { 634 $to = null; 635 } 636 if (!$cc) { 637 $cc = null; 638 } 639 if (!$bcc) { 640 $bcc = null; 641 } 642 if (!$status) { 643 $status = null; 644 } 645 if (!$email) { 646 $email = null; 647 } 648 if (!$subject) { 649 $subject = null; 650 } 651 if (!$message) { 652 $message = null; 653 } 654 655 $nextId = (int) $this->db->nextId($this->table_mail); 656 $this->db->insert($this->table_mail, array( 657 'mail_id' => array('integer', $nextId), 658 'user_id' => array('integer', $usrId), 659 'folder_id' => array('integer', $folderId), 660 'sender_id' => array('integer', $senderUsrId), 661 'attachments' => array('clob', serialize($attachments)), 662 'send_time' => array('timestamp', date('Y-m-d H:i:s', time())), 663 'rcp_to' => array('clob', $to), 664 'rcp_cc' => array('clob', $cc), 665 'rcp_bcc' => array('clob', $bcc), 666 'm_status' => array('text', $status), 667 'm_email' => array('integer', $email), 668 'm_subject' => array('text', $subject), 669 'm_message' => array('clob', $message), 670 'tpl_ctx_id' => array('text', $templateContextId), 671 'tpl_ctx_params' => array('blob', @json_encode((array) $templateContextParameters)) 672 )); 673 674 $raiseEvent = (int) $usrId !== $this->mailbox->getUsrId(); 675 if (!$raiseEvent) { 676 $raiseEvent = (int) $folderId !== $this->mailbox->getSentFolder(); 677 } 678 679 if ($raiseEvent) { 680 $this->eventHandler->raise('Services/Mail', 'sentInternalMail', [ 681 'id' => $nextId, 682 'subject' => (string) $subject, 683 'body' => (string) $message, 684 'from_usr_id' => (int) $senderUsrId, 685 'to_usr_id' => (int) $usrId, 686 'rcp_to' => (string) $to, 687 'rcp_cc' => (string) $cc, 688 'rcp_bcc' => (string) $bcc, 689 ]); 690 } 691 692 return $nextId; 693 } 694 695 /** 696 * @param string $message 697 * @param int $usrId 698 * @param boolean $replaceEmptyPlaceholders 699 * @return string 700 */ 701 protected function replacePlaceholders( 702 string $message, 703 int $usrId = 0, 704 bool $replaceEmptyPlaceholders = true 705 ) : string { 706 try { 707 if ($this->contextId) { 708 $context = ilMailTemplateContextService::getTemplateContextById($this->contextId); 709 } else { 710 $context = new ilMailTemplateGenericContext(); 711 } 712 713 $user = $usrId > 0 ? $this->getUserInstanceById($usrId) : null; 714 715 $processor = new ilMailTemplatePlaceholderResolver($context, $message); 716 $message = $processor->resolve($user, $this->contextParameters, $replaceEmptyPlaceholders); 717 } catch (Exception $e) { 718 $this->logger->error(__METHOD__ . ' has been called with invalid context.'); 719 } 720 721 return $message; 722 } 723 724 /** 725 * @param string $to 726 * @param string $cc 727 * @param string $bcc 728 * @param string $subject 729 * @param string $message 730 * @param array $attachments 731 * @param int $sentMailId 732 * @param bool $usePlaceholders 733 * @return bool 734 */ 735 protected function distributeMail( 736 string $to, 737 string $cc, 738 string $bcc, 739 string $subject, 740 string $message, 741 array $attachments, 742 int $sentMailId, 743 bool $usePlaceholders = false 744 ) : bool { 745 if ($usePlaceholders) { 746 $toUsrIds = $this->getUserIds([$to]); 747 $this->logger->debug(sprintf( 748 "Parsed TO user ids from given recipients for serial letter notification: %s", 749 implode(', ', $toUsrIds) 750 )); 751 752 $this->sendChanneledMails( 753 $to, 754 $cc, 755 $bcc, 756 $toUsrIds, 757 $subject, 758 $message, 759 $attachments, 760 $sentMailId, 761 true 762 ); 763 764 $otherUsrIds = $this->getUserIds([$cc, $bcc]); 765 $this->logger->debug(sprintf( 766 "Parsed CC/BCC user ids from given recipients for serial letter notification: %s", 767 implode(', ', $otherUsrIds) 768 )); 769 770 $this->sendChanneledMails( 771 $to, 772 $cc, 773 $bcc, 774 $otherUsrIds, 775 $subject, 776 $this->replacePlaceholders($message, 0, false), 777 $attachments, 778 $sentMailId, 779 false 780 ); 781 } else { 782 $usrIds = $this->getUserIds([$to, $cc, $bcc]); 783 $this->logger->debug(sprintf( 784 "Parsed TO/CC/BCC user ids from given recipients: %s", 785 implode(', ', $usrIds) 786 )); 787 788 $this->sendChanneledMails( 789 $to, 790 $cc, 791 $bcc, 792 $usrIds, 793 $subject, 794 $message, 795 $attachments, 796 $sentMailId, 797 false 798 ); 799 } 800 801 return true; 802 } 803 804 /** 805 * @param string $to 806 * @param string $cc 807 * @param string $bcc 808 * @param array $usrIds 809 * @param string $subject 810 * @param string $message 811 * @param array $attachments 812 * @param int $sentMailId 813 * @param bool $usePlaceholders 814 */ 815 protected function sendChanneledMails( 816 string $to, 817 string $cc, 818 string $bcc, 819 array $usrIds, 820 string $subject, 821 string $message, 822 array $attachments, 823 int $sentMailId, 824 bool $usePlaceholders = false 825 ) : void { 826 $usrIdToExternalEmailAddressesMap = []; 827 $usrIdToMessageMap = []; 828 829 foreach ($usrIds as $usrId) { 830 $user = $this->getUserInstanceById($usrId); 831 $mailOptions = $this->getMailOptionsByUserId($user->getId()); 832 833 $canReadInternalMails = !$user->hasToAcceptTermsOfService() && $user->checkTimeLimit(); 834 835 $individualMessage = $message; 836 if ($usePlaceholders) { 837 $individualMessage = $this->replacePlaceholders($message, $user->getId()); 838 $usrIdToMessageMap[$user->getId()] = $individualMessage; 839 } 840 841 if ($user->getActive()) { 842 $wantsToReceiveExternalEmail = ( 843 $mailOptions->getIncomingType() == ilMailOptions::INCOMING_EMAIL || 844 $mailOptions->getIncomingType() == ilMailOptions::INCOMING_BOTH 845 ); 846 847 if (!$canReadInternalMails || $wantsToReceiveExternalEmail) { 848 $emailAddresses = $mailOptions->getExternalEmailAddresses(); 849 $usrIdToExternalEmailAddressesMap[$user->getId()] = $emailAddresses; 850 851 if ($mailOptions->getIncomingType() == ilMailOptions::INCOMING_EMAIL) { 852 $this->logger->debug(sprintf( 853 "Recipient with id %s will only receive external emails sent to: %s", 854 $user->getId(), 855 implode(', ', $emailAddresses) 856 )); 857 continue; 858 } else { 859 $this->logger->debug(sprintf( 860 "Recipient with id %s will additionally receive external emails " . 861 "(because the user wants to receive it externally, or the user cannot access " . 862 "the internal mail system) sent to: %s", 863 $user->getId(), 864 implode(', ', $emailAddresses) 865 )); 866 } 867 } else { 868 $this->logger->debug(sprintf( 869 "Recipient with id %s is does not want to receive external emails", 870 $user->getId() 871 )); 872 } 873 } else { 874 $this->logger->debug(sprintf( 875 "Recipient with id %s is inactive and will not receive external emails", 876 $user->getId() 877 )); 878 } 879 880 $mbox = clone $this->mailbox; 881 $mbox->setUsrId((int) $user->getId()); 882 $recipientInboxId = $mbox->getInboxFolder(); 883 884 $internalMailId = $this->sendInternalMail( 885 $recipientInboxId, 886 $this->user_id, 887 $attachments, 888 $to, 889 $cc, 890 '', 891 'unread', 892 0, 893 $subject, 894 $individualMessage, 895 $user->getId(), 896 0 897 ); 898 899 if (count($attachments) > 0) { 900 $this->mfile->assignAttachmentsToDirectory($internalMailId, $sentMailId); 901 } 902 } 903 904 $this->delegateExternalEmails( 905 $subject, 906 $message, 907 $attachments, 908 $usePlaceholders, 909 $usrIdToExternalEmailAddressesMap, 910 $usrIdToMessageMap 911 ); 912 } 913 914 /** 915 * @param string $subject 916 * @param string $message 917 * @param array $attachments 918 * @param bool $usePlaceholders 919 * @param array $usrIdToExternalEmailAddressesMap 920 * @param array $usrIdToMessageMap 921 */ 922 protected function delegateExternalEmails( 923 string $subject, 924 string $message, 925 array $attachments, 926 bool $usePlaceholders, 927 array $usrIdToExternalEmailAddressesMap, 928 array $usrIdToMessageMap 929 ) : void { 930 if (1 === count($usrIdToExternalEmailAddressesMap)) { 931 if ($usePlaceholders) { 932 $message = array_values($usrIdToMessageMap)[0]; 933 } 934 935 $usrIdToExternalEmailAddressesMap = array_values($usrIdToExternalEmailAddressesMap); 936 $firstAddresses = current($usrIdToExternalEmailAddressesMap); 937 938 $this->sendMimeMail( 939 implode(',', $firstAddresses), 940 '', 941 '', 942 $subject, 943 $this->formatLinebreakMessage($message), 944 (array) $attachments 945 ); 946 } elseif (count($usrIdToExternalEmailAddressesMap) > 1) { 947 if ($usePlaceholders) { 948 foreach ($usrIdToExternalEmailAddressesMap as $usrId => $addresses) { 949 if (0 === count($addresses)) { 950 continue; 951 } 952 953 $this->sendMimeMail( 954 implode(',', $addresses), 955 '', 956 '', 957 $subject, 958 $this->formatLinebreakMessage($usrIdToMessageMap[$usrId]), 959 (array) $attachments 960 ); 961 } 962 } else { 963 $flattenEmailAddresses = iterator_to_array(new RecursiveIteratorIterator(new RecursiveArrayIterator( 964 $usrIdToExternalEmailAddressesMap 965 )), false); 966 967 $flattenEmailAddresses = array_unique($flattenEmailAddresses); 968 969 // https://mantis.ilias.de/view.php?id=23981 and https://www.ietf.org/rfc/rfc2822.txt 970 $remainingAddresses = ''; 971 foreach ($flattenEmailAddresses as $emailAddress) { 972 $sep = ''; 973 if (strlen($remainingAddresses) > 0) { 974 $sep = ','; 975 } 976 977 $recipientsLineLength = ilStr::strLen($remainingAddresses) + ilStr::strLen($sep . $emailAddress); 978 if ($recipientsLineLength >= $this->maxRecipientCharacterLength) { 979 $this->sendMimeMail( 980 '', 981 '', 982 $remainingAddresses, 983 $subject, 984 $this->formatLinebreakMessage($message), 985 (array) $attachments 986 ); 987 988 $remainingAddresses = ''; 989 $sep = ''; 990 } 991 992 $remainingAddresses .= ($sep . $emailAddress); 993 } 994 995 if ('' !== $remainingAddresses) { 996 $this->sendMimeMail( 997 '', 998 '', 999 $remainingAddresses, 1000 $subject, 1001 $this->formatLinebreakMessage($message), 1002 (array) $attachments 1003 ); 1004 } 1005 } 1006 } 1007 } 1008 1009 /** 1010 * @param string[] $recipients 1011 * @return int[] 1012 */ 1013 protected function getUserIds(array $recipients) : array 1014 { 1015 $usrIds = array(); 1016 1017 $joinedRecipients = implode(',', array_filter(array_map('trim', $recipients))); 1018 1019 $addresses = $this->parseAddresses($joinedRecipients); 1020 foreach ($addresses as $address) { 1021 $addressType = $this->mailAddressTypeFactory->getByPrefix($address); 1022 $usrIds = array_merge($usrIds, $addressType->resolve()); 1023 } 1024 1025 return array_unique($usrIds); 1026 } 1027 1028 /** 1029 * @param string $to 1030 * @param string $cc 1031 * @param string $bcc 1032 * @param string $subject 1033 * @return ilMailError[] An array of errors determined on validation 1034 */ 1035 protected function checkMail(string $to, string $cc, string $bcc, string $subject) : array 1036 { 1037 $errors = []; 1038 1039 foreach ([ 1040 $subject => 'mail_add_subject', 1041 $to => 'mail_add_recipient' 1042 ] as $string => $error 1043 ) { 1044 if (0 === strlen($string)) { 1045 $errors[] = new ilMailError($error); 1046 } 1047 } 1048 1049 return $errors; 1050 } 1051 1052 /** 1053 * Check if recipients are valid 1054 * @param string $recipients 1055 * @return ilMailError[] An array of errors determined on validation 1056 * @throws ilMailException 1057 */ 1058 protected function checkRecipients(string $recipients) : array 1059 { 1060 $errors = []; 1061 1062 try { 1063 $addresses = $this->parseAddresses($recipients); 1064 foreach ($addresses as $address) { 1065 $addressType = $this->mailAddressTypeFactory->getByPrefix($address); 1066 if (!$addressType->validate($this->user_id)) { 1067 $newErrors = $addressType->getErrors(); 1068 $errors = array_merge($errors, $newErrors); 1069 } 1070 } 1071 } catch (ilException $e) { 1072 $colonPosition = strpos($e->getMessage(), ':'); 1073 throw new ilMailException( 1074 ($colonPosition === false) ? $e->getMessage() : substr($e->getMessage(), $colonPosition + 2) 1075 ); 1076 } 1077 1078 return $errors; 1079 } 1080 1081 /** 1082 * save post data in table 1083 * @access public 1084 * @param int $a_user_id 1085 * @param array $a_attachments 1086 * @param string $a_rcp_to 1087 * @param string $a_rcp_cc 1088 * @param string $a_rcp_bcc 1089 * @param int $a_m_email 1090 * @param string $a_m_subject 1091 * @param string $a_m_message 1092 * @param int $a_use_placeholders 1093 * @param string|null $a_tpl_context_id 1094 * @param array|null $a_tpl_ctx_params 1095 * @return bool 1096 */ 1097 public function savePostData( 1098 $a_user_id, 1099 $a_attachments, 1100 $a_rcp_to, 1101 $a_rcp_cc, 1102 $a_rcp_bcc, 1103 $a_m_email, 1104 $a_m_subject, 1105 $a_m_message, 1106 $a_use_placeholders, 1107 $a_tpl_context_id = null, 1108 $a_tpl_ctx_params = array() 1109 ) { 1110 if (!$a_attachments) { 1111 $a_attachments = null; 1112 } 1113 if (!$a_rcp_to) { 1114 $a_rcp_to = null; 1115 } 1116 if (!$a_rcp_cc) { 1117 $a_rcp_cc = null; 1118 } 1119 if (!$a_rcp_bcc) { 1120 $a_rcp_bcc = null; 1121 } 1122 if (!$a_m_email) { 1123 $a_m_email = null; 1124 } 1125 if (!$a_m_message) { 1126 $a_m_message = null; 1127 } 1128 if (!$a_use_placeholders) { 1129 $a_use_placeholders = '0'; 1130 } 1131 1132 $this->db->replace( 1133 $this->table_mail_saved, 1134 [ 1135 'user_id' => ['integer', $this->user_id] 1136 ], 1137 [ 1138 'attachments' => ['clob', serialize($a_attachments)], 1139 'rcp_to' => ['clob', $a_rcp_to], 1140 'rcp_cc' => ['clob', $a_rcp_cc], 1141 'rcp_bcc' => ['clob', $a_rcp_bcc], 1142 'm_email' => ['integer', $a_m_email], 1143 'm_subject' => ['text', $a_m_subject], 1144 'm_message' => ['clob', $a_m_message], 1145 'use_placeholders' => ['integer', $a_use_placeholders], 1146 'tpl_ctx_id' => ['text', $a_tpl_context_id], 1147 'tpl_ctx_params' => ['blob', json_encode((array) $a_tpl_ctx_params)] 1148 ] 1149 ); 1150 1151 $this->getSavedData(); 1152 1153 return true; 1154 } 1155 1156 /** 1157 * @return array|null 1158 */ 1159 public function getSavedData() : ?array 1160 { 1161 $res = $this->db->queryF( 1162 "SELECT * FROM {$this->table_mail_saved} WHERE user_id = %s", 1163 ['integer'], 1164 [$this->user_id] 1165 ); 1166 1167 $this->mail_data = $this->fetchMailData($this->db->fetchAssoc($res)); 1168 1169 return $this->mail_data; 1170 } 1171 1172 /** 1173 * Should be used to enqueue a 'mail'. A validation is executed before, errors are returned 1174 * @param string $a_rcp_to 1175 * @param string $a_rcp_cc 1176 * @param string $a_rcp_bcc 1177 * @param string $a_m_subject 1178 * @param string $a_m_message 1179 * @param array $a_attachment 1180 * @param bool|int $a_use_placeholders 1181 * @return ilMailError[] 1182 */ 1183 public function enqueue( 1184 $a_rcp_to, 1185 $a_rcp_cc, 1186 $a_rcp_bcc, 1187 $a_m_subject, 1188 $a_m_message, 1189 $a_attachment, 1190 $a_use_placeholders = 0 1191 ) : array { 1192 global $DIC; 1193 1194 $this->logger->debug( 1195 "New mail system task:" . 1196 " To: " . $a_rcp_to . 1197 " | CC: " . $a_rcp_cc . 1198 " | BCC: " . $a_rcp_bcc . 1199 " | Subject: " . $a_m_subject 1200 ); 1201 1202 if ($a_attachment && !$this->mfile->checkFilesExist($a_attachment)) { 1203 return [new ilMailError('mail_attachment_file_not_exist', [$a_attachment])]; 1204 } 1205 1206 $errors = $this->checkMail((string) $a_rcp_to, (string) $a_rcp_cc, (string) $a_rcp_bcc, (string) $a_m_subject); 1207 if (count($errors) > 0) { 1208 return $errors; 1209 } 1210 1211 $errors = $this->validateRecipients((string) $a_rcp_to, (string) $a_rcp_cc, (string) $a_rcp_bcc); 1212 if (count($errors) > 0) { 1213 return $errors; 1214 } 1215 1216 $rcp_to = $a_rcp_to; 1217 $rcp_cc = $a_rcp_cc; 1218 $rcp_bcc = $a_rcp_bcc; 1219 1220 if (null === $rcp_cc) { 1221 $rcp_cc = ''; 1222 } 1223 1224 if (null === $rcp_bcc) { 1225 $rcp_bcc = ''; 1226 } 1227 1228 $numberOfExternalAddresses = $this->getCountRecipients($rcp_to, $rcp_cc, $rcp_bcc, true); 1229 if ( 1230 $numberOfExternalAddresses > 0 && 1231 !$this->isSystemMail() && 1232 !$DIC->rbac()->system()->checkAccessOfUser($this->user_id, 'smtp_mail', $this->mail_obj_ref_id) 1233 ) { 1234 return [new ilMailError('mail_no_permissions_write_smtp')]; 1235 } 1236 1237 if ($this->appendInstallationSignature()) { 1238 $a_m_message .= self::_getInstallationSignature(); 1239 } 1240 1241 if (ilContext::getType() == ilContext::CONTEXT_CRON) { 1242 return $this->sendMail( 1243 (string) $rcp_to, 1244 (string) $rcp_cc, 1245 (string) $rcp_bcc, 1246 (string) $a_m_subject, 1247 (string) $a_m_message, 1248 (array) $a_attachment, 1249 (bool) $a_use_placeholders 1250 ); 1251 } 1252 1253 $taskFactory = $DIC->backgroundTasks()->taskFactory(); 1254 $taskManager = $DIC->backgroundTasks()->taskManager(); 1255 1256 $bucket = new BasicBucket(); 1257 $bucket->setUserId($this->user_id); 1258 1259 $task = $taskFactory->createTask(ilMailDeliveryJob::class, [ 1260 (int) $this->user_id, 1261 (string) $rcp_to, 1262 (string) $rcp_cc, 1263 (string) $rcp_bcc, 1264 (string) $a_m_subject, 1265 (string) $a_m_message, 1266 (string) serialize($a_attachment), 1267 (bool) $a_use_placeholders, 1268 (bool) $this->getSaveInSentbox(), 1269 (string) $this->contextId, 1270 (string) serialize($this->contextParameters) 1271 ]); 1272 $interaction = $taskFactory->createTask(ilMailDeliveryJobUserInteraction::class, [ 1273 $task, 1274 (int) $this->user_id 1275 ]); 1276 1277 $bucket->setTask($interaction); 1278 $bucket->setTitle($this->lng->txt('mail_bg_task_title')); 1279 $bucket->setDescription(sprintf($this->lng->txt('mail_bg_task_desc'), $a_m_subject)); 1280 1281 $this->logger->info('Delegated delivery to background task'); 1282 $taskManager->run($bucket); 1283 1284 return []; 1285 } 1286 1287 /** 1288 * This method is used to finally send internal messages and external emails 1289 * To use the mail system as a consumer, please use \ilMail::enqueue 1290 * @param string $to 1291 * @param string $cc 1292 * @param string $bcc 1293 * @param string $subject 1294 * @param string $message 1295 * @param array $attachments 1296 * @param bool $usePlaceholders 1297 * @return ilMailError[] 1298 * @see \ilMail::enqueue() 1299 * @internal 1300 */ 1301 public function sendMail( 1302 string $to, 1303 string $cc, 1304 string $bcc, 1305 string $subject, 1306 string $message, 1307 array $attachments, 1308 bool $usePlaceholders 1309 ) : array { 1310 $internalMessageId = $this->saveInSentbox( 1311 $attachments, 1312 $to, 1313 $cc, 1314 $bcc, 1315 $subject, 1316 $message 1317 ); 1318 1319 if (count($attachments) > 0) { 1320 $this->mfile->assignAttachmentsToDirectory($internalMessageId, $internalMessageId); 1321 $this->mfile->saveFiles($internalMessageId, $attachments); 1322 } 1323 1324 $numberOfExternalAddresses = $this->getCountRecipients($to, $cc, $bcc, true); 1325 1326 if ($numberOfExternalAddresses > 0) { 1327 $externalMailRecipientsTo = $this->getEmailRecipients($to); 1328 $externalMailRecipientsCc = $this->getEmailRecipients($cc); 1329 $externalMailRecipientsBcc = $this->getEmailRecipients($bcc); 1330 1331 $this->logger->debug( 1332 "Parsed external email addresses from given recipients /" . 1333 " To: " . $externalMailRecipientsTo . 1334 " | CC: " . $externalMailRecipientsCc . 1335 " | BCC: " . $externalMailRecipientsBcc . 1336 " | Subject: " . $subject 1337 ); 1338 1339 $this->sendMimeMail( 1340 $externalMailRecipientsTo, 1341 $externalMailRecipientsCc, 1342 $externalMailRecipientsBcc, 1343 $subject, 1344 $this->formatLinebreakMessage( 1345 $usePlaceholders ? $this->replacePlaceholders($message, 0, false) : $message 1346 ), 1347 $attachments 1348 ); 1349 } else { 1350 $this->logger->debug('No external email addresses given in recipient string'); 1351 } 1352 1353 $errors = []; 1354 1355 if (!$this->distributeMail( 1356 $to, 1357 $cc, 1358 $bcc, 1359 $subject, 1360 $message, 1361 $attachments, 1362 $internalMessageId, 1363 $usePlaceholders 1364 )) { 1365 $errors['mail_send_error'] = new ilMailError('mail_send_error'); 1366 } 1367 1368 if (!$this->getSaveInSentbox()) { 1369 $this->deleteMails([$internalMessageId]); 1370 } 1371 1372 return array_values($errors); 1373 } 1374 1375 /** 1376 * @param string $to 1377 * @param string $cc 1378 * @param string $bcc 1379 * @return ilMailError[] An array of errors determined on validation 1380 */ 1381 public function validateRecipients(string $to, string $cc, string $bcc) : array 1382 { 1383 try { 1384 $errors = []; 1385 $errors = array_merge($errors, $this->checkRecipients($to)); 1386 $errors = array_merge($errors, $this->checkRecipients($cc)); 1387 $errors = array_merge($errors, $this->checkRecipients($bcc)); 1388 1389 if (count($errors) > 0) { 1390 return array_merge([new ilMailError('mail_following_rcp_not_valid')], $errors); 1391 } 1392 } catch (ilMailException $e) { 1393 return [new ilMailError('mail_generic_rcp_error', [$e->getMessage()])]; 1394 } 1395 1396 return []; 1397 } 1398 1399 /** 1400 * Stores a message in the sent bod of the current user 1401 * @param array $attachment 1402 * @param string $to 1403 * @param string $cc 1404 * @param string $bcc 1405 * @param string $subject 1406 * @param string $message 1407 * @return int mail id 1408 */ 1409 protected function saveInSentbox( 1410 array $attachment, 1411 string $to, 1412 string $cc, 1413 string $bcc, 1414 string $subject, 1415 string $message 1416 ) : int { 1417 return $this->sendInternalMail( 1418 $this->mailbox->getSentFolder(), 1419 $this->user_id, 1420 $attachment, 1421 $to, 1422 $cc, 1423 $bcc, 1424 'read', 1425 0, 1426 $subject, 1427 $message, 1428 $this->user_id, 1429 0 1430 ); 1431 } 1432 1433 /** 1434 * @param string $to 1435 * @param string $cc 1436 * @param string $bcc 1437 * @param string $subject 1438 * @param string $message 1439 * @param array $attachments 1440 */ 1441 private function sendMimeMail(string $to, string $cc, string $bcc, $subject, $message, array $attachments) : void 1442 { 1443 $mailer = new ilMimeMail(); 1444 $mailer->From($this->senderFactory->getSenderByUsrId((int) $this->user_id)); 1445 $mailer->To($to); 1446 $mailer->Subject($subject, true); 1447 $mailer->Body($message); 1448 1449 if ($cc) { 1450 $mailer->Cc($cc); 1451 } 1452 1453 if ($bcc) { 1454 $mailer->Bcc($bcc); 1455 } 1456 1457 foreach ($attachments as $attachment) { 1458 $mailer->Attach( 1459 $this->mfile->getAbsoluteAttachmentPoolPathByFilename($attachment), 1460 '', 1461 'inline', 1462 $attachment 1463 ); 1464 } 1465 1466 $mailer->Send(); 1467 } 1468 1469 /** 1470 * @param string[] $attachments An array of attachments 1471 */ 1472 public function saveAttachments(array $attachments) : void 1473 { 1474 $this->db->update( 1475 $this->table_mail_saved, 1476 [ 1477 'attachments' => ['clob', serialize($attachments)] 1478 ], 1479 [ 1480 'user_id' => ['integer', $this->user_id] 1481 ] 1482 ); 1483 } 1484 1485 /** 1486 * Explode recipient string, allowed separators are ',' ';' ' ' 1487 * Returns an array with recipient ilMailAddress instances 1488 * @param string $addresses 1489 * @return ilMailAddress[] An array with objects of type ilMailAddress 1490 */ 1491 protected function parseAddresses($addresses) : array 1492 { 1493 if (strlen($addresses) > 0) { 1494 $this->logger->debug(sprintf( 1495 "Started parsing of recipient string: %s", 1496 $addresses 1497 )); 1498 } 1499 1500 $parser = $this->mailAddressParserFactory->getParser((string) $addresses); 1501 $parsedAddresses = $parser->parse(); 1502 1503 if (strlen($addresses) > 0) { 1504 $this->logger->debug(sprintf( 1505 "Parsed addresses: %s", 1506 implode(',', array_map(function (ilMailAddress $address) { 1507 return (string) $address; 1508 }, $parsedAddresses)) 1509 )); 1510 } 1511 1512 return $parsedAddresses; 1513 } 1514 1515 /** 1516 * @param string $recipients 1517 * @param bool $onlyExternalAddresses 1518 * @return int 1519 */ 1520 protected function getCountRecipient(string $recipients, $onlyExternalAddresses = true) : int 1521 { 1522 $addresses = new ilMailAddressListImpl($this->parseAddresses($recipients)); 1523 if ($onlyExternalAddresses) { 1524 $addresses = new ilMailOnlyExternalAddressList( 1525 $addresses, 1526 self::ILIAS_HOST, 1527 $this->usrIdByLoginCallable 1528 ); 1529 } 1530 1531 return count($addresses->value()); 1532 } 1533 1534 /** 1535 * @param string $toRecipients 1536 * @param string $ccRecipients 1537 * @param $bccRecipients 1538 * @param bool $onlyExternalAddresses 1539 * @return int 1540 */ 1541 protected function getCountRecipients( 1542 string $toRecipients, 1543 string $ccRecipients, 1544 string $bccRecipients, 1545 $onlyExternalAddresses = true 1546 ) : int { 1547 return ( 1548 $this->getCountRecipient($toRecipients, $onlyExternalAddresses) + 1549 $this->getCountRecipient($ccRecipients, $onlyExternalAddresses) + 1550 $this->getCountRecipient($bccRecipients, $onlyExternalAddresses) 1551 ); 1552 } 1553 1554 /** 1555 * @param string $recipients 1556 * @return string 1557 */ 1558 protected function getEmailRecipients(string $recipients) : string 1559 { 1560 $addresses = new ilMailOnlyExternalAddressList( 1561 new ilMailAddressListImpl($this->parseAddresses($recipients)), 1562 self::ILIAS_HOST, 1563 $this->usrIdByLoginCallable 1564 ); 1565 1566 $emailRecipients = array_map(function (ilMailAddress $address) { 1567 return (string) $address; 1568 }, $addresses->value()); 1569 1570 return implode(',', $emailRecipients); 1571 } 1572 1573 /** 1574 * Get auto generated info string 1575 * @param ilLanguage $lang 1576 * @return string; 1577 */ 1578 public static function _getAutoGeneratedMessageString(ilLanguage $lang = null) : string 1579 { 1580 global $DIC; 1581 1582 if (!($lang instanceof ilLanguage)) { 1583 $lang = ilLanguageFactory::_getLanguage(); 1584 } 1585 1586 $lang->loadLanguageModule('mail'); 1587 1588 return sprintf( 1589 $lang->txt('mail_auto_generated_info'), 1590 $DIC->settings()->get('inst_name', 'ILIAS ' . ((int) ILIAS_VERSION_NUMERIC)), 1591 ilUtil::_getHttpPath() 1592 ) . "\n\n"; 1593 } 1594 1595 /** 1596 * @return string 1597 */ 1598 public static function _getIliasMailerName() : string 1599 { 1600 /** @var ilMailMimeSenderFactory $senderFactory */ 1601 $senderFactory = $GLOBALS["DIC"]["mail.mime.sender.factory"]; 1602 1603 return $senderFactory->system()->getFromName(); 1604 } 1605 1606 /** 1607 * @param bool|null $a_flag 1608 * @return self|bool 1609 */ 1610 public function appendInstallationSignature(bool $a_flag = null) 1611 { 1612 if (null === $a_flag) { 1613 return $this->appendInstallationSignature; 1614 } 1615 1616 $this->appendInstallationSignature = $a_flag; 1617 return $this; 1618 } 1619 1620 /** 1621 * @return string The installation mail signature 1622 */ 1623 public static function _getInstallationSignature() : string 1624 { 1625 global $DIC; 1626 1627 $signature = $DIC->settings()->get('mail_system_sys_signature'); 1628 1629 $clientUrl = ilUtil::_getHttpPath(); 1630 $clientdirs = glob(ILIAS_WEB_DIR . '/*', GLOB_ONLYDIR); 1631 if (is_array($clientdirs) && count($clientdirs) > 1) { 1632 $clientUrl .= '/login.php?client_id=' . CLIENT_ID; // #18051 1633 } 1634 1635 $signature = str_ireplace('[CLIENT_NAME]', $DIC['ilClientIniFile']->readVariable('client', 'name'), $signature); 1636 $signature = str_ireplace( 1637 '[CLIENT_DESC]', 1638 $DIC['ilClientIniFile']->readVariable('client', 'description'), 1639 $signature 1640 ); 1641 $signature = str_ireplace('[CLIENT_URL]', $clientUrl, $signature); 1642 1643 if (!preg_match('/^[\n\r]+/', $signature)) { 1644 $signature = "\n" . $signature; 1645 } 1646 1647 return $signature; 1648 } 1649 1650 /** 1651 * @param int $a_usr_id 1652 * @param $a_language ilLanguage|null 1653 * @return string 1654 */ 1655 public static function getSalutation($a_usr_id, ilLanguage $a_language = null) : string 1656 { 1657 global $DIC; 1658 1659 $lang = ($a_language instanceof ilLanguage) ? $a_language : $DIC->language(); 1660 $lang->loadLanguageModule('mail'); 1661 1662 $gender = ilObjUser::_lookupGender($a_usr_id); 1663 $gender = $gender ? $gender : 'n'; 1664 $name = ilObjUser::_lookupName($a_usr_id); 1665 1666 if (!strlen($name['firstname'])) { 1667 return $lang->txt('mail_salutation_anonymous') . ','; 1668 } 1669 1670 return 1671 $lang->txt('mail_salutation_' . $gender) . ' ' . 1672 ($name['title'] ? $name['title'] . ' ' : '') . 1673 ($name['firstname'] ? $name['firstname'] . ' ' : '') . 1674 $name['lastname'] . ','; 1675 } 1676 1677 /** 1678 * @param int $usrId 1679 * @return ilObjUser 1680 */ 1681 protected function getUserInstanceById(int $usrId) : ilObjUser 1682 { 1683 if (!isset($this->userInstancesByIdMap[$usrId])) { 1684 $this->userInstancesByIdMap[$usrId] = new ilObjUser($usrId); 1685 } 1686 1687 return $this->userInstancesByIdMap[$usrId]; 1688 } 1689 1690 /** 1691 * @param ilObjUser[] $userInstanceByIdMap 1692 * @internal 1693 */ 1694 public function setUserInstanceById(array $userInstanceByIdMap) : void 1695 { 1696 $this->userInstancesByIdMap = $userInstanceByIdMap; 1697 } 1698 1699 /** 1700 * @param int $usrId 1701 * @return ilMailOptions 1702 */ 1703 protected function getMailOptionsByUserId(int $usrId) : ilMailOptions 1704 { 1705 if (!isset($this->mailOptionsByUsrIdMap[$usrId])) { 1706 $this->mailOptionsByUsrIdMap[$usrId] = new ilMailOptions($usrId); 1707 } 1708 1709 return $this->mailOptionsByUsrIdMap[$usrId]; 1710 } 1711 1712 /** 1713 * @param ilMailOptions[] $mailOptionsByUsrIdMap 1714 * @internal 1715 */ 1716 public function setMailOptionsByUserIdMap(array $mailOptionsByUsrIdMap) : void 1717 { 1718 $this->mailOptionsByUsrIdMap = $mailOptionsByUsrIdMap; 1719 } 1720 1721 /** 1722 * @inheritdoc 1723 */ 1724 public function formatLinebreakMessage(string $message) : string 1725 { 1726 return $message; 1727 } 1728} 1729