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