Отправка писем в Битрикс на D7, старом ядре и через phpMailer
Последние записи
Отправка писем на D7 в Битрикс
Отправка простого сообщения по почтовому событию "USER_INFO" для сайта "s1" по расписанию:
\Bitrix\Main\Mail\Event::send(array(
"EVENT_NAME" => "USER_INFO",
"LID" => "s1",
"C_FIELDS" => array(
"EMAIL" => "test@mysite.ru",
"USER_ID" => 235
),
));
Отправка простого сообщения по почтовому событию "USER_INFO" для сайта "s1" (мгновенная):
\Bitrix\Main\Mail\Event::sendImmediate(array(
"EVENT_NAME" => "USER_INFO",
"LID" => "s1",
"C_FIELDS" => array(
"EMAIL" => "test@mysite.ru",
"USER_ID" => 235
),
));
Мгновенная отправка на почту отправленного на сервер файла вложением:
$fileId = false;
if($_FILES['file'])
$fileId = \CFile::SaveFile($_FILES['file'],"mailatt");
\Bitrix\Main\Mail\Event::sendImmediate(array( // or send
"EVENT_NAME" => "VM_SERVICE_REQUEST",
"LID" => "s2",
"C_FIELDS" => array(
"EMAIL" => $arCompany["PROPERTIES"]["EMAIL"]["VALUE"],
"COMPANY_NAME" => $arCompany["NAME"],
"MESSAGE" => $request->getPost("MESSAGE"),
"USER_NAME" => $USER->GetFullName(),
"USER_EMAIL" => $USER->GetEmail(),
),
"FILE" => array($fileId), // нужно сохранять сначала, из документации к CEvent::send: Массив id файлов, которые используются классом CFile. Либо можно передать массив абсолютных путей до файлов.
));
if($fileId)
CFile::Delete($fileId);
Аналогом функций \Bitrix\Main\Mail\Event
в старом ядре служит CEvent
. Вызов очень похож:
$arEventFields = array(
"ID" => $CONTRACT_ID,
"MESSAGE" => $mess,
"EMAIL_TO" => implode(",", $EMAIL_TO),
"ADMIN_EMAIL" => implode(",", $ADMIN_EMAIL),
"ADD_EMAIL" => implode(",", $ADD_EMAIL),
"STAT_EMAIL" => implode(",", $VIEW_EMAIL),
"EDIT_EMAIL" => implode(",", $EDIT_EMAIL),
"OWNER_EMAIL" => implode(",", $OWNER_EMAIL),
"BCC" => implode(",", $BCC),
"INDICATOR" => GetMessage("AD_".strtoupper($arContract["LAMP"]."_CONTRACT_STATUS")),
"ACTIVE" => $arContract["ACTIVE"],
"NAME" => $arContract["NAME"],
"DESCRIPTION" => $description,
"MAX_SHOW_COUNT" => $arContract["MAX_SHOW_COUNT"],
"SHOW_COUNT" => $arContract["SHOW_COUNT"],
"MAX_CLICK_COUNT" => $arContract["MAX_CLICK_COUNT"],
"CLICK_COUNT" => $arContract["CLICK_COUNT"],
"BANNERS" => $arContract["BANNER_COUNT"],
"DATE_SHOW_FROM" => $arContract["DATE_SHOW_FROM"],
"DATE_SHOW_TO" => $arContract["DATE_SHOW_TO"],
"DATE_CREATE" => $arContract["DATE_CREATE"],
"CREATED_BY" => $CREATED_BY,
"DATE_MODIFY" => $arContract["DATE_MODIFY"],
"MODIFIED_BY" => $MODIFIED_BY
);
$arrSITE = CAdvContract::GetSiteArray($CONTRACT_ID);
CEvent::Send("ADV_CONTRACT_INFO", $arrSITE, $arEventFields);
Стоит учесть, что SendImmediate
немедленно отправляет сообщение и не заносит информацию о нем в БД.
А Send
добавляет сообщение в очередь и добавляет информацию о событии в БД.
Отправка писем в Битриксе через PHPMailer
Что делать, если почта настроена, письма уходят, но не доходят до получателя или попадают в спам? Ситуация очень распространена, а потому заслуживает отдельного решения.
Будем считать, что вы уже знакомы с composer
, у вас есть свой smtp
сервер (подойдут сервисы "Почта для домена" от Яндекс или Mail.ru), на домене почты с которой идет отправка настроены записи DKIM, spf и т.д.
Первым делом устанавливаем PHPMailer
Идем в /local/php_interface/init.php
и добавляем функцию
use Bitrix\Main\Application;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
//Перехват генерации почтового события с возможностью его отмены
AddEventHandler("main", "OnBeforeEventAdd", array("OnBeforeEventAddClass", "OnBeforeEventAddHandler"));
class OnBeforeEventAddClass{
function OnBeforeEventAddHandler(&$event, &$lid, &$arFields, &$message_id, &$files){
// Load Composer's autoloader
require $_SERVER['DOCUMENT_ROOT'].'/vendor/autoload.php';
//Получаем соединение с БД
$connection = Bitrix\Main\Application::getConnection('default');
//Получаем шаблон письма
$recordset = $connection->query("select SUBJECT, MESSAGE, MESSAGE_PHP from b_event_message where ACTIVE = 'Y' AND EVENT_NAME = '".$event."'")->fetchAll();
//Проверяем есть ли хоть один шаблон
if(isset($recordset[0]['MESSAGE'])){
$mask = $recordset[0]['MESSAGE'];
$subject = $recordset[0]['SUBJECT'];
$fields = $arFields;
//Проходим по полям и заменяем все паттерны, которые найдем
foreach ($fields as $key => $value){
//Исключаем из замены массивы и символы ~
if(!is_array($value) && strpos($key, '~') === false){
//Заменяем все возможные паттерны
$mask = preg_replace('~\#'.$key.'\#~', $value, $mask);
$subject = preg_replace('~\#'.$key.'\#~', $value, $subject);
}
}
$mask = preg_replace('~\#SITE_NAME\#~', 'Название сайта', $mask);
$mask = preg_replace('~\#SERVER_NAME\#~', 'Домен сайта', $mask);
$mask = preg_replace('~\#DEFAULT_EMAIL_FROM\#~', 'Адрес почты с которой идет отправка', $mask);
$subject = preg_replace('~\#SITE_NAME\#~', 'Название сайта', $subject);
$subject = preg_replace('~\#SERVER_NAME\#~', 'Домен сайта', $subject);
if($mask) {
//Проверяем возможный перечень полей с почтой
//Данные поля уникальны для одного из моих проектов
if(isset($fields['RS_USER_EMAIL'])){
if (filter_var($fields['RS_USER_EMAIL'], FILTER_VALIDATE_EMAIL)) {
$email = $fields['RS_USER_EMAIL'];
}
}
if(isset($fields['EMAIL'])){
if (filter_var($fields['EMAIL'], FILTER_VALIDATE_EMAIL)) {
$email = $fields['EMAIL'];
}
}
if(isset($fields['EMAIL_TO'])){
if (filter_var($fields['EMAIL_TO'], FILTER_VALIDATE_EMAIL)) {
$email = $fields['EMAIL_TO'];
}
}
//Если почта есть и валидатор дает добро
if($email && filter_var($email, FILTER_VALIDATE_EMAIL)){
$cl = new OnBeforeEventAddClass;
//Отправляем письмо
if($cl->custom_mail($email, $subject, $mask,'',''))
AddMessage2Log($event.'- Сообщение было отправлено', "messages");
else
AddMessage2Log($event.'- Ошибка. Сообщение отправлено не было', "messages");
}else{
AddMessage2Log($event.'- Ошибка. Почта не найдена. Почта: '.$fields['EMAIL_RAW'], "messages");
}
return false;
}else{
AddMessage2Log($event.'- Ошибка. Нет тела письма', "messages");
}
}else{
AddMessage2Log($event.'- Ошибка. Не найден шаблон письма', "messages");
}
}
public function custom_mail($to, $subject, $message, $additionalHeaders = '', $additional_parameters)
{
// Instantiation and passing `true` enables exceptions
$mail = new PHPMailer(true);
//логирование ошибок (0 - не выводить)
$mail->SMTPDebug = 0;
$mail->CharSet = 'UTF-8';
$mail->isSMTP(); // Set mailer to use SMTP
//$mail->Host = 'mail.mail.ru'; // Specify main and backup SMTP servers
$mail->Host = 'ssl://smtp.mail.ru'; // Specify main and backup SMTP servers
$mail->SMTPAuth = true; // Enable SMTP authentication
$mail->Username = 'zakaz@YOUR_DOMAIN'; // SMTP username
$mail->Password = 'PASSWORD'; // SMTP password
$mail->SMTPSecure = 'ssl'; // Enable TLS encryption, `ssl` also accepted
//$mail->Port = 25; // port to connect to
$mail->Port = 465; // port to connect to
$d_message='';
$from = 'zakaz@YOUR_DOMAIN';
$d_message.='$from - '.$from.' +++ '; $d_message.='$to - '.$to.' +++ ';
$d_message.='$subject - '.$subject.' +++ ';
$d_message.='$message - '.$message.' +++ ';
$mail->setFrom($from, 'Название сайта');
$mail->addAddress($to, ''); // Add a recipient
$mail->addReplyTo($from, '');
//$mail->addCC('mail2@mail.ru');
$mail->AddBCC($from);
// $mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments
// $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name
$mail->Subject = $subject;
if($message != strip_tags($message)) {
$mail->isHTML(true);
}
$mail->Body = $message;
// $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
// log_message
$addLOG='To: '.$to.PHP_EOL. 'Subject: '.$subject.PHP_EOL. 'Message: '.$message.PHP_EOL. 'Headers: '.$additionalHeaders.PHP_EOL. 'Params: '.$additional_parameters.PHP_EOL;
file_put_contents($_SERVER['DOCUMENT_ROOT'].'/test/emailLog.txt', $addLOG);
if(!$mail->send()) {
// log error
file_put_contents($_SERVER['DOCUMENT_ROOT'].'/test/emailLog.txt', 'Mailer Error: ' . $d_message.' '.$mail->ErrorInfo);
return false;
} else {
return true;
}
}
}
AddMessage2Log
используется для отладки, на рабочих проектах можно выкинуть.
Таким образом мы получаем все сгенерированные письма перед их отправкой, получаем шаблон письма, заменяем в нем все константы, заполняем и отправляем средствами PHPMailer
, а почтовое событие Битрикс отменяем. В общем, что и требовалось.
Проблем с кодом или нагрузкой не выявлено на проектах с до 10к посетителей в сутки.
Использованы материалы:
Комментарии