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