145 $message[
'__email'] =
null;
146 foreach (array($message[
'MAILBOX_EMAIL'], $message[
'MAILBOX_NAME'], $message[
'MAILBOX_LOGIN']) as $item)
149 if ($address->validate())
151 $message[
'__email'] = $address->getEmail();
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',
165 if (
'' != $message[
'HEADER'])
167 foreach ($fieldsMap as $field)
169 if (mb_strlen($message[$field]) == 255)
171 $parsedHeader = \CMailMessage::parseHeader($message[
'HEADER'], LANG_CHARSET);
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')
187 foreach ($fieldsMap as $fieldKey => $fieldName)
189 $message[$fieldKey] = [];
191 if($fieldName ===
'FIELD_FROM')
193 if(static::checkMessageIsOutcomeByField($message,$fieldKey,$message[$fieldName]))
195 $message[
'__is_outcome'] =
true;
198 $filed = static::prepareField($message[$fieldName]);
202 $message[$fieldKey][] = $filed;
208 foreach (explode(
',', $message[$fieldName]) as $item)
210 if(static::checkMessageIsOutcomeByField($message,$fieldKey,$item))
212 $message[
'__is_outcome'] =
true;
215 $filed = static::prepareField($item);
219 $message[$fieldKey][] = $filed;
224 if (empty($message[
'__reply_to']))
226 $message[
'__reply_to'] = $message[
'__from'];
230 $message[
'__href'] = sprintf(
'/mail/message/%u', $message[
'ID']);
232 $urlManager = Attachment\Storage::getUrlManager();
234 if (!empty($message[
'__files']) && is_array($message[
'__files']))
236 $urlParams = array();
238 if (isset($_REQUEST[
'mail_uf_message_token']) && is_string($_REQUEST[
'mail_uf_message_token']))
240 $urlParams[
'mail_uf_message_token'] = $_REQUEST[
'mail_uf_message_token'];
243 foreach ($message[
'__files'] as $k => $item)
245 if ($diskFile = Attachment\Storage::getObjectByAttachment($item,
true))
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(),
257 if (\
Bitrix\Disk\TypeFile::isImage($diskFile))
259 $message[
'__files'][$k][
'preview'] = $urlManager->getUrlForShowFile(
262 array(
'width' => 80,
'height' => 80,
'exact' =>
'Y'),
268 $inlineParams = array_merge(
269 array(
'__bxacid' => sprintf(
'n%u', $diskFile->getId())),
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']
280 $file = \CFile::getFileArray($item[
'FILE_ID']);
281 if (!empty($file) && is_array($file))
283 $message[
'__files'][$k] = array(
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'],
292 if (\CFile::isImage($item[
'FILE_NAME'], $item[
'CONTENT_TYPE']))
294 $preview = \CFile::resizeImageGet(
295 $file, array(
'width' => 80,
'height' => 80),
296 BX_RESIZE_IMAGE_EXACT,
false
299 if (!empty($preview[
'src']))
301 $message[
'__files'][$k][
'preview'] = $preview[
'src'];
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']
313 unset($message[
'__files'][$k]);
322 public static function hasAccess(&$message, $userId =
null)
327 !($userId > 0 || is_object($USER) && $USER->isAuthorized()) ||
329 is_null($message[
'ID']) || $message[
'ID'] === 0 || $message[
'ID'] ===
'0'
337 $userId = $USER->getId();
340 $messageAccess = \Bitrix\Mail\MessageAccess::createByMessageId($message[
'ID'], $userId);
341 $access = $messageAccess->isOwner();
343 $message[
'__access_level'] = $access ?
'full' :
false;
346 if (!$access && isset($_REQUEST[
'mail_uf_message_token']))
348 $token = $signature =
'';
349 if (is_string($_REQUEST[
'mail_uf_message_token']) && mb_strpos($_REQUEST[
'mail_uf_message_token'],
':') > 0)
351 [$token, $signature] = explode(
':', $_REQUEST[
'mail_uf_message_token'], 2);
354 if ($token <>
'' && $signature <>
'')
356 $excerpt = MessageAccessTable::getList(array(
357 'select' => array(
'SECRET',
'MESSAGE_ID',
'ENTITY_TYPE',
'ENTITY_ID'),
360 '=MAILBOX_ID' => $message[
'MAILBOX_ID'],
365 if (!empty($excerpt[
'SECRET']))
367 if (self::checkAccessForEntityToken($excerpt[
'ENTITY_TYPE'], (
int)$excerpt[
'ENTITY_ID'], $userId))
369 $salt = self::getSaltByEntityType($excerpt[
'ENTITY_TYPE'], (
int)$excerpt[
'ENTITY_ID'], $userId);
373 if ($signer->validate($excerpt[
'SECRET'], $signature, $salt))
375 $access = $message[
'ID'] == $excerpt[
'MESSAGE_ID'];
379 $access = (bool) MessageClosureTable::getList(array(
380 'select' => array(
'PARENT_ID'),
382 '=MESSAGE_ID' => $message[
'ID'],
383 '=PARENT_ID' => $excerpt[
'MESSAGE_ID'],
396 $access = $messageAccess->canViewMessage();
399 if (
false === $message[
'__access_level'])
401 $message[
'__access_level'] = $access ?
'read' :
false;
436 static $countersForUsers;
438 if (empty($countersForUsers))
440 $countersForUsers = [];
443 if (!isset($countersForUsers[$userId]))
447 if (empty($mailboxes))
452 $mailboxIds = array_column($mailboxes,
'ID');
454 $totalUnseen = Internals\MailCounterTable::getList([
464 '=ENTITY_TYPE' =>
'MAILBOX',
465 '@ENTITY_ID' => $mailboxIds,
473 foreach ($totalUnseen as $index => $item)
475 $totalCounter += $item[
'VALUE'];
477 $counters[$item[
'ENTITY_ID']] = [
478 'UNSEEN' => $item[
'VALUE'],
482 $countersForUsers[$userId] = [
483 'mailboxesWithCounters' => $counters,
484 'totalCounter' => $totalCounter,
488 if($onlyGeneralCounter)
490 return $countersForUsers[$userId][
'totalCounter'];
494 return $countersForUsers[$userId][
'mailboxesWithCounters'];
500 if ($message[
'ATTACHMENTS'] > 0 || !($message[
'OPTIONS'][
'attachments'] > 0))
505 if (Option::get(
'mail',
'save_attachments', B_MAIL_SAVE_ATTACHMENTS) !==
'Y')
512 $attachments = empty($mailboxHelper) ? false : $mailboxHelper->downloadAttachments($message);
514 if (
false === $attachments)
517 'Helper\Message: Attachments downloading failed (%u:%s:%u)',
518 $message[
'MAILBOX_ID'],
523 if (!empty($mailboxHelper) && !$mailboxHelper->getErrors()->isEmpty())
525 $logEntry .= PHP_EOL . join(PHP_EOL, $mailboxHelper->getErrors()->toArray());
528 addMessage2Log($logEntry,
'mail', 2);
533 $originalBody = $message[
'BODY_HTML'] ??
null;
534 foreach ($attachments as $i => $item)
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'],
544 $attachmentId = \CMailMessage::addAttachment($attachFields);
546 if ($attachmentId > 0)
548 $message[
'ATTACHMENTS']++;
550 if (isset($message[
'BODY_HTML']) && mb_strlen($message[
'BODY_HTML']) > 0)
552 $bodyWithReplaced = self::replaceBodyInlineImgContentId(
553 (
string)$message[
'BODY_HTML'],
554 (
string)$item[
'CONTENT-ID'],
557 if ($bodyWithReplaced)
559 $message[
'BODY_HTML'] = $bodyWithReplaced;
565 if ($message[
'ATTACHMENTS'] > 0)
567 if ($originalBody !== $message[
'BODY_HTML'])
569 \CMailMessage::update($message[
'ID'], [
'BODY_HTML' => $message[
'BODY_HTML']], $message[
'MAILBOX_ID']);
572 return $message[
'ID'];
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);
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;
639 $messageHtml = preg_replace(
'%((?:^|\s)position(?:^|\s)?:(?:^|\s)?)(absolute|fixed|inherit)%',
'$1relative', $messageHtml);
641 $messageHtml = preg_replace(
'%@media\b[^{]*({((?:[^{}]+|(?1))*)})%msi',
'', $messageHtml);
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);
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);
662 $cleared = static::isolateMessageStyles($cleared);
670 if (empty($messageIds) || !is_array($messageIds))
675 $messages = \Bitrix\Mail\MailMessageUidTable::getList([
680 '=MAILBOX_ID' => $mailboxId,
681 '@MESSAGE_ID' => $messageIds,
685 $notProcessed = array_combine($messageIds, $messageIds);
689 if(!empty($mailboxHelper))
691 $mailbox = $mailboxHelper->getMailbox();
693 while ($message = $messages->fetch())
695 $technicalTitle = $mailboxHelper->downloadMessage($message);
698 $charset = $mailbox[
'CHARSET'] ?: $mailbox[
'LANG_CHARSET'];
699 [$header, $html, $text, $attachments] = \CMailMessage::parseMessage($technicalTitle, $charset);
701 if (\CMailMessage::isLongMessageBody($text))
703 [$text, $html] = \CMailMessage::prepareLongMessage($text, $html);
706 if (rtrim($text) || $html)
708 \CMailMessage::update(
709 $message[
'MESSAGE_ID'],
711 'BODY' => rtrim($text),
712 'BODY_HTML' => $html,
718 self::updateMailEntityOptionsRow($mailboxId, (
int)$message[
'MESSAGE_ID']);
719 unset($notProcessed[$message[
'MESSAGE_ID']]);
723 foreach ($notProcessed as $messageId)
725 self::updateMailEntityOptionsRow($mailboxId, (
int)$messageId);