ILIAS  trunk Revision v11.0_alpha-1753-gb21ca8c4367
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
class.ilMail.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
26 
31 class ilMail
32 {
33  public const ILIAS_HOST = 'ilias';
34  public const PROP_CONTEXT_SUBJECT_PREFIX = 'subject_prefix';
35 
37  public int $user_id;
38  private string $table_mail;
39  private string $table_mail_saved;
41  protected ?array $mail_data = [];
42  private bool $save_in_sentbox;
43  private bool $append_installation_signature = false;
44  private bool $append_user_signature = false;
45 
46  private ?string $context_id = null;
47  private array $context_parameters = [];
48 
50  private array $mail_options_by_usr_id_map = [];
51 
53  private array $user_instances_by_id_map = [];
55  private readonly Conductor $legal_documents;
56 
57  public function __construct(
58  private int $a_user_id,
59  private ?ilMailAddressTypeFactory $mail_address_type_factory = null,
60  private ilMailRfc822AddressParserFactory $mail_address_parser_factory = new ilMailRfc822AddressParserFactory(),
61  private ?ilAppEventHandler $event_handler = null,
62  private ?ilLogger $logger = null,
63  private ?ilDBInterface $db = null,
64  private ?ilLanguage $lng = null,
65  private ?ilFileDataMail $mail_file_data = null,
66  protected ?ilMailOptions $mail_options = null,
67  private ?ilMailbox $mailbox = null,
68  private ?ilMailMimeSenderFactory $sender_factory = null,
69  private ?Closure $usr_id_by_login_callable = null,
70  private ?AutoresponderService $auto_responder_service = null,
71  private ?int $mail_admin_node_ref_id = null,
72  private ?int $mail_obj_ref_id = null,
73  private ?ilObjUser $actor = null,
74  private ?ilMailTemplatePlaceholderResolver $placeholder_resolver = null,
75  private ?ilMailTemplatePlaceholderToEmptyResolver $placeholder_to_empty_resolver = null,
76  ?Conductor $legal_documents = null,
77  ?MailSignatureService $signature_service = null,
78  ) {
79  global $DIC;
80  $this->logger = $logger ?? ilLoggerFactory::getLogger('mail');
81  $this->mail_address_type_factory = $mail_address_type_factory ?? new ilMailAddressTypeFactory(null, $logger);
82  $this->event_handler = $event_handler ?? $DIC->event();
83  $this->db = $db ?? $DIC->database();
84  $this->lng = $lng ?? $DIC->language();
85  $this->actor = $actor ?? $DIC->user();
86  $this->mail_file_data = $mail_file_data ?? new ilFileDataMail($a_user_id);
87  $this->mail_options = $mail_options ?? new ilMailOptions($a_user_id);
88  $this->mailbox = $mailbox ?? new ilMailbox($a_user_id);
89 
90  $this->sender_factory = $sender_factory ?? $DIC->mail()->mime()->senderFactory();
91  $this->usr_id_by_login_callable = $usr_id_by_login_callable ?? static function (string $login): int {
92  return (int) ilObjUser::_lookupId($login);
93  };
94  $this->auto_responder_service = $auto_responder_service ?? $DIC->mail()->autoresponder();
95  $this->user_id = $a_user_id;
96  if (null === $this->mail_obj_ref_id) {
98  }
99  $this->lng->loadLanguageModule('mail');
100  $this->table_mail = 'mail';
101  $this->table_mail_saved = 'mail_saved';
102  $this->setSaveInSentbox(false);
103  $this->placeholder_resolver = $placeholder_resolver ?? $DIC->mail()->placeholderResolver();
104  $this->placeholder_to_empty_resolver = $placeholder_to_empty_resolver ?? $DIC->mail()->placeholderToEmptyResolver();
105  $this->legal_documents = $legal_documents ?? $DIC['legalDocuments'];
106  $this->signature_service = $signature_service ?? $DIC->mail()->signature();
107  }
108 
110  {
111  return $this->auto_responder_service;
112  }
113 
114  public function withContextId(string $contextId): self
115  {
116  $clone = clone $this;
117 
118  $clone->context_id = $contextId;
119 
120  return $clone;
121  }
122 
123  public function withContextParameters(array $parameters): self
124  {
125  $clone = clone $this;
126 
127  $clone->context_parameters = $parameters;
128 
129  return $clone;
130  }
131 
132  private function isSystemMail(): bool
133  {
134  return $this->user_id === ANONYMOUS_USER_ID;
135  }
136 
137  public function existsRecipient(string $newRecipient, string $existingRecipients): bool
138  {
139  $newAddresses = new ilMailAddressListImpl($this->parseAddresses($newRecipient));
140  $addresses = new ilMailAddressListImpl($this->parseAddresses($existingRecipients));
141 
142  $list = new ilMailDiffAddressList($newAddresses, $addresses);
143 
144  $diffedAddresses = $list->value();
145 
146  return $diffedAddresses === [];
147  }
148 
149  public function setSaveInSentbox(bool $saveInSentbox): void
150  {
151  $this->save_in_sentbox = $saveInSentbox;
152  }
153 
154  public function getSaveInSentbox(): bool
155  {
156  return $this->save_in_sentbox;
157  }
158 
159  private function readMailObjectReferenceId(): void
160  {
161  $this->mail_obj_ref_id = ilMailGlobalServices::getMailObjectRefId();
162  }
163 
164  public function getMailObjectReferenceId(): int
165  {
166  return $this->mail_obj_ref_id;
167  }
168 
169  public function formatNamesForOutput(string $recipients): string
170  {
171  $recipients = trim($recipients);
172  if ($recipients === '') {
173  return $this->lng->txt('not_available');
174  }
175 
176  $names = [];
177 
178  $recipients = array_filter(array_map('trim', explode(',', $recipients)));
179  foreach ($recipients as $recipient) {
180  $usrId = ilObjUser::_lookupId($recipient);
181  if (is_int($usrId) && $usrId > 0) {
182  $pp = ilObjUser::_lookupPref($usrId, 'public_profile');
183  if ($pp === 'g' || ($pp === 'y' && !$this->actor->isAnonymous())) {
184  $user = $this->getUserInstanceById($usrId);
185  if ($user) {
186  $names[] = $user->getFullname() . ' [' . $recipient . ']';
187  continue;
188  }
189  }
190  }
191 
192  $names[] = $recipient;
193  }
194 
195  return implode(', ', $names);
196  }
197 
198  public function getPreviousMail(int $mailId): ?array
199  {
200  $this->db->setLimit(1, 0);
201 
202  $query = implode(' ', [
203  "SELECT b.* FROM $this->table_mail a",
204  "INNER JOIN $this->table_mail b ON b.folder_id = a.folder_id",
205  'AND b.user_id = a.user_id AND b.send_time > a.send_time',
206  'WHERE a.user_id = %s AND a.mail_id = %s ORDER BY b.send_time ASC',
207  ]);
208  $res = $this->db->queryF(
209  $query,
210  ['integer', 'integer'],
211  [$this->user_id, $mailId]
212  );
213 
214  $this->mail_data = $this->fetchMailData($this->db->fetchAssoc($res));
215 
216  return $this->mail_data;
217  }
218 
219  public function getNextMail(int $mailId): ?array
220  {
221  $this->db->setLimit(1, 0);
222 
223  $query = implode(' ', [
224  "SELECT b.* FROM $this->table_mail a",
225  "INNER JOIN $this->table_mail b ON b.folder_id = a.folder_id",
226  'AND b.user_id = a.user_id AND b.send_time < a.send_time',
227  'WHERE a.user_id = %s AND a.mail_id = %s ORDER BY b.send_time DESC',
228  ]);
229  $res = $this->db->queryF(
230  $query,
231  ['integer', 'integer'],
232  [$this->user_id, $mailId]
233  );
234 
235  $this->mail_data = $this->fetchMailData($this->db->fetchAssoc($res));
236 
237  return $this->mail_data;
238  }
239 
240  public function getMailsOfFolder(int $a_folder_id, array $filter = []): array
241  {
242  $mails = [];
243 
244  $query =
245  "SELECT sender_id, m_subject, mail_id, m_status, send_time, import_name " .
246  "FROM $this->table_mail " .
247  "LEFT JOIN object_data ON obj_id = sender_id " .
248  "WHERE user_id = %s AND folder_id = %s " .
249  "AND ((sender_id > 0 AND sender_id IS NOT NULL AND obj_id IS NOT NULL) " .
250  "OR (sender_id = 0 OR sender_id IS NULL))";
251 
252  if (isset($filter['status']) && $filter['status'] !== '') {
253  $query .= ' AND m_status = ' . $this->db->quote($filter['status'], 'text');
254  }
255 
256  $query .= " ORDER BY send_time DESC";
257 
258  $res = $this->db->queryF(
259  $query,
260  ['integer', 'integer'],
261  [$this->user_id, $a_folder_id]
262  );
263 
264  while ($row = $this->db->fetchAssoc($res)) {
265  $mails[] = $this->fetchMailData($row);
266  }
267 
268  return array_filter($mails);
269  }
270 
271  public function countMailsOfFolder(int $folderId): int
272  {
273  $res = $this->db->queryF(
274  "SELECT COUNT(*) FROM $this->table_mail WHERE user_id = %s AND folder_id = %s",
275  ['integer', 'integer'],
276  [$this->user_id, $folderId]
277  );
278 
279  return $this->db->numRows($res);
280  }
281 
282  public function deleteMailsOfFolder(int $folderId): void
283  {
284  $mails = $this->getMailsOfFolder($folderId);
285  foreach ($mails as $mail_data) {
286  $this->deleteMails([$mail_data['mail_id']]);
287  }
288  }
289 
290  public function getMail(int $mailId): ?array
291  {
292  $res = $this->db->queryF(
293  "SELECT * FROM $this->table_mail WHERE user_id = %s AND mail_id = %s",
294  ['integer', 'integer'],
295  [$this->user_id, $mailId]
296  );
297 
298  $this->mail_data = $this->fetchMailData($this->db->fetchAssoc($res));
299 
300  return $this->mail_data;
301  }
302 
306  public function markRead(array $mailIds): void
307  {
308  $values = [];
309  $types = [];
310 
311  $query = "UPDATE $this->table_mail SET m_status = %s WHERE user_id = %s ";
312  $types[] = 'text';
313  $types[] = 'integer';
314  $values[] = 'read';
315  $values[] = $this->user_id;
316 
317  if ($mailIds !== []) {
318  $query .= ' AND ' . $this->db->in('mail_id', $mailIds, false, 'integer');
319  }
320 
321  $this->db->manipulateF($query, $types, $values);
322  }
323 
327  public function markUnread(array $mailIds): void
328  {
329  $values = [];
330  $types = [];
331 
332  $query = "UPDATE $this->table_mail SET m_status = %s WHERE user_id = %s ";
333  $types[] = 'text';
334  $types[] = 'integer';
335  $values[] = 'unread';
336  $values[] = $this->user_id;
337 
338  if ($mailIds !== []) {
339  $query .= ' AND ' . $this->db->in('mail_id', $mailIds, false, 'integer');
340  }
341 
342  $this->db->manipulateF($query, $types, $values);
343  }
344 
348  public function moveMailsToFolder(array $mailIds, int $folderId): bool
349  {
350  $values = [];
351  $types = [];
352 
353  $mailIds = array_filter(array_map('intval', $mailIds));
354 
355  if ([] === $mailIds) {
356  return false;
357  }
358 
359  $query =
360  "UPDATE $this->table_mail " .
361  "INNER JOIN mail_obj_data " .
362  "ON mail_obj_data.obj_id = %s AND mail_obj_data.user_id = %s " .
363  "SET $this->table_mail.folder_id = mail_obj_data.obj_id " .
364  "WHERE $this->table_mail.user_id = %s";
365  $types[] = 'integer';
366  $types[] = 'integer';
367  $types[] = 'integer';
368  $values[] = $folderId;
369  $values[] = $this->user_id;
370  $values[] = $this->user_id;
371 
372  $query .= ' AND ' . $this->db->in('mail_id', $mailIds, false, 'integer');
373 
374  $affectedRows = $this->db->manipulateF($query, $types, $values);
375 
376  return $affectedRows > 0;
377  }
378 
382  public function deleteMails(array $mailIds): void
383  {
384  $mailIds = array_filter(array_map('intval', $mailIds));
385  foreach ($mailIds as $id) {
386  $this->db->manipulateF(
387  "DELETE FROM $this->table_mail WHERE user_id = %s AND mail_id = %s",
388  ['integer', 'integer'],
389  [$this->user_id, $id]
390  );
391  $this->mail_file_data->deassignAttachmentFromDirectory($id);
392  }
393  }
394 
395  private function fetchMailData(?array $row): ?array
396  {
397  if (!is_array($row) || empty($row)) {
398  return null;
399  }
400 
401  if (isset($row['attachments'])) {
402  $unserialized = unserialize(stripslashes($row['attachments']), ['allowed_classes' => false]);
403  $row['attachments'] = is_array($unserialized) ? $unserialized : [];
404  } else {
405  $row['attachments'] = [];
406  }
407 
408  if (isset($row['tpl_ctx_params']) && is_string($row['tpl_ctx_params'])) {
409  $decoded = json_decode($row['tpl_ctx_params'], true, 512, JSON_THROW_ON_ERROR);
410  $row['tpl_ctx_params'] = (array) ($decoded ?? []);
411  } else {
412  $row['tpl_ctx_params'] = [];
413  }
414 
415  if (isset($row['mail_id'])) {
416  $row['mail_id'] = (int) $row['mail_id'];
417  }
418 
419  if (isset($row['user_id'])) {
420  $row['user_id'] = (int) $row['user_id'];
421  }
422 
423  if (isset($row['folder_id'])) {
424  $row['folder_id'] = (int) $row['folder_id'];
425  }
426 
427  if (isset($row['sender_id'])) {
428  $row['sender_id'] = (int) $row['sender_id'];
429  }
430 
431  if (isset($row['use_placeholders'])) {
432  $row['use_placeholders'] = (bool) $row['use_placeholders'];
433  }
434 
435  $null_to_string_properties = ['m_subject', 'm_message', 'rcp_to', 'rcp_cc', 'rcp_bcc'];
436  foreach ($null_to_string_properties as $null_to_string_property) {
437  if (!isset($row[$null_to_string_property])) {
438  $row[$null_to_string_property] = '';
439  }
440  }
441 
442  return $row;
443  }
444 
445  public function getNewDraftId(int $folderId): int
446  {
447  $nextId = $this->db->nextId($this->table_mail);
448  $this->db->insert($this->table_mail, [
449  'mail_id' => ['integer', $nextId],
450  'user_id' => ['integer', $this->user_id],
451  'folder_id' => ['integer', $folderId],
452  'sender_id' => ['integer', $this->user_id],
453  ]);
454 
455  return $nextId;
456  }
457 
461  public function updateDraft(
462  int $a_folder_id,
463  array $a_attachments,
464  string $a_rcp_to,
465  string $a_rcp_cc,
466  string $a_rcp_bcc,
467  string $a_m_subject,
468  string $a_m_message,
469  int $a_draft_id = 0,
470  bool $a_use_placeholders = false,
471  ?string $a_tpl_context_id = null,
472  array $a_tpl_context_params = []
473  ): int {
474  $this->db->update(
475  $this->table_mail,
476  [
477  'folder_id' => ['integer', $a_folder_id],
478  'attachments' => ['clob', serialize($a_attachments)],
479  'send_time' => ['timestamp', date('Y-m-d H:i:s')],
480  'rcp_to' => ['clob', $a_rcp_to],
481  'rcp_cc' => ['clob', $a_rcp_cc],
482  'rcp_bcc' => ['clob', $a_rcp_bcc],
483  'm_status' => ['text', 'read'],
484  'm_subject' => ['text', $a_m_subject],
485  'm_message' => ['clob', $a_m_message],
486  'use_placeholders' => ['integer', (int) $a_use_placeholders],
487  'tpl_ctx_id' => ['text', $a_tpl_context_id],
488  'tpl_ctx_params' => ['blob', json_encode($a_tpl_context_params, JSON_THROW_ON_ERROR)],
489  ],
490  [
491  'mail_id' => ['integer', $a_draft_id],
492  ]
493  );
494 
495  return $a_draft_id;
496  }
497 
498  private function sendInternalMail(
499  int $folderId,
500  int $senderUsrId,
501  array $attachments,
502  string $to,
503  string $cc,
504  string $bcc,
505  string $status,
506  string $subject,
507  string $message,
508  int $usrId = 0,
509  bool $usePlaceholders = false,
510  ?string $templateContextId = null,
511  array $templateContextParameters = []
512  ): int {
513  $usrId = $usrId ?: $this->user_id;
514 
515  if ($usePlaceholders) {
516  $message = $this->replacePlaceholders($message, $usrId);
517  }
518  $message = str_ireplace(["<br />", "<br>", "<br/>"], "\n", $message);
519 
520  $nextId = $this->db->nextId($this->table_mail);
521  $this->db->insert($this->table_mail, [
522  'mail_id' => ['integer', $nextId],
523  'user_id' => ['integer', $usrId],
524  'folder_id' => ['integer', $folderId],
525  'sender_id' => ['integer', $senderUsrId],
526  'attachments' => ['clob', serialize($attachments)],
527  'send_time' => ['timestamp', date('Y-m-d H:i:s')],
528  'rcp_to' => ['clob', $to],
529  'rcp_cc' => ['clob', $cc],
530  'rcp_bcc' => ['clob', $bcc],
531  'm_status' => ['text', $status],
532  'm_subject' => ['text', $subject],
533  'm_message' => ['clob', $message],
534  'tpl_ctx_id' => ['text', $templateContextId],
535  'tpl_ctx_params' => ['blob', json_encode($templateContextParameters, JSON_THROW_ON_ERROR)],
536  ]);
537 
538  $sender_equals_reveiver = $usrId === $this->mailbox->getUsrId();
539  $is_sent_folder_of_sender = false;
540  if ($sender_equals_reveiver) {
541  $current_folder_id = $this->getSubjectSentFolderId();
542  $is_sent_folder_of_sender = $folderId === $current_folder_id;
543  }
544 
545  $raise_event = !$sender_equals_reveiver || !$is_sent_folder_of_sender;
546 
547  if ($raise_event) {
548  $this->event_handler->raise('components/ILIAS/Mail', 'sentInternalMail', [
549  'id' => $nextId,
550  'subject' => $subject,
551  'body' => $message,
552  'from_usr_id' => $senderUsrId,
553  'to_usr_id' => $usrId,
554  'rcp_to' => $to,
555  'rcp_cc' => $cc,
556  'rcp_bcc' => $bcc,
557  ]);
558  }
559 
560  return $nextId;
561  }
562 
563  private function replacePlaceholders(
564  string $message,
565  int $usrId = 0
566  ): string {
567  try {
568  if ($this->context_id) {
570  } else {
572  }
573 
574  $user = $usrId > 0 ? $this->getUserInstanceById($usrId) : null;
575  $message = $this->placeholder_resolver->resolve(
576  $context,
577  $message,
578  $user,
579  $this->context_parameters
580  );
581  } catch (Exception $e) {
582  $this->logger->error(sprintf(
583  '%s has been called with invalid context: %s / %s',
584  __METHOD__,
585  $e->getMessage(),
586  $e->getTraceAsString()
587  ));
588  }
589 
590  return $message;
591  }
592 
593  private function replacePlaceholdersEmpty(string $message): string
594  {
595  return $this->placeholder_to_empty_resolver->resolve($message);
596  }
597 
598  private function distributeMail(MailDeliveryData $mail_data): bool
599  {
600  $this->auto_responder_service->emptyAutoresponderData();
601  $to_usr_ids = $this->getUserIds([$mail_data->getTo()]);
602  $this->logger->debug(sprintf(
603  "Parsed TO user ids from given recipients for serial letter notification: %s",
604  implode(', ', $to_usr_ids)
605  ));
606 
607  $other_usr_ids = $this->getUserIds([$mail_data->getCc(), $mail_data->getBcc()]);
608  $cc_bcc_recipients = array_map(
609  $this->createRecipient(...),
610  $other_usr_ids
611  );
612  $this->logger->debug(sprintf(
613  "Parsed CC/BCC user ids from given recipients for serial letter notification: %s",
614  implode(', ', $other_usr_ids)
615  ));
616 
617  if ($mail_data->isUsePlaceholder()) {
618  $this->sendMailWithReplacedPlaceholder($mail_data, $to_usr_ids);
619  $this->sendMailWithReplacedEmptyPlaceholder($mail_data, $cc_bcc_recipients);
620  } else {
621  $this->sendMailWithoutReplacedPlaceholder($mail_data, $to_usr_ids, $cc_bcc_recipients);
622  }
623 
624  $this->auto_responder_service->disableAutoresponder();
625  $this->auto_responder_service->handleAutoresponderMails($this->user_id);
626 
627  return true;
628  }
629 
631  MailDeliveryData $mail_data,
632  array $to_usr_ids
633  ): void {
634  foreach ($to_usr_ids as $user_id) {
635  $recipient = $this->createRecipient($user_id);
636 
637  $this->sendChanneledMails(
638  $mail_data,
639  [$recipient],
640  $this->replacePlaceholders($mail_data->getMessage(), $user_id),
641  );
642  }
643  }
644 
646  MailDeliveryData $mail_data,
647  array $recipients,
648  ): void {
649  $this->sendChanneledMails(
650  $mail_data,
651  $recipients,
652  $this->replacePlaceholdersEmpty($mail_data->getMessage()),
653  );
654  }
655 
657  MailDeliveryData $mail_data,
658  array $to_usr_ids,
659  array $cc_bcc_recipients
660  ): void {
661  $to_recipients = array_map(
662  $this->createRecipient(...),
663  $to_usr_ids
664  );
665 
666  $this->sendChanneledMails(
667  $mail_data,
668  array_merge($to_recipients, $cc_bcc_recipients),
669  $mail_data->getMessage()
670  );
671  }
672 
677  private function sendChanneledMails(
678  MailDeliveryData $mail_data,
679  array $recipients,
680  string $message
681  ): void {
682  $usrIdToExternalEmailAddressesMap = [];
683 
684  foreach ($recipients as $recipient) {
685  if (!$recipient->isUser()) {
686  $this->logger->critical(sprintf(
687  "Skipped recipient with id %s (User not found)",
688  $recipient->getUserId()
689  ));
690  continue;
691  }
692 
693  $can_read_internal = $recipient->evaluateInternalMailReadability();
694  if ($this->isSystemMail() && !$can_read_internal->isOk()) {
695  $this->logger->debug(sprintf(
696  'Skipped recipient with id %s and reason: %s',
697  $recipient->getUserId(),
698  is_string($can_read_internal->error()) ? $can_read_internal->error() : $can_read_internal->error()->getMessage()
699  ));
700  continue;
701  }
702 
703  if ($recipient->isUserActive()) {
704  if (!$can_read_internal->isOk() || $recipient->userWantsToReceiveExternalMails()) {
705  $emailAddresses = $recipient->getExternalMailAddress();
706  $usrIdToExternalEmailAddressesMap[$recipient->getUserId()] = $emailAddresses;
707 
708  if ($recipient->onlyToExternalMailAddress()) {
709  $this->logger->debug(sprintf(
710  "Recipient with id %s will only receive external emails sent to: %s",
711  $recipient->getUserId(),
712  implode(', ', $emailAddresses)
713  ));
714  continue;
715  }
716 
717  $this->logger->debug(sprintf(
718  "Recipient with id %s will additionally receive external emails " .
719  "(because the user wants to receive it externally, or the user cannot access " .
720  "the internal mail system) sent to: %s",
721  $recipient->getUserId(),
722  implode(', ', $emailAddresses)
723  ));
724  } else {
725  $this->logger->debug(sprintf(
726  "Recipient with id %s is does not want to receive external emails",
727  $recipient->getUserId()
728  ));
729  }
730  } else {
731  $this->logger->debug(sprintf(
732  "Recipient with id %s is inactive and will not receive external emails",
733  $recipient->getUserId()
734  ));
735  }
736 
737  $mbox = clone $this->mailbox;
738  $mbox->setUsrId($recipient->getUserId());
739  $recipientInboxId = $mbox->getInboxFolder();
740 
741  $internalMailId = $this->sendInternalMail(
742  $recipientInboxId,
743  $this->user_id,
744  $mail_data->getAttachments(),
745  $mail_data->getTo(),
746  $mail_data->getCc(),
747  '',
748  'unread',
749  $mail_data->getSubject(),
750  $message,
751  $recipient->getUserId()
752  );
753 
754  $this->auto_responder_service->enqueueAutoresponderIfEnabled(
755  $recipient->getUserId(),
756  $recipient->getMailOptions(),
757  $this->getMailOptionsByUserId($this->user_id),
758  );
759 
760  if ($mail_data->getAttachments() !== []) {
761  $this->mail_file_data->assignAttachmentsToDirectory($internalMailId, $mail_data->getInternalMailId());
762  }
763  }
764 
765  $this->delegateExternalEmails(
766  $mail_data->getSubject(),
767  $mail_data->getAttachments(),
768  $message,
769  $usrIdToExternalEmailAddressesMap
770  );
771  }
772 
777  private function delegateExternalEmails(
778  string $subject,
779  array $attachments,
780  string $message,
781  array $usrIdToExternalEmailAddressesMap
782  ): void {
783  if (1 === count($usrIdToExternalEmailAddressesMap)) {
784  $usrIdToExternalEmailAddressesMap = array_values($usrIdToExternalEmailAddressesMap);
785  $firstAddresses = current($usrIdToExternalEmailAddressesMap);
786 
787  $this->sendMimeMail(
788  implode(',', $firstAddresses),
789  '',
790  '',
791  $subject,
792  $message,
793  $attachments
794  );
795  } elseif (count($usrIdToExternalEmailAddressesMap) > 1) {
796  $flattenEmailAddresses = iterator_to_array(new RecursiveIteratorIterator(new RecursiveArrayIterator(
797  $usrIdToExternalEmailAddressesMap
798  )), false);
799 
800  $flattenEmailAddresses = array_unique($flattenEmailAddresses);
801 
802  // https://mantis.ilias.de/view.php?id=23981 and https://www.ietf.org/rfc/rfc2822.txt
803  $remainingAddresses = '';
804  foreach ($flattenEmailAddresses as $emailAddress) {
805  $sep = '';
806  if ($remainingAddresses !== '') {
807  $sep = ',';
808  }
809 
810  $recipientsLineLength = ilStr::strLen($remainingAddresses) +
811  ilStr::strLen($sep . $emailAddress);
812  if ($recipientsLineLength >= $this->max_recipient_character_length) {
813  $this->sendMimeMail(
814  '',
815  '',
816  $remainingAddresses,
817  $subject,
818  $message,
819  $attachments
820  );
821 
822  $remainingAddresses = '';
823  $sep = '';
824  }
825 
826  $remainingAddresses .= ($sep . $emailAddress);
827  }
828 
829  if ('' !== $remainingAddresses) {
830  $this->sendMimeMail(
831  '',
832  '',
833  $remainingAddresses,
834  $subject,
835  $message,
836  $attachments
837  );
838  }
839  }
840  }
841 
846  private function getUserIds(array $recipients): array
847  {
848  $parsed_usr_ids = [];
849 
850  $joined_recipients = implode(',', array_filter(array_map('trim', $recipients)));
851 
852  $addresses = $this->parseAddresses($joined_recipients);
853  foreach ($addresses as $address) {
854  $address_type = $this->mail_address_type_factory->getByPrefix($address);
855  $parsed_usr_ids[] = $address_type->resolve();
856  }
857 
858  return array_unique(array_merge(...$parsed_usr_ids));
859  }
860 
864  private function checkMail(string $to, string $cc, string $bcc, string $subject): array
865  {
866  $errors = [];
867 
868  $checks = [
869  $subject => 'mail_add_subject',
870  $to => 'mail_add_recipient',
871  ];
872  foreach ($checks as $string => $error) {
873  if ($string === '') {
874  $errors[] = new ilMailError($error);
875  }
876  }
877 
878  if (ilStr::strLen($subject) > 255) {
879  // https://mantis.ilias.de/view.php?id=37881
880  $errors[] = new ilMailError('mail_subject_too_long');
881  }
882 
883  return $errors;
884  }
885 
890  private function checkRecipients(string $recipients): array
891  {
892  $errors = [];
893 
894  try {
895  $addresses = $this->parseAddresses($recipients);
896  foreach ($addresses as $address) {
897  $address_type = $this->mail_address_type_factory->getByPrefix($address);
898  if (!$address_type->validate($this->user_id)) {
899  $errors[] = $address_type->getErrors();
900  }
901  }
902  } catch (Exception $e) {
903  $colonPosition = strpos($e->getMessage(), ':');
904  throw new ilMailException(
905  ($colonPosition === false) ? $e->getMessage() : substr($e->getMessage(), $colonPosition + 2),
906  $e->getCode(),
907  $e
908  );
909  }
910 
911  return array_merge(...$errors);
912  }
913 
917  public function persistToStage(
918  int $a_user_id,
919  array $a_attachments,
920  string $a_rcp_to,
921  string $a_rcp_cc,
922  string $a_rcp_bcc,
923  string $a_m_subject,
924  string $a_m_message,
925  bool $a_use_placeholders = false,
926  ?string $a_tpl_context_id = null,
927  ?array $a_tpl_ctx_params = []
928  ): bool {
929  $this->db->replace(
930  $this->table_mail_saved,
931  [
932  'user_id' => ['integer', $this->user_id],
933  ],
934  [
935  'attachments' => ['clob', serialize($a_attachments)],
936  'rcp_to' => ['clob', $a_rcp_to],
937  'rcp_cc' => ['clob', $a_rcp_cc],
938  'rcp_bcc' => ['clob', $a_rcp_bcc],
939  'm_subject' => ['text', $a_m_subject],
940  'm_message' => ['clob', $a_m_message],
941  'use_placeholders' => ['integer', (int) $a_use_placeholders],
942  'tpl_ctx_id' => ['text', $a_tpl_context_id],
943  'tpl_ctx_params' => ['blob', json_encode((array) $a_tpl_ctx_params, JSON_THROW_ON_ERROR)],
944  ]
945  );
946 
947  $this->retrieveFromStage();
948 
949  return true;
950  }
951 
952  public function retrieveFromStage(): array
953  {
954  $res = $this->db->queryF(
955  "SELECT * FROM $this->table_mail_saved WHERE user_id = %s",
956  ['integer'],
957  [$this->user_id]
958  );
959 
960  $this->mail_data = $this->fetchMailData($this->db->fetchAssoc($res));
961  if (!is_array($this->mail_data)) {
962  $this->persistToStage($this->user_id, [], '', '', '', '', '', false);
963  }
964 
965  return $this->mail_data;
966  }
967 
973  public function enqueue(
974  string $a_rcp_to,
975  string $a_rcp_cc,
976  string $a_rcp_bcc,
977  string $a_m_subject,
978  string $a_m_message,
979  array $a_attachment,
980  bool $a_use_placeholders = false
981  ): array {
982  global $DIC;
983 
984  $this->logger->info(
985  "New mail system task:" .
986  " To: " . $a_rcp_to .
987  " | CC: " . $a_rcp_cc .
988  " | BCC: " . $a_rcp_bcc .
989  " | Subject: " . $a_m_subject .
990  " | Attachments: " . print_r($a_attachment, true)
991  );
992 
993  if ($a_attachment && !$this->mail_file_data->checkFilesExist($a_attachment)) {
994  return [new ilMailError('mail_attachment_file_not_exist', [$a_attachment])];
995  }
996 
997  $errors = $this->checkMail($a_rcp_to, $a_rcp_cc, $a_rcp_bcc, $a_m_subject);
998  if ($errors !== []) {
999  return $errors;
1000  }
1001 
1002  $errors = $this->validateRecipients($a_rcp_to, $a_rcp_cc, $a_rcp_bcc);
1003  if ($errors !== []) {
1004  return $errors;
1005  }
1006 
1007  $rcp_to = $a_rcp_to;
1008  $rcp_cc = $a_rcp_cc;
1009  $rcp_bcc = $a_rcp_bcc;
1010 
1011  $numberOfExternalAddresses = $this->getCountRecipients($rcp_to, $rcp_cc, $rcp_bcc);
1012  if (
1013  $numberOfExternalAddresses > 0 &&
1014  !$this->isSystemMail() &&
1015  !$DIC->rbac()->system()->checkAccessOfUser($this->user_id, 'smtp_mail', $this->mail_obj_ref_id)
1016  ) {
1017  return [new ilMailError('mail_no_permissions_write_smtp')];
1018  }
1019 
1020  if ($this->appendInstallationSignature()) {
1021  $a_m_message .= self::_getInstallationSignature();
1022  }
1023 
1025  $mail_data = new MailDeliveryData(
1026  $rcp_to,
1027  $rcp_cc,
1028  $rcp_bcc,
1029  $a_m_subject,
1030  $a_m_message,
1031  $a_attachment,
1032  $a_use_placeholders
1033  );
1034  return $this->sendMail($mail_data);
1035  }
1036 
1037  $taskFactory = $DIC->backgroundTasks()->taskFactory();
1038  $taskManager = $DIC->backgroundTasks()->taskManager();
1039 
1040  $bucket = new BasicBucket();
1041  $bucket->setUserId($this->user_id);
1042 
1043  $task = $taskFactory->createTask(ilMailDeliveryJob::class, [
1044  $this->user_id,
1045  $rcp_to,
1046  $rcp_cc,
1047  $rcp_bcc,
1048  $a_m_subject,
1049  $a_m_message,
1050  serialize($a_attachment),
1051  $a_use_placeholders,
1052  $this->getSaveInSentbox(),
1053  (string) $this->context_id,
1054  serialize(array_merge(
1055  $this->context_parameters,
1056  [
1057  'auto_responder' => $this->auto_responder_service->isAutoresponderEnabled()
1058  ]
1059  ))
1060  ]);
1061  $interaction = $taskFactory->createTask(ilMailDeliveryJobUserInteraction::class, [
1062  $task,
1063  $this->user_id,
1064  ]);
1065 
1066  $bucket->setTask($interaction);
1067  $bucket->setTitle($this->lng->txt('mail_bg_task_title'));
1068  $bucket->setDescription(sprintf($this->lng->txt('mail_bg_task_desc'), $a_m_subject));
1069 
1070  $this->logger->info('Delegated delivery to background task');
1071  $taskManager->run($bucket);
1072 
1073  return [];
1074  }
1075 
1084  public function sendMail(
1085  MailDeliveryData $mail_data
1086  ): array {
1087  $internalMessageId = $this->saveInSentbox(
1088  $mail_data->getAttachments(),
1089  $mail_data->getTo(),
1090  $mail_data->getCc(),
1091  $mail_data->getBcc(),
1092  $mail_data->getSubject(),
1093  $mail_data->getMessage()
1094  );
1095  $mail_data = $mail_data->withInternalMailId($internalMessageId);
1096 
1097  if ($mail_data->getAttachments() !== []) {
1098  $this->mail_file_data->assignAttachmentsToDirectory($internalMessageId, $internalMessageId);
1099  $this->mail_file_data->saveFiles($internalMessageId, $mail_data->getAttachments());
1100  }
1101 
1102  $numberOfExternalAddresses = $this->getCountRecipients($mail_data->getTo(), $mail_data->getCc(), $mail_data->getBcc());
1103 
1104  if ($numberOfExternalAddresses > 0) {
1105  $externalMailRecipientsTo = $this->getEmailRecipients($mail_data->getTo());
1106  $externalMailRecipientsCc = $this->getEmailRecipients($mail_data->getCc());
1107  $externalMailRecipientsBcc = $this->getEmailRecipients($mail_data->getBcc());
1108 
1109  $this->logger->debug(
1110  "Parsed external email addresses from given recipients /" .
1111  " To: " . $externalMailRecipientsTo .
1112  " | CC: " . $externalMailRecipientsCc .
1113  " | BCC: " . $externalMailRecipientsBcc .
1114  " | Subject: " . $mail_data->getSubject()
1115  );
1116 
1117  $this->sendMimeMail(
1118  $externalMailRecipientsTo,
1119  $externalMailRecipientsCc,
1120  $externalMailRecipientsBcc,
1121  $mail_data->getSubject(),
1122  $mail_data->isUsePlaceholder() ?
1123  $this->replacePlaceholders($mail_data->getMessage(), 0) :
1124  $mail_data->getMessage(),
1125  $mail_data->getAttachments()
1126  );
1127  } else {
1128  $this->logger->debug('No external email addresses given in recipient string');
1129  }
1130 
1131  $errors = [];
1132 
1133  if (!$this->distributeMail($mail_data)) {
1134  $errors['mail_send_error'] = new ilMailError('mail_send_error');
1135  }
1136 
1137  if (!$this->getSaveInSentbox()) {
1138  $this->deleteMails([$internalMessageId]);
1139  }
1140 
1141  if ($this->isSystemMail()) {
1142  $random = new Random\Randomizer();
1143  if ($random->getInt(0, 50) === 2) {
1145  $this->logger,
1146  $this->mail_file_data
1147  ))->run();
1148  }
1149  }
1150 
1151  return array_values($errors);
1152  }
1153 
1157  public function validateRecipients(string $to, string $cc, string $bcc): array
1158  {
1159  try {
1160  $errors = [];
1161  $errors = array_merge($errors, $this->checkRecipients($to));
1162  $errors = array_merge($errors, $this->checkRecipients($cc));
1163  $errors = array_merge($errors, $this->checkRecipients($bcc));
1164 
1165  if ($errors !== []) {
1166  return array_merge([new ilMailError('mail_following_rcp_not_valid')], $errors);
1167  }
1168  } catch (ilMailException $e) {
1169  return [new ilMailError('mail_generic_rcp_error', [$e->getMessage()])];
1170  }
1171 
1172  return [];
1173  }
1174 
1175  private function getSubjectSentFolderId(): int
1176  {
1177  $send_folder_id = 0;
1178  if (!$this->isSystemMail()) {
1179  $send_folder_id = $this->mailbox->getSentFolder();
1180  }
1181 
1182  return $send_folder_id;
1183  }
1184 
1188  private function saveInSentbox(
1189  array $attachment,
1190  string $to,
1191  string $cc,
1192  string $bcc,
1193  string $subject,
1194  string $message
1195  ): int {
1196  return $this->sendInternalMail(
1197  $this->getSubjectSentFolderId(),
1198  $this->user_id,
1199  $attachment,
1200  $to,
1201  $cc,
1202  $bcc,
1203  'read',
1204  $subject,
1205  $message,
1206  $this->user_id
1207  );
1208  }
1209 
1213  private function sendMimeMail(
1214  string $to,
1215  string $cc,
1216  string $bcc,
1217  string $subject,
1218  string $message,
1219  array $attachments
1220  ): void {
1221  $mailer = new ilMimeMail();
1222  $mailer->From($this->sender_factory->getSenderByUsrId($this->user_id));
1223  $mailer->To($to);
1224  $mailer->Subject(
1225  $subject,
1226  true,
1227  (string) ($this->context_parameters[self::PROP_CONTEXT_SUBJECT_PREFIX] ?? '')
1228  );
1229 
1230  if (!$this->isSystemMail()) {
1231  $message .= $this->signature_service->user($this->user_id);
1232  }
1233  $mailer->Body($message);
1234 
1235  if ($cc !== '') {
1236  $mailer->Cc($cc);
1237  }
1238 
1239  if ($bcc !== '') {
1240  $mailer->Bcc($bcc);
1241  }
1242 
1243 
1244  foreach ($attachments as $attachment) {
1245  $mailer->Attach(
1246  $this->mail_file_data->getAbsoluteAttachmentPoolPathByFilename($attachment),
1247  '',
1248  'inline',
1249  $attachment
1250  );
1251  }
1252 
1253  $mailer->Send();
1254  }
1255 
1259  public function saveAttachments(array $attachments): void
1260  {
1261  $this->db->update(
1262  $this->table_mail_saved,
1263  [
1264  'attachments' => ['clob', serialize($attachments)],
1265  ],
1266  [
1267  'user_id' => ['integer', $this->user_id],
1268  ]
1269  );
1270  }
1271 
1276  private function parseAddresses(string $addresses): array
1277  {
1278  if ($addresses !== '') {
1279  $this->logger->debug(sprintf(
1280  "Started parsing of recipient string: %s",
1281  $addresses
1282  ));
1283  }
1284 
1285  $parser = $this->mail_address_parser_factory->getParser($addresses);
1286  $parsedAddresses = $parser->parse();
1287 
1288  if ($addresses !== '') {
1289  $this->logger->debug(sprintf(
1290  "Parsed addresses: %s",
1291  implode(',', array_map(static function (ilMailAddress $address): string {
1292  return (string) $address;
1293  }, $parsedAddresses))
1294  ));
1295  }
1296 
1297  return $parsedAddresses;
1298  }
1299 
1300  private function getCountRecipient(string $recipients, bool $onlyExternalAddresses = true): int
1301  {
1302  $addresses = new ilMailAddressListImpl($this->parseAddresses($recipients));
1303  if ($onlyExternalAddresses) {
1304  $addresses = new ilMailOnlyExternalAddressList(
1305  $addresses,
1306  self::ILIAS_HOST,
1307  $this->usr_id_by_login_callable
1308  );
1309  }
1310 
1311  return count($addresses->value());
1312  }
1313 
1314  private function getCountRecipients(
1315  string $toRecipients,
1316  string $ccRecipients,
1317  string $bccRecipients,
1318  bool $onlyExternalAddresses = true
1319  ): int {
1320  return (
1321  $this->getCountRecipient($toRecipients, $onlyExternalAddresses) +
1322  $this->getCountRecipient($ccRecipients, $onlyExternalAddresses) +
1323  $this->getCountRecipient($bccRecipients, $onlyExternalAddresses)
1324  );
1325  }
1326 
1327  private function getEmailRecipients(string $recipients): string
1328  {
1329  $addresses = new ilMailOnlyExternalAddressList(
1330  new ilMailAddressListImpl($this->parseAddresses($recipients)),
1331  self::ILIAS_HOST,
1332  $this->usr_id_by_login_callable
1333  );
1334 
1335  $emailRecipients = array_map(static function (ilMailAddress $address): string {
1336  return (string) $address;
1337  }, $addresses->value());
1338 
1339  return implode(',', $emailRecipients);
1340  }
1341 
1342  public static function _getAutoGeneratedMessageString(?ilLanguage $lang = null): string
1343  {
1344  global $DIC;
1345 
1346  if (!($lang instanceof ilLanguage)) {
1348  }
1349 
1350  $lang->loadLanguageModule('mail');
1351 
1352  return sprintf(
1353  $lang->txt('mail_auto_generated_info'),
1354  $DIC->settings()->get('inst_name', 'ILIAS ' . ((int) ILIAS_VERSION_NUMERIC)),
1356  ) . "\n\n";
1357  }
1358 
1359  public static function _getIliasMailerName(): string
1360  {
1361  global $DIC;
1362  $senderFactory = $DIC->mail()->mime()->senderFactory();
1363 
1364  return $senderFactory->system()->getFromName();
1365  }
1366 
1370  public function appendInstallationSignature(?bool $a_flag = null)
1371  {
1372  if (null === $a_flag) {
1374  }
1375 
1376  $this->append_installation_signature = $a_flag;
1377  return $this;
1378  }
1379 
1380  public static function _getInstallationSignature(): string
1381  {
1382  global $DIC;
1383  return $DIC->mail()->signature()->installation();
1384  }
1385 
1386  public static function getSalutation(int $a_usr_id, ?ilLanguage $a_language = null): string
1387  {
1388  global $DIC;
1389 
1390  $lang = ($a_language instanceof ilLanguage) ? $a_language : $DIC->language();
1391  $lang->loadLanguageModule('mail');
1392 
1393  $gender = ilObjUser::_lookupGender($a_usr_id);
1394  $gender = $gender ?: 'n';
1395  $name = ilObjUser::_lookupName($a_usr_id);
1396 
1397  if ($name['firstname'] === '') {
1398  return $lang->txt('mail_salutation_anonymous') . ',';
1399  }
1400 
1401  return
1402  $lang->txt('mail_salutation_' . $gender) . ' ' .
1403  ($name['title'] ? $name['title'] . ' ' : '') .
1404  ($name['firstname'] ? $name['firstname'] . ' ' : '') .
1405  $name['lastname'] . ',';
1406  }
1407 
1408  private function getUserInstanceById(int $usrId): ?ilObjUser
1409  {
1410  if (!array_key_exists($usrId, $this->user_instances_by_id_map)) {
1411  try {
1412  $user = new ilObjUser($usrId);
1413  } catch (Exception) {
1414  $user = null;
1415  }
1416 
1417  $this->user_instances_by_id_map[$usrId] = $user;
1418  }
1419 
1420  return $this->user_instances_by_id_map[$usrId];
1421  }
1422 
1426  public function setUserInstanceById(array $userInstanceByIdMap): void
1427  {
1428  $this->user_instances_by_id_map = $userInstanceByIdMap;
1429  }
1430 
1431  private function getMailOptionsByUserId(int $usrId): ilMailOptions
1432  {
1433  if (!isset($this->mail_options_by_usr_id_map[$usrId])) {
1434  $this->mail_options_by_usr_id_map[$usrId] = new ilMailOptions($usrId);
1435  }
1436 
1437  return $this->mail_options_by_usr_id_map[$usrId];
1438  }
1439 
1443  public function setMailOptionsByUserIdMap(array $mailOptionsByUsrIdMap): void
1444  {
1445  $this->mail_options_by_usr_id_map = $mailOptionsByUsrIdMap;
1446  }
1447 
1448  public function formatLinebreakMessage(string $message): string
1449  {
1450  return $message;
1451  }
1452 
1453  private function createRecipient(int $user_id): Recipient
1454  {
1455  return new Recipient(
1456  $user_id,
1457  $this->getUserInstanceById($user_id),
1458  $this->getMailOptionsByUserId($user_id),
1459  $this->legal_documents
1460  );
1461  }
1462 }
setSaveInSentbox(bool $saveInSentbox)
Class ilMailError.
formatLinebreakMessage(string $message)
$res
Definition: ltiservices.php:66
Global event handler.
sendMailWithReplacedPlaceholder(MailDeliveryData $mail_data, array $to_usr_ids)
getEmailRecipients(string $recipients)
int $max_recipient_character_length
persistToStage(int $a_user_id, array $a_attachments, string $a_rcp_to, string $a_rcp_cc, string $a_rcp_bcc, string $a_m_subject, string $a_m_message, bool $a_use_placeholders=false, ?string $a_tpl_context_id=null, ?array $a_tpl_ctx_params=[])
countMailsOfFolder(int $folderId)
$context
Definition: webdav.php:31
const ANONYMOUS_USER_ID
Definition: constants.php:27
static getLogger(string $a_component_id)
Get component logger.
const ILIAS_HOST
markUnread(array $mailIds)
array $mail_data
This class handles all operations on files (attachments) in directory ilias_data/mail.
checkMail(string $to, string $cc, string $bcc, string $subject)
existsRecipient(string $newRecipient, string $existingRecipients)
getCountRecipients(string $toRecipients, string $ccRecipients, string $bccRecipients, bool $onlyExternalAddresses=true)
const CONTEXT_CRON
MailSignatureService $signature_service
getMailsOfFolder(int $a_folder_id, array $filter=[])
const PROP_CONTEXT_SUBJECT_PREFIX
appendInstallationSignature(?bool $a_flag=null)
sendMimeMail(string $to, string $cc, string $bcc, string $subject, string $message, array $attachments)
enqueue(string $a_rcp_to, string $a_rcp_cc, string $a_rcp_bcc, string $a_m_subject, string $a_m_message, array $a_attachment, bool $a_use_placeholders=false)
Should be used to enqueue a &#39;mail&#39;.
getUserInstanceById(int $usrId)
static _lookupName(int $a_user_id)
lookup user name
string $context_id
static _lookupId($a_user_str)
static _getIliasMailerName()
Class ilMailOnlyExternalAddressList.
deleteMailsOfFolder(int $folderId)
static _lookupPref(int $a_usr_id, string $a_keyword)
array $mail_options_by_usr_id_map
saveInSentbox(array $attachment, string $to, string $cc, string $bcc, string $subject, string $message)
getPreviousMail(int $mailId)
sendChanneledMails(MailDeliveryData $mail_data, array $recipients, string $message)
static _lookupGender(int $a_user_id)
int $user_id
Class ilMailDiffAddressList.
getCountRecipient(string $recipients, bool $onlyExternalAddresses=true)
bool $append_installation_signature
readonly Conductor $legal_documents
static _getAutoGeneratedMessageString(?ilLanguage $lang=null)
retrieveFromStage()
withContextParameters(array $parameters)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
array $user_instances_by_id_map
saveAttachments(array $attachments)
static strLen(string $a_string)
Definition: class.ilStr.php:63
Class ilMailRfc822AddressParserFactory.
array $context_parameters
delegateExternalEmails(string $subject, array $attachments, string $message, array $usrIdToExternalEmailAddressesMap)
const ILIAS_VERSION_NUMERIC
replacePlaceholdersEmpty(string $message)
fetchMailData(?array $row)
withContextId(string $contextId)
isSystemMail()
Mail Box class Base class for creating and handling mail boxes.
static getSalutation(int $a_usr_id, ?ilLanguage $a_language=null)
checkRecipients(string $recipients)
bool $save_in_sentbox
distributeMail(MailDeliveryData $mail_data)
global $DIC
Definition: shib_login.php:22
replacePlaceholders(string $message, int $usrId=0)
getMailOptionsByUserId(int $usrId)
string $table_mail_saved
autoresponder()
bool $append_user_signature
getSaveInSentbox()
setUserInstanceById(array $userInstanceByIdMap)
sendMailWithReplacedEmptyPlaceholder(MailDeliveryData $mail_data, array $recipients,)
static _getLanguage(string $a_lang_key='')
Get language object.
Class ilMailTemplatePlaceholderResolver.
getMailObjectReferenceId()
__construct(private int $a_user_id, private ?ilMailAddressTypeFactory $mail_address_type_factory=null, private ilMailRfc822AddressParserFactory $mail_address_parser_factory=new ilMailRfc822AddressParserFactory(), private ?ilAppEventHandler $event_handler=null, private ?ilLogger $logger=null, private ?ilDBInterface $db=null, private ?ilLanguage $lng=null, private ?ilFileDataMail $mail_file_data=null, protected ?ilMailOptions $mail_options=null, private ?ilMailbox $mailbox=null, private ?ilMailMimeSenderFactory $sender_factory=null, private ?Closure $usr_id_by_login_callable=null, private ?AutoresponderService $auto_responder_service=null, private ?int $mail_admin_node_ref_id=null, private ?int $mail_obj_ref_id=null, private ?ilObjUser $actor=null, private ?ilMailTemplatePlaceholderResolver $placeholder_resolver=null, private ?ilMailTemplatePlaceholderToEmptyResolver $placeholder_to_empty_resolver=null, ?Conductor $legal_documents=null, ?MailSignatureService $signature_service=null,)
validateRecipients(string $to, string $cc, string $bcc)
$lang
Definition: xapiexit.php:25
getNewDraftId(int $folderId)
sendMail(MailDeliveryData $mail_data)
This method is used to finally send internal messages and external emails To use the mail system as a...
getMail(int $mailId)
createRecipient(int $user_id)
static _getHttpPath()
sendMailWithoutReplacedPlaceholder(MailDeliveryData $mail_data, array $to_usr_ids, array $cc_bcc_recipients)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
formatNamesForOutput(string $recipients)
global $lng
Definition: privfeed.php:31
deleteMails(array $mailIds)
string $table_mail
getNextMail(int $mailId)
setMailOptionsByUserIdMap(array $mailOptionsByUsrIdMap)
withInternalMailId(int $internal_mail_id)
sendInternalMail(int $folderId, int $senderUsrId, array $attachments, string $to, string $cc, string $bcc, string $status, string $subject, string $message, int $usrId=0, bool $usePlaceholders=false, ?string $templateContextId=null, array $templateContextParameters=[])
$message
Definition: xapiexit.php:31
getUserIds(array $recipients)
static getType()
Get context type.
markRead(array $mailIds)
getSubjectSentFolderId()
parseAddresses(string $addresses)
Explode recipient string, allowed separators are &#39;,&#39; &#39;;&#39; &#39; &#39;.
Class ilMailAddressTypeFactory.
updateDraft(int $a_folder_id, array $a_attachments, string $a_rcp_to, string $a_rcp_cc, string $a_rcp_bcc, string $a_m_subject, string $a_m_message, int $a_draft_id=0, bool $a_use_placeholders=false, ?string $a_tpl_context_id=null, array $a_tpl_context_params=[])
moveMailsToFolder(array $mailIds, int $folderId)
readMailObjectReferenceId()
Class ilMailAddress.
static _getInstallationSignature()
Class ilMailAddressListImpl.