Отправка писем в Битрикс на D7, старом ядре и через phpMailer
Rus
Eng
Отправка писем в Битрикс на 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к посетителей в сутки.

 

Использованы материалы:

 

Комментарии

Комментариев еще нет, Вы можете стать первым кто его оставит

Оставьте комментарий

На сайте используется система премодерирования комментариев, поэтому ваше сообщение будет опубликовано лишь после одобрения модератором

Вы отвечаете на комментарий пользователя

Отправить

ОБРАТНАЯ СВЯЗЬ

Напишите мне

Вы разрабатываете новый сервис, вносите доработки в существующий и хотите лучше чем у конкурентов? Вы обратились по адресу. Предлагаю вам комплексную разработку сайтов студийного уровня. У меня вы можете заказать дизайн, верстку, програмированние, разработку нетрадиционного функционала, реализацию связи между CMS, CRM и Data Analitics, а так же все остальное касаемое сайтов, кроме продвижения.

Обращайтесь, я всегда проконсультирую по всем вопросам и помогу подобрать наиболее эффективное решение для Вашего бизнеса. Я занимаюсь созданием сайтов в Новосибирске и в других регионах России, также работаю со странами СНГ. Вы останетесь довольны нашим сотрудничеством

Во время отправки произошла ошибка, пожалуйста попробуйте еще раз через некоторое время
Сообщение отправлено успешно

Телефоны

+7(993) 007-18-96

Email

info@tichiy.ru

Адрес

Россия, г. Москва

Отправляя форму Вы автоматически подтверждаете, что ознакомились и принимаете Политику конфиденциальности сайта

Написать мне
Отправить
Отправляя форму Вы автоматически подтверждаете, что ознакомились и принимаете Политику конфиденциальности сайта
Отправка успешна!
Thank you for your feedback. I will answer you within the next working hours
Отправка не удалась
Во время отправки запроса произошла ошибка. Пожалуйста, подождите и попробуйте снова через некоторое время или свяжитесь со мной