5use Bitrix\Mail\Integration\UI\EntitySelector\AddressBookProvider;
7use Bitrix\Main\Context;
8use Bitrix\Main\Localization\Loc;
9use Bitrix\UI\EntitySelector\Dialog;
10use Bitrix\UI\EntitySelector\ItemCollection;
24 const QUOTE_HTML_REGEX =
'/<div\s[^>]+srvb24mqsm[^>]+>.*?<\/div>(.*)<div\s[^>]+qemb24msrv[^>]+>.*?<\/div>/is';
38 'headers',
'subject',
'from',
'to',
39 'text',
'html',
'attachments',
43 foreach ($properties as $property)
46 $this->$property =
$message[$property];
52 return preg_replace(
'/^("(.*)"|\'(.*)\')$/',
'$2$3',
$text);
55 private static function convertContactListToString($list): string
59 foreach ($list as $contact)
61 $name = static::stripQuotes($contact[
'name']);
62 $email = $contact[
'email'];
69 $string .= Loc::getMessage(
'MAIL_QUOTE_MESSAGE_HEADER_CONTACT', [
'#NAME#' =>
$name,
'#EMAIL#' =>
$email]);
85 'id' => AddressBookProvider::PROVIDER_ENTITY_ID,
91 $provider = $dialog->getEntity(AddressBookProvider::PROVIDER_ENTITY_ID)->getProvider();
92 $provider->setPreinstalledItems($recipients, $updateData);
98 $itemCollection->add($item);
101 return $itemCollection;
106 $fieldDateInTimeStamp = makeTimestamp($timeString);
107 $titleDateFormat = Context::getCurrent()->getCulture()->getFullDateFormat().
"
H:i:s";
108 $formattedDate =
FormatDate($titleDateFormat, $fieldDateInTimeStamp, (time() + CTimeZone::getOffset()));
112 $fromList = static::convertContactListToString(
$from);
113 $toList = static::convertContactListToString(
$to);
114 $ccList = static::convertContactListToString($cc);
117 $body = Helper\Message::sanitizeHtml($body);
122 $wrap .= Loc::getMessage(
'MAIL_QUOTE_MESSAGE_HEADER_WITHOUT_CC', [
123 '#DATE#' => $formattedDate,
126 '#FROM_LIST#' => $fromList,
127 '#TO_LIST#' => $toList,
128 '[blockquote]' =>
'<blockquote style="margin: 0 0 0 5px; padding: 5px 5px 5px 8px; border-left: 4px solid #e2e3e5; ">',
129 '[/blockquote]' =>
'</blockquote>'
134 $wrap .= Loc::getMessage(
'MAIL_QUOTE_MESSAGE_HEADER', [
135 '#DATE#' => $formattedDate,
138 '#FROM_LIST#' => $fromList,
139 '#TO_LIST#' => $toList,
140 '#CC_LIST#' => $ccList,
141 '[blockquote]' =>
'<blockquote style="margin: 0 0 0 5px; padding: 5px 5px 5px 8px; border-left: 4px solid #e2e3e5; ">',
142 '[/blockquote]' =>
'</blockquote>'
157 return $html ? static::QUOTE_START_MARKER_HTML : static::QUOTE_START_MARKER;
168 return $html ? static::QUOTE_END_MARKER_HTML : static::QUOTE_END_MARKER;
178 return is_array($this->attachments) ?
count($this->attachments) : 0;
188 if (isset($this->html))
193 $html = preg_replace(
'/<br\s*\/?>/is',
"\n",
$html);
195 $html = str_ireplace(
'</div>',
"</div>\n",
$html);
196 $html = str_ireplace(
'</p>',
"</p>\n",
$html);
197 $html = preg_replace(
'/<\/h([1-6])>/i',
"</h\\1>\n",
$html);
198 $html = str_ireplace(
'</table>',
"</table>\n",
$html);
199 $html = str_ireplace(
'</tr>',
"</tr>\n",
$html);
200 $html = str_ireplace(
'</pre>',
"</pre>\n",
$html);
202 $html = preg_replace(
'/(\n\s*)?<div/i',
"\n<div",
$html);
203 $html = preg_replace(
'/(\n\s*)?<p(?=\s|>)/i',
"\n<p",
$html);
204 $html = preg_replace(
'/(\n\s*)?<h([1-6])/i',
"\n<h\\2",
$html);
205 $html = preg_replace(
'/(\n\s*)?<table/i',
"\n<table",
$html);
206 $html = preg_replace(
'/(\n\s*)?<tr/i',
"\n<tr",
$html);
207 $html = preg_replace(
'/(\n\s*)?<pre/i',
"\n<pre",
$html);
209 $html = preg_replace(
'/(\n\s*)?<hr[^>]*>(\s*\n)?/i',
"\n<hr>\n",
$html);
213 list($before, $quote, $after) = $parts;
214 $html = sprintf(
'%s%s%s', $before, static::QUOTE_PLACEHOLDER, $after);
219 foreach ($this->attachments as $item)
221 $html = preg_replace(
222 sprintf(
'/<img[^>]+src\s*=\s*(\'|\")?\s*(cid:%s)\s*\1[^>]*>/is', preg_quote($item[
'contentId'],
'/')),
223 sprintf(
'[ATTACHMENT=%s]', $item[
'uniqueId']),
230 $html = preg_replace(
'/<style[^>]*>.*?<\/style>/is',
'',
$html);
231 $html = preg_replace(
'/<script[^>]*>.*?<\/script>/is',
'',
$html);
232 $html = preg_replace(
'/<title[^>]*>.*?<\/title>/is',
'',
$html);
233 $html = preg_replace(
'/<caption[^>]*>.*?<\/caption>/is',
'',
$html);
236 $html = preg_replace(
'/<a\s[^>]*href\s*=\s*([^\'\"\s>]+)\s*[^>]*>/is',
'<a href="\1">',
$html);
239 $html = preg_replace(
'/<strong[^>]*>(.*?)<\/strong>/is',
'<b>\1</b>',
$html);
240 $html = preg_replace(
'/<em[^>]*>(.*?)<\/em>/is',
'<i>\1</i>',
$html);
241 $html = preg_replace(
'/<blockquote[^>]*>(.*?)<\/blockquote>/is',
'<quote>\1</quote>',
$html);
242 $html = preg_replace(
'/<hr[^>]*>/is',
'________________________________________',
$html);
243 $html = preg_replace(
'/<del[^>]*>(.*?)<\/del>/is',
'<s>\1</s>',
$html);
244 $html = preg_replace(
'/<ins[^>]*>(.*?)<\/ins>/is',
'<u>\1</u>',
$html);
245 $html = preg_replace(
'/<h([1-6])[^>]*>(.*?)<\/h\1>/is',
'<b>\2</b>',
$html);
246 $html = preg_replace(
'/<dl[^>]*>(.*?)<\/dl>/is',
'<ul>\1</ul>',
$html);
247 $html = preg_replace(
'/<dt[^>]*>/is',
'<li>',
$html);
248 $html = preg_replace(
'/<dd[^>]*>/is',
' - ',
$html);
249 $html = preg_replace(
'/<(sub|sup)[^>]*>(.*?)<\/\1>/is',
'(\2)',
$html);
252 $html = preg_replace(
'/<th[^>]*>(.*?)<\/th>/is',
'<td>\1</td>',
$html);
254 $sanitizer = new \CBXSanitizer();
256 $sanitizer->addTags(
array(
257 'a' =>
array(
'href'),
262 'img' =>
array(
'src'),
263 'font' =>
array(
'color',
'size',
'face'),
276 $sanitizer->applyDoubleEncode(
false);
279 $parser = new \CTextParser();
285 $text = preg_replace(
'/<\/?([abuis]|img|font|ul|ol|li|table|tr|td|th|quote|br)(?=\s|>)[^>]*>/i',
'',
$text);
287 $text = preg_replace(
'/[\t\x20]+/',
"\x20",
$text);
298 list($before, $quote, $after) = $parts;
299 $text = sprintf(
'%s%s%s', $before, static::QUOTE_PLACEHOLDER, $after);
304 foreach ($this->attachments as $item)
307 sprintf(
'[cid:%s]', $item[
'contentId']),
308 sprintf(
'[ATTACHMENT=%s]', $item[
'uniqueId']),
315 if ($this->type ==
'reply' && mb_strpos(
$text, static::QUOTE_PLACEHOLDER))
318 $text = preg_replace(sprintf(
'/\s*%s\s*/', preg_quote(static::QUOTE_PLACEHOLDER,
'/')),
"\n\n",
$text);
321 if ($this->type ==
'forward')
325 $text = preg_replace(
'/\[tr\]\s*\[\/tr\]/is',
'',
$text);
326 $text = preg_replace(
'/\[table\]\s*\[\/table\]/is',
'',
$text);
329 $text = preg_replace(
'/(\s*\n){2,}/',
"\n\n",
$text);
332 $text = sprintf(
'[ATTACHMENT=%s]', $item[
'uniqueId']);
334 if (!empty($this->secret))
335 $text = str_replace($this->secret,
'xxxxxxxx',
$text);
355 $reply =
new static(
$message,
'reply');
357 return $reply->parse();
368 $forward =
new static(
$message,
'forward');
370 return $forward->parse();
381 $parts = preg_split(
'/(<blockquote.+?<\/blockquote>)/is',
$html,
null, PREG_SPLIT_DELIM_CAPTURE);
383 if (
count($parts) > 3)
385 $parts = array_merge(
386 array(join(array_slice($parts, 0, -2))),
387 array_slice($parts, -2)
392 if (
count($parts) == 3)
393 $parts = preg_split(
'/(<blockquote.+<\/blockquote>)/is',
$html,
null, PREG_SPLIT_DELIM_CAPTURE);
396 if (
count($parts) < 3)
397 $parts = preg_split(static::QUOTE_HTML_REGEX,
$html,
null, PREG_SPLIT_DELIM_CAPTURE);
399 if (
count($parts) == 3)
413 $parts = preg_split(
'/((?:^>.*$\n?){2,})/m',
$text,
null, PREG_SPLIT_DELIM_CAPTURE);
415 if (
count($parts) < 3)
416 $parts = preg_split(
'/((?:^\|.*$\n?){2,})/m',
$text,
null, PREG_SPLIT_DELIM_CAPTURE);
418 if (
count($parts) < 3)
421 (?:^_{20,}\n(?:[\t\x20]*\n)?)?
422 (?:^(?:from|to|subject|sent|date):\x20[^\n]+$\n?){2,8}.*
424 $parts = preg_split($outlookRegex,
$text,
null, PREG_SPLIT_DELIM_CAPTURE);
427 if (
count($parts) == 3)
443 if (preg_match_all(
'/^([^\:\n]{1,20}):[\t\x20]+(.+)$/mu', $head,
$matches, PREG_SET_ORDER))
446 'value' => $this->subject,
447 'strlen' => mb_strlen($this->subject),
448 'sgnlen' => mb_strlen(trim($this->subject))
453 if (mb_strlen(trim($value)) >= 10 &&
$subject[
'sgnlen'] >= 10)
455 $dist =
$subject[
'strlen'] - mb_strlen($value);
459 if ($dist >= 0 && mb_strpos(
$subject[
'value'], $value) !==
false)
464 if (max(
$subject[
'strlen'], mb_strlen($value)) < 256 && levenshtein(
$subject[
'value'], $value) < 10)
471 $date = preg_replace(
'/(?<=[\s\d])UT$/i',
'+0000', trim($value));
472 if (preg_match(
'/\d{1,2}:\d{2}(:\d{2})?\x20?(am|pm)?/i', $date) && strtotime($date) !==
false)
477 if (preg_match(
'/([a-z\d_](\.?[a-z\d_-]+)*)?[a-z\d_]@(([a-z\d][a-z\d-]*)?[a-z\d]\.?)+/i', $value))
487 $score += (int) $isHeader($item[1], $item[2]);
505 (?<date>.{5,50}\d),?\x20
506 [^\d\n]{0,20}(?<time>\d{1,2}\:\d{2}(?:\:\d{2})?\x20?(?:am|pm)?),?\x20
509 if (preg_match($regex, $head,
$matches))
512 if (strtotime(
$matches[
'date']) !==
false)
516 else if (preg_match(
'/^[^\x20]+\x20+((?:[^\x20]+\x20+)?(.+))$/',
$matches[
'date'], $date))
518 if (strtotime($date[1]) !==
false || strtotime($date[2]) !==
false)
522 if (preg_match(
'/([a-z\d_](\.?[a-z\d_-]+)*)?[a-z\d_]@(([a-z\d][a-z\d-]*)?[a-z\d]\.?)+/i',
$matches[
'from']))
537 list($before, $after) = explode(static::QUOTE_PLACEHOLDER,
$text, 2);
542 $data = static::reduceTags($before);
553 $fullHeadRegex =
'/(?:^|\n\n)
554 (?<hr>_{20,}\n(?:[\t\x20]*\n)?)?
555 (?<head>(?:[^\:\n]{1,20}:[\t\x20]+.+(?:\n|$)){2,6})\s*$
559 $score = (int) !empty(
$matches[
'hr']);
565 $before = preg_replace_callback(
574 return sprintf(
'%s%s%s', $before, static::QUOTE_PLACEHOLDER, $after);
583 $shortHeadRegex =
'/(?:^|\n)
584 (?<date>.{5,50}\d),?\x20
585 [^\d\n]{0,20}(?<time>\d{1,2}\:\d{2}(?:\:\d{2})?\x20?(?:am|pm)?),?\x20
596 $before = preg_replace_callback(
605 return sprintf(
'%s%s%s', $before, static::QUOTE_PLACEHOLDER, $after);
625 $shortHeadRegex =
'/(?:^|\n)\s*
626 -{3,}.{4,40}?-{3,}[\t\x20]*\n
627 (?<head>(?:[\t\x20]*\n)?
628 (?<date>.{5,50}\d),?\x20
629 [^\d\n]{0,20}(?<time>\d{1,2}\:\d{2}(?:\:\d{2})?\x20?(?:am|pm)?),?\x20
630 (?<from>.+):(?:\s*\n)?)
633 $hasMarker = preg_match($shortHeadRegex,
$data);
634 $fullHeadRegex =
'/(?:^|\n\n)\s*
635 (?<marker>-{3,}.{4,40}?-{3,}[\t\x20]*\n)'.($hasMarker ?
'' :
'?').
'
636 (?<head>(?:[\t\x20]*\n)?
637 (?<lines>(?:[^\:\n]{1,20}:[\t\x20]+.+(?:\n|$)){2,6}))
641 if (preg_match($fullHeadRegex,
$data,
$matches, PREG_OFFSET_CAPTURE))
643 $score = (int) !empty(
$matches[
'marker'][0]);
654 return preg_replace_callback(
665 if (preg_match($shortHeadRegex,
$data,
$matches, PREG_OFFSET_CAPTURE))
678 return preg_replace_callback(
702 $data = preg_replace(
'/^(\[\/?(\*|[busi]|img|table|tr|td|th|quote|(url|size|color|font|list)(=.+?)?)\])+$/im',
"\t",
$data);
703 $data = preg_replace(
'/\[\/?(\*|[busi]|img|table|tr|td|th|quote|(url|size|color|font|list)(=.+?)?)\]/i',
'',
$data);
716 preg_match_all(
'/\[\/?([busi]|img|table|tr|td|th|quote|(url|size|color|font|list)(=.+?)?)\]/is',
$text, $tags);
723 $result = preg_replace(
'/\[([busi]|img|table|tr|td|th|quote|url|size|color|font|list)(=.+?)?\]\[\/\1\]/is',
'',
$result, -1, $n2);
if(!Loader::includeModule('messageservice')) $provider
static getSelectedRecipientsForDialog($recipients=[], $updateData=false)
removeForwardHead(&$text)
static stripQuotes($text)
static wrapTheMessageWithAQuote($body, $subject, $timeString, $from=[], $to=[], $cc=[], bool $sanitized=false)
static reduceHead(&$text)
const QUOTE_START_MARKER_HTML
static parseReply(array &$message)
static reduceTags(&$text)
__construct(array &$message, $type)
const QUOTE_END_MARKER_HTML
static getQuoteStartMarker($html=false)
static getQuoteEndMarker($html=false)
static parseForward(array &$message)
static parseMessage(array &$message)
static loadMessages($file)
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
FormatDate($format="", $timestamp=false, $now=false, ?string $languageId=null)
if(empty($signedUserToken)) $key
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
if(!Loader::includeModule('sale')) $pattern