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