Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
message.php
1<?php
2
3namespace Bitrix\Mail\Helper;
4
11use Bitrix\Main;
14use Bitrix\Mail\Helper\MessageAccess as AccessHelper;
16
18{
19 // entity types with special access rules (group tokens)
20 public const ENTITY_TYPE_IM_CHAT = MessageAccessTable::ENTITY_TYPE_IM_CHAT;
21 public const ENTITY_TYPE_CALENDAR_EVENT = MessageAccessTable::ENTITY_TYPE_CALENDAR_EVENT;
22 private const MAX_FILE_SIZE_MAIL_ATTACHMENT = 20000000;
23
24 public static function getMaxAttachedFilesSize()
25 {
26 // @TODO: Until the 'Main' module update of is released with the reset of the option for the cloud
27 if (IsModuleInstalled('bitrix24'))
28 {
29 return self::MAX_FILE_SIZE_MAIL_ATTACHMENT;
30 }
31 else
32 {
33 return (int)Option::get('main', 'max_file_size');
34 }
35 }
36
37 public static function getMaxAttachedFilesSizeAfterEncoding()
38 {
39 return floor(static::getMaxAttachedFilesSize()/4)*3;
40 }
41
48 public static function getWhitelistTagAttributes()
49 {
50 $validTagAttributes = [
51 'colspan',
52 'border',
53 'bgcolor',
54 'width',
55 'background',
56 'style',
57 'align',
58 'height',
59 'background-color',
60 'border',
61 'ltr',
62 'rtl',
63 'class',
64 ];
65
66 $tableAttributes = array_merge(
67 $validTagAttributes,
68 [
69 'cellpadding',
70 'cellspacing',
71 ]
72 );
73
74 $tdAttributes = array_merge(
75 $validTagAttributes,
76 [
77 'rowspan',
78 ]
79 );
80
81 return [
82 'style' => [],
83 'colgroup' => [],
84 'col' => ['width'],
85 'table' => $tableAttributes,
86 'center' => $validTagAttributes,
87 'div' => $validTagAttributes,
88 'td' =>$tdAttributes,
89 ];
90 }
91
92 private static function prepareField($value)
93 {
94 if (trim($value))
95 {
96 $address = new Main\Mail\Address($value);
97
98 if ($address->validate())
99 {
100 return [
101 'name' => $address->getName(),
102 'email' => $address->getEmail(),
103 'formated' => ($address->getName() ? $address->get() : $address->getEmail()),
104 ];
105 }
106 else
107 {
108 return [
109 'name' => $value,
110 ];
111 }
112 }
113
114 return false;
115 }
116
117 private static function checkMessageIsOutcomeByField($message,$keyField,$value)
118 {
119 if (trim($value))
120 {
121 $isFromField = in_array($keyField, ['__from', '__reply_to']);
122 $address = new Main\Mail\Address($value);
123
124 if ($address->validate())
125 {
126 if ($isFromField && $address->getEmail() == $message['__email'])
127 {
128 return true;
129 }
130 }
131 }
132
133 return false;
134 }
135
143 public static function prepare(&$message)
144 {
145 $message['__email'] = null;
146 foreach (array($message['MAILBOX_EMAIL'], $message['MAILBOX_NAME'], $message['MAILBOX_LOGIN']) as $item)
147 {
148 $address = new Main\Mail\Address($item);
149 if ($address->validate())
150 {
151 $message['__email'] = $address->getEmail();
152 break;
153 }
154 }
155
156 $fieldsMap = array(
157 '__from' => 'FIELD_FROM',
158 '__reply_to' => 'FIELD_REPLY_TO',
159 '__to' => 'FIELD_TO',
160 '__cc' => 'FIELD_CC',
161 '__bcc' => 'FIELD_BCC',
162 '__rcpt' => 'FIELD_RCPT',
163 );
164
165 if ('' != $message['HEADER'])
166 {
167 foreach ($fieldsMap as $field)
168 {
169 if (mb_strlen($message[$field]) == 255)
170 {
171 $parsedHeader = \CMailMessage::parseHeader($message['HEADER'], LANG_CHARSET);
172
173 $message['FIELD_FROM'] = $parsedHeader->getHeader('FROM');
174 $message['FIELD_REPLY_TO'] = $parsedHeader->getHeader('REPLY-TO');
175 $message['FIELD_TO'] = $parsedHeader->getHeader('TO');
176 $message['FIELD_CC'] = $parsedHeader->getHeader('CC');
177 $message['FIELD_BCC'] = join(', ', array_merge(
178 (array) $parsedHeader->getHeader('X-Original-Rcpt-to'),
179 (array) $parsedHeader->getHeader('BCC')
180 ));
181
182 break;
183 }
184 }
185 }
186
187 foreach ($fieldsMap as $fieldKey => $fieldName)
188 {
189 $message[$fieldKey] = [];
190
191 if($fieldName === 'FIELD_FROM')
192 {
193 if(static::checkMessageIsOutcomeByField($message,$fieldKey,$message[$fieldName]))
194 {
195 $message['__is_outcome'] = true;
196 }
197
198 $filed = static::prepareField($message[$fieldName]);
199
200 if($filed !== false)
201 {
202 $message[$fieldKey][] = $filed;
203 }
204
205 continue;
206 }
207
208 foreach (explode(',', $message[$fieldName]) as $item)
209 {
210 if(static::checkMessageIsOutcomeByField($message,$fieldKey,$item))
211 {
212 $message['__is_outcome'] = true;
213 }
214
215 $filed = static::prepareField($item);
216
217 if($filed !== false)
218 {
219 $message[$fieldKey][] = $filed;
220 }
221 }
222 }
223
224 if (empty($message['__reply_to']))
225 {
226 $message['__reply_to'] = $message['__from'];
227 }
228
229 // @TODO: path
230 $message['__href'] = sprintf('/mail/message/%u', $message['ID']);
231
232 $urlManager = Attachment\Storage::getUrlManager();
233
234 if (!empty($message['__files']) && is_array($message['__files']))
235 {
236 $urlParams = array();
237
238 if (isset($_REQUEST['mail_uf_message_token']) && is_string($_REQUEST['mail_uf_message_token']))
239 {
240 $urlParams['mail_uf_message_token'] = $_REQUEST['mail_uf_message_token'];
241 }
242
243 foreach ($message['__files'] as $k => $item)
244 {
245 if ($diskFile = Attachment\Storage::getObjectByAttachment($item, true))
246 {
247 $message['__files'][$k] = array(
248 'id' => sprintf('n%u', $diskFile->getId()),
249 'name' => $item['FILE_NAME'],
250 'url' => $urlManager->getUrlForShowFile($diskFile, $urlParams),
251 'size' => \CFile::formatSize($diskFile->getSize()),
252 'fileId' => $diskFile->getFileId(),
253 'objectId' => $diskFile->getId(),
254 'bytes' => $diskFile->getSize(),
255 );
256
257 if (\Bitrix\Disk\TypeFile::isImage($diskFile))
258 {
259 $message['__files'][$k]['preview'] = $urlManager->getUrlForShowFile(
260 $diskFile,
261 array_merge(
262 array('width' => 80, 'height' => 80, 'exact' => 'Y'),
263 $urlParams
264 )
265 );
266 }
267
268 $inlineParams = array_merge(
269 array('__bxacid' => sprintf('n%u', $diskFile->getId())),
270 $urlParams
271 );
272 $message['BODY_HTML'] = preg_replace(
273 sprintf('/("|\')\s*aid:%u\s*\1/i', $item['ID']),
274 sprintf('\1%s\1', $urlManager->getUrlForShowFile($diskFile, $inlineParams)),
275 $message['BODY_HTML']
276 );
277 }
278 else
279 {
280 $file = \CFile::getFileArray($item['FILE_ID']);
281 if (!empty($file) && is_array($file))
282 {
283 $message['__files'][$k] = array(
284 'id' => $file['ID'],
285 'name' => $item['FILE_NAME'],
286 'url' => $file['SRC'],
287 'size' => \CFile::formatSize($file['FILE_SIZE']),
288 'fileId' => $file['ID'],
289 'bytes' => $file['FILE_SIZE'],
290 );
291
292 if (\CFile::isImage($item['FILE_NAME'], $item['CONTENT_TYPE']))
293 {
294 $preview = \CFile::resizeImageGet(
295 $file, array('width' => 80, 'height' => 80),
296 BX_RESIZE_IMAGE_EXACT, false
297 );
298
299 if (!empty($preview['src']))
300 {
301 $message['__files'][$k]['preview'] = $preview['src'];
302 }
303 }
304
305 $message['BODY_HTML'] = preg_replace(
306 sprintf('/("|\')\s*aid:%u\s*\1/i', $item['ID']),
307 sprintf('\1%s\1', $file['SRC']),
308 $message['BODY_HTML']
309 );
310 }
311 else
312 {
313 unset($message['__files'][$k]);
314 }
315 }
316 }
317 }
318
319 return $message;
320 }
321
322 public static function hasAccess(&$message, $userId = null)
323 {
324 global $USER;
325
326 if (
327 !($userId > 0 || is_object($USER) && $USER->isAuthorized()) ||
328 //If message id = 0 , the message is deleted or not loaded:
329 is_null($message['ID']) || $message['ID'] === 0 || $message['ID'] === '0'
330 )
331 {
332 return false;
333 }
334
335 if (!($userId > 0))
336 {
337 $userId = $USER->getId();
338 }
339
340 $messageAccess = \Bitrix\Mail\MessageAccess::createByMessageId($message['ID'], $userId);
341 $access = $messageAccess->isOwner();
342
343 $message['__access_level'] = $access ? 'full' : false;
344
345 // check access by tokens
346 if (!$access && isset($_REQUEST['mail_uf_message_token']))
347 {
348 $token = $signature = '';
349 if (is_string($_REQUEST['mail_uf_message_token']) && mb_strpos($_REQUEST['mail_uf_message_token'], ':') > 0)
350 {
351 [$token, $signature] = explode(':', $_REQUEST['mail_uf_message_token'], 2);
352 }
353
354 if ($token <> '' && $signature <> '')
355 {
356 $excerpt = MessageAccessTable::getList(array(
357 'select' => array('SECRET', 'MESSAGE_ID', 'ENTITY_TYPE', 'ENTITY_ID'),
358 'filter' => array(
359 '=TOKEN' => $token,
360 '=MAILBOX_ID' => $message['MAILBOX_ID'],
361 ),
362 'limit' => 1,
363 ))->fetch();
364
365 if (!empty($excerpt['SECRET']))
366 {
367 if (self::checkAccessForEntityToken($excerpt['ENTITY_TYPE'], (int)$excerpt['ENTITY_ID'], $userId))
368 {
369 $salt = self::getSaltByEntityType($excerpt['ENTITY_TYPE'], (int)$excerpt['ENTITY_ID'], $userId);
370
371 $signer = new Security\Sign\Signer(new Security\Sign\HmacAlgorithm('md5'));
372
373 if ($signer->validate($excerpt['SECRET'], $signature, $salt))
374 {
375 $access = $message['ID'] == $excerpt['MESSAGE_ID'];
376
377 if (!$access) // check parent access
378 {
379 $access = (bool) MessageClosureTable::getList(array(
380 'select' => array('PARENT_ID'),
381 'filter' => array(
382 '=MESSAGE_ID' => $message['ID'],
383 '=PARENT_ID' => $excerpt['MESSAGE_ID'],
384 ),
385 ))->fetch();
386 }
387 }
388 }
389 }
390 }
391 }
392
393 // check access by direct links
394 if (!$access)
395 {
396 $access = $messageAccess->canViewMessage();
397 }
398
399 if (false === $message['__access_level'])
400 {
401 $message['__access_level'] = $access ? 'read' : false;
402 }
403
404 return $access;
405 }
406
407 public static function prepareSearchContent(&$fields)
408 {
409 // @TODO: filter short words, filter duplicates, str_rot13?
410 return str_rot13(join(
411 ' ',
412 array(
413 $fields['FIELD_FROM'],
414 $fields['FIELD_REPLY_TO'],
415 $fields['FIELD_TO'],
416 $fields['FIELD_CC'],
417 $fields['FIELD_BCC'],
418 $fields['SUBJECT'],
419 self::isolateBase64Files((string)$fields['BODY']),
420 )
421 ));
422 }
423
424 public static function prepareSearchString($string)
425 {
426 return str_rot13($string);
427 }
428
434 public static function getCountersForUserMailboxes($userId, $onlyGeneralCounter = false)
435 {
436 static $countersForUsers;
437
438 if (empty($countersForUsers))
439 {
440 $countersForUsers = [];
441 }
442
443 if (!isset($countersForUsers[$userId]))
444 {
445 $mailboxes = MailboxTable::getUserMailboxes($userId);
446
447 if (empty($mailboxes))
448 {
449 return array();
450 }
451
452 $mailboxIds = array_column($mailboxes, 'ID');
453
454 $totalUnseen = Internals\MailCounterTable::getList([
455 'select' => [
456 new \Bitrix\Main\Entity\ExpressionField(
457 'UNSEEN',
458 'SUM(VALUE)'
459 ),
460 'VALUE',
461 'ENTITY_ID',
462 ],
463 'filter' => [
464 '=ENTITY_TYPE' => 'MAILBOX',
465 '@ENTITY_ID' => $mailboxIds,
466 ],
467 ])->fetchAll();
468
469 $counters = [];
470
471 $totalCounter = 0;
472
473 foreach ($totalUnseen as $index => $item)
474 {
475 $totalCounter += $item['VALUE'];
476
477 $counters[$item['ENTITY_ID']] = [
478 'UNSEEN' => $item['VALUE'],
479 ];
480 }
481
482 $countersForUsers[$userId] = [
483 'mailboxesWithCounters' => $counters,
484 'totalCounter' => $totalCounter,
485 ];
486 }
487
488 if($onlyGeneralCounter)
489 {
490 return $countersForUsers[$userId]['totalCounter'];
491 }
492 else
493 {
494 return $countersForUsers[$userId]['mailboxesWithCounters'];
495 }
496 }
497
498 public static function ensureAttachments(&$message)
499 {
500 if ($message['ATTACHMENTS'] > 0 || !($message['OPTIONS']['attachments'] > 0))
501 {
502 return false;
503 }
504
505 if (Option::get('mail', 'save_attachments', B_MAIL_SAVE_ATTACHMENTS) !== 'Y')
506 {
507 return false;
508 }
509
510 $mailboxHelper = Mailbox::createInstance($message['MAILBOX_ID'], false);
511
512 $attachments = empty($mailboxHelper) ? false : $mailboxHelper->downloadAttachments($message);
513
514 if (false === $attachments)
515 {
516 $logEntry = sprintf(
517 'Helper\Message: Attachments downloading failed (%u:%s:%u)',
518 $message['MAILBOX_ID'],
519 $message['DIR_MD5'],
520 $message['MSG_UID']
521 );
522
523 if (!empty($mailboxHelper) && !$mailboxHelper->getErrors()->isEmpty())
524 {
525 $logEntry .= PHP_EOL . join(PHP_EOL, $mailboxHelper->getErrors()->toArray());
526 }
527
528 addMessage2Log($logEntry, 'mail', 2);
529
530 return false;
531 }
532
533 $originalBody = $message['BODY_HTML'] ?? null;
534 foreach ($attachments as $i => $item)
535 {
536 $attachFields = array(
537 'MESSAGE_ID' => $message['ID'],
538 'FILE_NAME' => $item['FILENAME'],
539 'CONTENT_TYPE' => $item['CONTENT-TYPE'],
540 'FILE_DATA' => $item['BODY'],
541 'CONTENT_ID' => $item['CONTENT-ID'],
542 );
543
544 $attachmentId = \CMailMessage::addAttachment($attachFields);
545
546 if ($attachmentId > 0)
547 {
548 $message['ATTACHMENTS']++;
549
550 if (isset($message['BODY_HTML']) && mb_strlen($message['BODY_HTML']) > 0)
551 {
552 $bodyWithReplaced = self::replaceBodyInlineImgContentId(
553 (string)$message['BODY_HTML'],
554 (string)$item['CONTENT-ID'],
555 $attachmentId
556 );
557 if ($bodyWithReplaced)
558 {
559 $message['BODY_HTML'] = $bodyWithReplaced;
560 }
561 }
562 }
563 }
564
565 if ($message['ATTACHMENTS'] > 0)
566 {
567 if ($originalBody !== $message['BODY_HTML'])
568 {
569 \CMailMessage::update($message['ID'], ['BODY_HTML' => $message['BODY_HTML']], $message['MAILBOX_ID']);
570 }
571
572 return $message['ID'];
573 }
574 }
575
576 public static function parseAddressList($column)
577 {
578 $column = trim($column);
579 //'email@email' => 'email@domain'
580 //'Name <email@domain>, Name2 <email2@domain2>' => 'Name <email@domain'
581 $columns = preg_split("/>,?/", $column);
582 $validColumns = [];
583
584 foreach ($columns as $value)
585 {
586 //'email@email' => 'email@domain'
587 //'Name <email@domain' => 'Name <email@domain>'
588 if(preg_match("/</", $value))
589 {
590 $value.='>';
591 }
592
593 if($value !== '')
594 {
595 $validColumns[] = $value;
596 }
597 }
598
599 return $validColumns;
600 }
601
602 public static function isolateSelector($matches)
603 {
604 $head = $matches['head'];
605 $body = $matches['body'];
606 $prefix = 'mail-message-';
607 $wrapper = '#mail-message-wrapper ';
608 if(substr($head,0,1)==='@') $wrapper ='';
609 $closure = $matches['closure'];
610 $head = preg_replace('%([\.#])([a-z][-_a-z0-9]+)%msi', '$1'.$prefix.'$2', $head);
611 return $wrapper.$head.$body.$closure;
612 }
613
614 public static function isolateStylesInTheTag($matches)
615 {
616 $wrapper = '#mail-message-wrapper ';
617 $openingTag = $matches['openingTag'];
618 $closingTag = $matches['closingTag'];
619 $styles = $matches['styles'];
620 $bodySelectorPattern = '#(.*?)(^|\s)(body)\s*((?:\{)(?:.*?)(?:\}))(.*)#msi';
621 $bodySelector = preg_replace($bodySelectorPattern, '$2'.$wrapper.'$4', $styles);
622 //cut off body selector
623 $styles = preg_replace($bodySelectorPattern, '$1$5', $styles);
624 $styles = preg_replace('#(^|\s)(body)\s*({)#isU', '$1mail-msg-view-body$3', $styles);
625 $styles = preg_replace_callback('%(?:^|\s)(?<head>[@#\.]?[a-z].*?\{)(?<body>.*?)(?<closure>\})%msi', 'static::isolateSelector', $styles);
626 return $openingTag.$bodySelector.$styles.$closingTag;
627 }
628
629 public static function isolateStylesInTheBody($html)
630 {
631 $prefix = 'mail-message-';
632 $html = preg_replace('%((?:^|\s)(?:class|id)(?:^|\s*)(?:=)(?:^|\s*)(\"|\'))((?:.*?)(?:\2))%', '$1'.$prefix.'$3', $html);
633 return $html;
634 }
635
636 public static function isolateMessageStyles($messageHtml)
637 {
638 //isolates the positioning of the element
639 $messageHtml = preg_replace('%((?:^|\s)position(?:^|\s)?:(?:^|\s)?)(absolute|fixed|inherit)%', '$1relative', $messageHtml);
640 //remove media queries
641 $messageHtml = preg_replace('%@media\b[^{]*({((?:[^{}]+|(?1))*)})%msi', '', $messageHtml);
642 //remove loading fonts
643 $messageHtml = preg_replace('%@font-face\b[^{]*({(?>[^{}]++|(?1))*})%msi', '', $messageHtml);
644 $messageHtml = static::isolateStylesInTheBody($messageHtml);
645 $messageHtml = preg_replace_callback('|(?<openingTag><style[^>]*>)(?<styles>.*)(?<closingTag><\/style>)|isU', 'static::isolateStylesInTheTag',$messageHtml);
646 return $messageHtml;
647 }
648
649 public static function sanitizeHtml($html, $isolateStyles = false)
650 {
651 $cleared = preg_replace('/<!--.*?-->/is', '', $html);
652 $cleared = preg_replace('/<script[^>]*>.*?<\/script>/is', '', $cleared);
653 $cleared = preg_replace('/<title[^>]*>.*?<\/title>/is', '', $cleared);
654 $sanitizer = new \CBXSanitizer();
655 $sanitizer->setLevel(\CBXSanitizer::SECURE_LEVEL_LOW);
656 $sanitizer->applyDoubleEncode(false);
657 $sanitizer->addTags(static::getWhitelistTagAttributes());
658 $cleared = $sanitizer->sanitizeHtml($cleared);
659
660 if($isolateStyles)
661 {
662 $cleared = static::isolateMessageStyles($cleared);
663 }
664
665 return $cleared;
666 }
667
668 public static function reSyncBody($mailboxId, $messageIds)
669 {
670 if (empty($messageIds) || !is_array($messageIds))
671 {
672 return false;
673 }
674
675 $messages = \Bitrix\Mail\MailMessageUidTable::getList([
676 'select' => [
677 '*'
678 ],
679 'filter' => [
680 '=MAILBOX_ID' => $mailboxId,
681 '@MESSAGE_ID' => $messageIds,
682 ],
683 ]);
684
685 $notProcessed = array_combine($messageIds, $messageIds);
686
687 $mailboxHelper = Mailbox::createInstance($mailboxId, false);
688
689 if(!empty($mailboxHelper))
690 {
691 $mailbox = $mailboxHelper->getMailbox();
692
693 while ($message = $messages->fetch())
694 {
695 $technicalTitle = $mailboxHelper->downloadMessage($message);
696 if ($technicalTitle)
697 {
698 $charset = $mailbox['CHARSET'] ?: $mailbox['LANG_CHARSET'];
699 [$header, $html, $text, $attachments] = \CMailMessage::parseMessage($technicalTitle, $charset);
700
701 if (\CMailMessage::isLongMessageBody($text))
702 {
703 [$text, $html] = \CMailMessage::prepareLongMessage($text, $html);
704 }
705
706 if (rtrim($text) || $html)
707 {
708 \CMailMessage::update(
709 $message['MESSAGE_ID'],
710 [
711 'BODY' => rtrim($text),
712 'BODY_HTML' => $html,
714 ]
715 );
716 }
717 }
718 self::updateMailEntityOptionsRow($mailboxId, (int)$message['MESSAGE_ID']);
719 unset($notProcessed[$message['MESSAGE_ID']]);
720 }
721 }
722
723 foreach ($notProcessed as $messageId)
724 {
725 self::updateMailEntityOptionsRow($mailboxId, (int)$messageId);
726 }
727
728 return true;
729 }
730
731 public static function getSaltByEntityType(string $entityType, int $entityId, ?int $userId = null): string
732 {
733 switch ($entityType)
734 {
735 case Message::ENTITY_TYPE_IM_CHAT:
736 return sprintf('chat%u', $entityId);
737 case Message::ENTITY_TYPE_CALENDAR_EVENT:
738 return sprintf('event'.'%u', $entityId);
739 default:
740 // per-user tokens for entity types like TASKS_TASK, CRM_ACTIVITY, ...
741 return sprintf('user'.'%u', $userId);
742 }
743 }
744
745 public static function isMailboxOwner(int $mailboxId, int $userId): bool
746 {
747 return (bool)MailboxTable::getUserMailbox($mailboxId, $userId);
748 }
749
750 private static function checkAccessForEntityToken(?string $entityType, int $entityId, int $userId): bool
751 {
752 switch ($entityType)
753 {
754 case Message::ENTITY_TYPE_IM_CHAT:
755 return AccessHelper::checkAccessForChat($entityId, $userId);
756 case Message::ENTITY_TYPE_CALENDAR_EVENT:
757 return AccessHelper::checkAccessForCalendarEvent($entityId, $userId);
758 default:
759 return true; // tasks, crm creates per-user tokens
760 }
761 }
762
768 public static function updateMailEntityOptionsRow($mailboxId, $messageId): void
769 {
770 Internals\MailEntityOptionsTable::update([
771 'MAILBOX_ID' => $mailboxId,
772 'ENTITY_ID' => $messageId,
773 'ENTITY_TYPE' => 'MESSAGE',
774 'PROPERTY_NAME' => 'UNSYNC_BODY',
775 ],
776 [
777 'VALUE' => 'N',
778 ]
779 );
780 }
781
789 public static function isBodyNeedUpdateAfterLoadAttachments(string $body): bool
790 {
791 return preg_match('/<img([^>]+)src\s*=\s*([\'"])?\s*((?:http:\/\/)?cid:.+)\s*\2([^>]*)>/is', $body);
792 }
793
803 public static function replaceBodyInlineImgContentId(string $body, string $contentId, int $attachmentId): string
804 {
805 return (string)preg_replace(
806 sprintf('/<img([^>]+)src\s*=\s*(\'|\")?\s*((?:http:\/\/)?cid:%s)\s*\2([^>]*)>/is', preg_quote($contentId, '/')),
807 sprintf('<img\1src="aid:%u"\4>', $attachmentId),
808 $body
809 );
810 }
811
812 public static function isolateBase64Files(string $text): string
813 {
814 $pattern = '/\[\s*data:(?!text\b)[^;]+;base64,\S+ \]/';
815
816 return (string)preg_replace($pattern, '', $text);
817 }
818
819 public static function isIcalMessage(\Bitrix\Mail\Item\Message $message)
820 {
821 $attachments = MailMessageAttachmentTable::getList([
822 'select' => [
823 'ID',
824 'FILE_ID',
825 'FILE_NAME',
826 'FILE_SIZE',
827 'CONTENT-TYPE' => 'CONTENT_TYPE',
828 ],
829 'filter' => [
830 '=MESSAGE_ID' => $message->getId(),
831 '@CONTENT_TYPE' => ICalMailManager::CONTENT_TYPES
832 ],
833 ])->fetchAll();
834
835 return ICalMailManager::hasICalAttachments($attachments);
836
837 }
838}
static createInstance($id, $throw=true)
Definition mailbox.php:101
static checkAccessForChat(int $chatId, int $userId)
static checkAccessForCalendarEvent(int $calendarEventId, int $userId)
static updateMailEntityOptionsRow($mailboxId, $messageId)
Definition message.php:768
static sanitizeHtml($html, $isolateStyles=false)
Definition message.php:649
static isolateMessageStyles($messageHtml)
Definition message.php:636
static isolateBase64Files(string $text)
Definition message.php:812
static prepareSearchString($string)
Definition message.php:424
static getMaxAttachedFilesSizeAfterEncoding()
Definition message.php:37
static isMailboxOwner(int $mailboxId, int $userId)
Definition message.php:745
static getSaltByEntityType(string $entityType, int $entityId, ?int $userId=null)
Definition message.php:731
static prepare(&$message)
Definition message.php:143
static isIcalMessage(\Bitrix\Mail\Item\Message $message)
Definition message.php:819
static prepareSearchContent(&$fields)
Definition message.php:407
static parseAddressList($column)
Definition message.php:576
static isolateStylesInTheBody($html)
Definition message.php:629
static ensureAttachments(&$message)
Definition message.php:498
static isolateStylesInTheTag($matches)
Definition message.php:614
static isBodyNeedUpdateAfterLoadAttachments(string $body)
Definition message.php:789
static getMaxAttachedFilesSize()
Definition message.php:24
static reSyncBody($mailboxId, $messageIds)
Definition message.php:668
static replaceBodyInlineImgContentId(string $body, string $contentId, int $attachmentId)
Definition message.php:803
static getCountersForUserMailboxes($userId, $onlyGeneralCounter=false)
Definition message.php:434
static hasAccess(&$message, $userId=null)
Definition message.php:322
static getWhitelistTagAttributes()
Definition message.php:48
static isolateSelector($matches)
Definition message.php:602
static getUserMailbox($mailboxId, $userId=null)
Definition mailbox.php:110
static getUserMailboxes($userId=null)
Definition mailbox.php:257