• Модуль: subscribe
  • Путь к файлу: ~/bitrix/modules/subscribe/classes/general/posting.php
  • Класс: CPostingGeneral
  • Вызов: CPostingGeneral::SendMessage
function SendMessage($ID, $timeout=0, $maxcount=0, $check_charset=false)
{
	global $DB, $APPLICATION;

	$eol = BitrixMainMailMail::getMailEol();
	$ID = intval($ID);
	$timeout = intval($timeout);
	$start_time = getmicrotime();

	@set_time_limit(0);
	$this->LAST_ERROR = "";

	$post = $this->GetByID($ID);
	if(!($post_arr = $post->Fetch()))
	{
		$this->LAST_ERROR .= GetMessage("class_post_err_notfound");
		return false;
	}

	if($post_arr["STATUS"] != "P")
	{
		$this->LAST_ERROR .= GetMessage("class_post_err_status")."
"; return false; } if( $check_charset && ($post_arr["MSG_CHARSET"] <> '') && (mb_strtoupper($post_arr["MSG_CHARSET"]) != mb_strtoupper(LANG_CHARSET)) ) { return "CONTINUE"; } if(CPosting::Lock($ID)===false) { if($e = $APPLICATION->GetException()) { $this->LAST_ERROR .= GetMessage("class_post_err_lock")."
".$e->GetString(); if(mb_strpos($this->LAST_ERROR, "PLS-00201") !== false && mb_strpos($this->LAST_ERROR, "'DBMS_LOCK'") !== false) $this->LAST_ERROR .= "
".GetMessage("class_post_err_lock_advice"); $APPLICATION->ResetException(); return false; } else { return "CONTINUE"; } } if($post_arr["VERSION"] <> '2') { if(is_string($post_arr["BCC_TO_SEND"]) && $post_arr["BCC_TO_SEND"] <> '') { $a = explode(",", $post_arr["BCC_TO_SEND"]); foreach($a as $e) $DB->Query("INSERT INTO b_posting_email (POSTING_ID, STATUS, EMAIL) VALUES (".$ID.", 'Y', '".$DB->ForSQL($e)."')"); } if(is_string($post_arr["ERROR_EMAIL"]) && $post_arr["ERROR_EMAIL"] <> '') { $a = explode(",", $post_arr["ERROR_EMAIL"]); foreach($a as $e) $DB->Query("INSERT INTO b_posting_email (POSTING_ID, STATUS, EMAIL) VALUES (".$ID.", 'E', '".$DB->ForSQL($e)."')"); } if(is_string($post_arr["SENT_BCC"]) && $post_arr["SENT_BCC"] <> '') { $a = explode(",", $post_arr["SENT_BCC"]); foreach($a as $e) $DB->Query("INSERT INTO b_posting_email (POSTING_ID, STATUS, EMAIL) VALUES (".$ID.", 'N', '".$DB->ForSQL($e)."')"); } $DB->Query("UPDATE b_posting SET VERSION='2', BCC_TO_SEND=null, ERROR_EMAIL=null, SENT_BCC=null WHERE ID=".$ID); } $tools = new CMailTools; //MIME with attachments if($post_arr["BODY_TYPE"]=="html" && COption::GetOptionString("subscribe", "attach_images")=="Y") { $post_arr["BODY"] = $tools->ReplaceImages($post_arr["BODY"]); } if($post_arr["CHARSET"] <> '') { $from_charset = $post_arr["MSG_CHARSET"]? $post_arr["MSG_CHARSET"]: SITE_CHARSET; $post_arr["BODY"] = $APPLICATION->ConvertCharset($post_arr["BODY"], $from_charset, $post_arr["CHARSET"]); $post_arr["SUBJECT"] = $APPLICATION->ConvertCharset($post_arr["SUBJECT"], $from_charset, $post_arr["CHARSET"]); $post_arr["FROM_FIELD"] = $APPLICATION->ConvertCharset($post_arr["FROM_FIELD"], $from_charset, $post_arr["CHARSET"]); } //Preparing message header, text, subject $sBody = str_replace("rn", "n", $post_arr["BODY"]); $sBody = implode( "n", array_filter( preg_split("/(.{512}[^ ]*[ ])/", $sBody." ", -1, PREG_SPLIT_DELIM_CAPTURE) ) ); //Some MTA has 4K limit for fgets function. So we have to split the message body. if(COption::GetOptionString("main", "CONVERT_UNIX_NEWLINE_2_WINDOWS", "N") == "Y") $sBody = str_replace("n", "rn", $sBody); if(COption::GetOptionString("subscribe", "allow_8bit_chars") <> "Y") { $sSubject = CMailTools::EncodeSubject($post_arr["SUBJECT"], $post_arr["CHARSET"]); $sFrom = CMailTools::EncodeHeaderFrom($post_arr["FROM_FIELD"], $post_arr["CHARSET"]); } else { $sSubject = $post_arr["SUBJECT"]; $sFrom = $post_arr["FROM_FIELD"]; } if($post_arr["BODY_TYPE"] == "html") { //URN2URI $tmpTools = new CMailTools; $sBody = $tmpTools->ReplaceHrefs($sBody); } $bHasAttachments = false; $sHeader = ""; $sBoundary = ""; if(count($tools->aMatches) > 0) { $bHasAttachments = true; $sBoundary = "----------".uniqid(""); $sHeader = 'From: '.$sFrom.$eol. 'X-Bitrix-Posting: '.$post_arr["ID"].$eol. 'MIME-Version: 1.0'.$eol. 'Content-Type: multipart/mixed; boundary="'.$sBoundary.'"'.$eol. 'Content-Transfer-Encoding: 8bit'; $sBody = "--".$sBoundary.$eol. "Content-Type: ".($post_arr["BODY_TYPE"]=="html"? "text/html":"text/plain").($post_arr["CHARSET"]<>""? "; charset=".$post_arr["CHARSET"]:"").$eol. "Content-Transfer-Encoding: 8bit".$eol.$eol. $sBody.$eol; foreach($tools->aMatches as $attachment) { if($post_arr["CHARSET"] <> '') { $from_charset = $post_arr["MSG_CHARSET"]? $post_arr["MSG_CHARSET"]: SITE_CHARSET; $attachment["DEST"] = $APPLICATION->ConvertCharset($attachment["DEST"], $from_charset, $post_arr["CHARSET"]); } if(COption::GetOptionString("subscribe", "allow_8bit_chars") <> "Y") $name = CMailTools::EncodeSubject($attachment["DEST"], $post_arr["CHARSET"]); else $name = $attachment["DEST"]; $sBody .= $eol."--".$sBoundary.$eol. "Content-Type: ".$attachment["CONTENT_TYPE"]."; name="".$name.""".$eol. "Content-Transfer-Encoding: base64".$eol. "Content-ID: <".$attachment["ID"].">".$eol.$eol. chunk_split( base64_encode( file_get_contents($attachment["PATH"]) ), 72, $eol ); } } $arFiles = array(); $maxFileSize = intval(COption::GetOptionInt("subscribe", "max_file_size")); $rsFile = CPosting::GetFileList($ID); while($arFile = $rsFile->Fetch()) { if ( $maxFileSize == 0 || $arFile["FILE_SIZE"] <= $maxFileSize ) $arFiles[] = $arFile; } if(!empty($arFiles)) { if(!$bHasAttachments) { $bHasAttachments = true; $sBoundary = "----------".uniqid(""); $sHeader = "From: ".$sFrom.$eol. 'X-Bitrix-Posting: '.$post_arr["ID"].$eol. "MIME-Version: 1.0".$eol. "Content-Type: multipart/mixed; boundary="".$sBoundary.""".$eol. "Content-Transfer-Encoding: 8bit"; $sBody = "--".$sBoundary.$eol. "Content-Type: ".($post_arr["BODY_TYPE"]=="html"? "text/html":"text/plain").($post_arr["CHARSET"]<>""? "; charset=".$post_arr["CHARSET"]:"").$eol. "Content-Transfer-Encoding: 8bit".$eol.$eol. $sBody.$eol; } foreach ($arFiles as $arFile) { if($post_arr["CHARSET"] <> '') { $from_charset = $post_arr["MSG_CHARSET"]? $post_arr["MSG_CHARSET"]: SITE_CHARSET; $file_name = $APPLICATION->ConvertCharset($arFile["ORIGINAL_NAME"], $from_charset, $post_arr["CHARSET"]); } else { $file_name = $arFile["ORIGINAL_NAME"]; } $sBody .= $eol."--".$sBoundary.$eol. "Content-Type: ".$arFile["CONTENT_TYPE"]."; name="".$file_name.""".$eol. "Content-Transfer-Encoding: base64".$eol. "Content-Disposition: attachment; filename="".CMailTools::EncodeHeaderFrom($file_name, $post_arr["CHARSET"]).""".$eol.$eol; $arTempFile = CFile::MakeFileArray($arFile["ID"]); $sBody .= chunk_split( base64_encode( file_get_contents($arTempFile["tmp_name"]) ), 72, $eol ); } } if($bHasAttachments) { $sBody .= $eol."--".$sBoundary."--".$eol; } else { //plain message without MIME $sHeader = "From: ".$sFrom.$eol. 'X-Bitrix-Posting: '.$post_arr["ID"].$eol. "MIME-Version: 1.0".$eol. "Content-Type: ".($post_arr["BODY_TYPE"]=="html"? "text/html":"text/plain").($post_arr["CHARSET"]<>""? "; charset=".$post_arr["CHARSET"]:"").$eol. "Content-Transfer-Encoding: 8bit"; } $mail_additional_parameters = trim(COption::GetOptionString("subscribe", "mail_additional_parameters")); $context = new MailContext(); $context->setCategory(MailContext::CAT_EXTERNAL); $context->setPriority(MailContext::PRIORITY_LOW); if($post_arr["DIRECT_SEND"] == "Y") { //personal delivery $arEvents = GetModuleEvents("subscribe", "BeforePostingSendMail", true); $rsEmails = $DB->Query($DB->TopSql(" SELECT * FROM b_posting_email WHERE POSTING_ID = ".$ID." AND STATUS='Y' ", $maxcount)); while($arEmail = $rsEmails->Fetch()) { //Event part $arFields = array( "POSTING_ID" => $ID, "EMAIL" => $arEmail["EMAIL"], "SUBJECT" => $sSubject, "BODY" => $sBody, "HEADER" => $sHeader, "EMAIL_EX" => $arEmail, ); foreach($arEvents as $arEvent) $arFields = ExecuteModuleEventEx($arEvent, array($arFields)); //Sending if(is_array($arFields)) { $to = CMailTools::EncodeHeaderFrom($arFields["EMAIL"], $post_arr["CHARSET"]); $result = bxmail($to, $arFields["SUBJECT"], $arFields["BODY"], $arFields["HEADER"], $mail_additional_parameters, $context); } else { $result = $arFields !== false; } //Result check and iteration if($result) $DB->Query("UPDATE b_posting_email SET STATUS='N' WHERE ID = ".$arEmail["ID"]); else $DB->Query("UPDATE b_posting_email SET STATUS='E' WHERE ID = ".$arEmail["ID"]); if($timeout > 0 && getmicrotime()-$start_time >= $timeout) break; self::$current_emails_per_hit++; } } else { //BCC delivery $rsEmails = $DB->Query($DB->TopSql(" SELECT * FROM b_posting_email WHERE POSTING_ID = ".$ID." AND STATUS='Y' ", COption::GetOptionString("subscribe", "max_bcc_count"))); $aStep = array(); while($arEmail = $rsEmails->Fetch()) $aStep[$arEmail["ID"]] = $arEmail["EMAIL"]; if(count($aStep) > 0) { $BCC = implode(",", $aStep); $sHeaderStep = $sHeader.$eol."Bcc: ".$BCC; $result = bxmail($post_arr["TO_FIELD"], $sSubject, $sBody, $sHeaderStep, $mail_additional_parameters, $context); if($result) { $DB->Query("UPDATE b_posting_email SET STATUS='N' WHERE ID in (".implode(", ", array_keys($aStep)).")"); } else { $DB->Query("UPDATE b_posting_email SET STATUS='E' WHERE ID in (".implode(", ", array_keys($aStep)).")"); $this->LAST_ERROR .= GetMessage("class_post_err_mail")."
"; } } } //set status and delivered and error emails $arStatuses = $this->GetEmailStatuses($ID); if(!array_key_exists("Y", $arStatuses)) { $STATUS = array_key_exists("E", $arStatuses)? "E": "S"; $DATE = $DB->GetNowFunction(); } else { $STATUS = "P"; $DATE = "null"; } CPosting::UnLock($ID); $DB->Query("UPDATE b_posting SET STATUS='".$STATUS."', DATE_SENT=".$DATE." WHERE ID=".$ID); return ($STATUS=="P"? "CONTINUE": true); }