The last notes
Website hosting
If you are choosing hosting for your project, I recommend Timeweb. Modern infrastructure, a wide range of plans from starter options to high-load VPS, and responsive tech support that actually helps instead of sending template replies. I host some of my own projects there and recommend it to my clients.
Go to site Affiliate link. The price remains the same for you.All English-language materials have been translated fully automatically using the Google service
Testing sending emails
Sending a test email from the console
echo "Test text" | mail -s "Test title" test@test.ru
Checking the operation of the mail function from the PHP Bitrix console
Sending a test email from the console with detailed logging (recommended)
echo -e "To: info@domen.ru\nSubject: Test from msmtp\n\nThis is a test message." | msmtp --debug -a default info@domen.ru
if( mail("test@test.ru", "Subject", "Text") ){
echo 'Успешно отправлено!'; }
else{
echo 'Отправка не удалась!';
}
Checking socket operation
$fp = fsockopen("ssl://smtp.mail.ru", 465, $errno, $errstr, 30);
if (!$fp)
echo "Error: $errstr ($errno)\n";
else
echo "Connected";
fclose ($fp)
Correct msmtp Configuration and Application Password
If you are sure that your configuration file is set up correctly but emails are still not being sent, the reason is most likely the requirement to use an application password.
Let's verify this and send a test email from the console with detailed logging. Do not forget to replace domen.ru with your actual domain.
echo -e "To: info@domen.ru\nSubject: Test from msmtp\n\nThis is a test message." | msmtp --debug -a default info@domen.ru
If you were right and the configuration is accurate, you will most likely see an error like this (or similar) within the response:
535 5.7.0 NEOBHODIM parol prilozheniya https://help.mail.ru/mail/security/protection/external / Application password is REQUIRED
We were right, and we do need an application password. This happens because major email providers have upgraded to a higher security tier and now require you to use an application password instead of your regular account password. To find out how to generate one, please check the official documentation of your email service provider.
This applies to almost all major players in the email service market. However, each provider has its own specific conditions and pricing models.
But even if you have already generated an application password, your emails might still fail to send. For instance, Mail.ru disabled SMTP email sending for external services on their free plans starting from mid-2026. Yes, upgrading to a paid tier is an option — but personally, I prefer using a high-quality free alternative service.
If you run into authorization errors while sending emails via
smtp.mail.ru
(for example, 535 5.7.0 NEOBHODIM parol prilozheniya),
and standard troubleshooting methods do not help, consider using an alternative service like
smtp.bz.
It allows you to send up to 500 emails per day for free, is easy to configure,
and does not require creating application passwords. You only need to specify the
host,
port,
user, and
password
provided in your service dashboard right into your
msmtp config file.
This solution is suitable both for BitrixVM and other systems that utilize SMTP sending. Affiliate link, the price remains the same for you
Checking Bitrix settings
Go to Settings> Product Settings> Mail & SMS Events> Mail Templates and browse through the templates. Make sure that the From field contains #DEFAULT_EMAIL_FROM#
Go to Settings> Product settings> Modules settings> Main module> Mail and SMS in the Email of the site administrator (default sender) enter the correct value of the sender's mail p>
Just in case, you can also specify mail in the E-Mail field of the sales department: along the path Settings> Product settings> Module settings> Online store> Settings p >
Email must match in all of the above cases, plus it must be specified in the msmtp settings
msmtp config for simple submission via mail.ru
account default
logfile /home/bitrix/.msmtp.log
host mail.bitrixsoft.com
port 25
from user@email.com
auth off
msmtp config for simple sending via smtp.bz
account default
logfile /home/bitrix/msmtp_default.log
host connect.smtp.bz
port 587
from no-reply@domain.ru
keepbcc off
auth on
user no-reply@domain.ru
password PASSWORD
tls on
tls_certcheck off
msmtp config for simple submission via smtp mail.ru
account default
logfile /home/bitrix/msmtp_default.log
host smtp.mail.ru
port 587
from no-reply@default.ru
keepbcc off
auth on
user no-reply@default.ru
password default
tls on
tls_starttls on
tls_certcheck off
msmtp config for simple submission via smtp yandex.ru
account default
logfile /var/log/msmtp.log
host smtp.yandex.ru
port 587
from usr@yandex.ru
keepbcc on
auth on
user usr@yandex.ru
password PAss
tls on
tls_starttls on
msmtp config for easy submission via smtp gmail.com
account default
tls on
tls_certcheck off
auth on
host smtp.gmail.com
port 587
user usr@gmail.com
from usr@gmail.com
password yourgmailPass
msmtp config for easy shipping via smtp timeweb.ru
# smtp account configuration for default
account default
logfile /home/bitrix/msmtp_default.log
host smtp.timeweb.ru
port 465
from YOUR_EMAIL
aliases /etc/aliases
keepbcc off
auth on
user YOUR_EMAIL
password YOUR_PASSWORD
tls on
tls_starttls off
tls_certcheck off
Getting the list of letters
select * from b_event
where event_name like 'SALE_NEW_ORDER'
order by date_insert desc
Values of the status of sending letters in the column SUCCESS_EXEC
‘Y’ — означает успешная отправка;
‘N’ или 0 — письмо не отправлено;
‘F’ — ошибка
How to attach a file to a standard Bitrix email template
$FILES = [];
foreach ($_FILES as $file)
if (!empty($file['tmp_name'])
$FILES[]=CFile::SaveFile($file);
CEvent::Send('SUBSCRIBE_CONFIRM', SITE_ID, $eventFields, 'Y', '', $FILES);
Script for debugging SMTP email sending
// Настройки подключения
$smtp_host = 'smtp.yandex.ru';
$smtp_port = 587; // Обычно 587 для TLS/STARTTLS или 465 для SSL
$smtp_user = 'EMAIL';
$smtp_pass = 'APP_PASSWORD';
$timeout = 10;
function parse_smtp_response($stream, $expected_code) {
$response = '';
while ($line = fgets($stream, 515)) {
$response .= $line;
// Если 4-й символ пробел, значит это последняя строка ответа сервера
if (isset($line[3]) && $line[3] == ' ') {
break;
}
}
$code = substr($response, 0, 3);
if ($code != $expected_code) {
throw new Exception("Неожиданный ответ сервера: " . trim($response));
}
return $response;
}
try {
// Подключение к серверу
$socket = stream_socket_client("tcp://$smtp_host:$smtp_port", $errno, $errstr, $timeout);
if (!$socket) {
throw new Exception("Ошибка подключения ($errno): $errstr");
}
// Читаем приветствие (ожидаем код 220)
parse_smtp_response($socket, '220');
// Приветствуем сервер (EHLO)
fwrite($socket, "EHLO localhost\r\n");
parse_smtp_response($socket, '250');
// Активация шифрования (STARTTLS) для порта 587
// Если вы сразу подключились на порт 465, этот шаг нужно пропустить
fwrite($socket, "STARTTLS\r\n");
parse_smtp_response($socket, '220');
// Включаем шифрование на существующем потоке
if (!stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
throw new Exception("Не удалось запустить TLS шифрование.");
}
// Повторное приветствие EHLO уже внутри защищенного канала
fwrite($socket, "EHLO localhost\r\n");
parse_smtp_response($socket, '250');
// Аутентификация (LOGIN)
fwrite($socket, "AUTH LOGIN\r\n");
parse_smtp_response($socket, '334'); // Сервер просит логин
// Отправляем логин в Base64
fwrite($socket, base64_encode($smtp_user) . "\r\n");
parse_smtp_response($socket, '334'); // Сервер просит пароль
// Отправляем пароль в Base64
fwrite($socket, base64_encode($smtp_pass) . "\r\n");
parse_smtp_response($socket, '235'); // Код 235 означает успешный вход!
echo "Успех! Подключение и аутентификация на SMTP-сервере прошли корректно.";
// Закрываем сессию
fwrite($socket, "QUIT\r\n");
fclose($socket);
} catch (Exception $e) {
echo "Ошибка проверки SMTP: " . $e->getMessage();
if (isset($socket) && is_resource($socket)) {
fclose($socket);
}
}
Script for sending mail via phpMailer
Install composer
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === 'e0012edf3e80b6978849f5eff0d4b4e4c79ff1609dd1e613307e16318854d24ae64f26d17af3ef0bf7cfb710ca74755a') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
Installing phpMailer
composer require phpmailer/phpmailer
If the composer command is not found, then we try to install it globally
curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
Add to init.php
require '/var/www/YOUR_SITE/vendor/autoload.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)
{
$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();
$fields = $arFields;
AddMessage2Log($arFields, "arFields");
if(isset($recordset[0]['MESSAGE'])){//Проверяем есть ли шаблон
$mask = $recordset[0]['MESSAGE'];
$subject = $recordset[0]['SUBJECT'];
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\#~', COption::GetOptionString("main", "site_name", $GLOBALS["SERVER_NAME"]), $mask);
$mask = preg_replace('~\#SERVER_NAME\#~', COption::GetOptionString("main", "server_name", $GLOBALS["SERVER_NAME"]), $mask);
$mask = preg_replace('~\#DEFAULT_EMAIL_FROM\#~', COption::GetOptionString("main", "email_from", "admin@".$GLOBALS["SERVER_NAME"]), $mask);
$subject = preg_replace('~\#SITE_NAME\#~', COption::GetOptionString("main", "server_name", $GLOBALS["SERVER_NAME"]), $subject);
$subject = preg_replace('~\#SERVER_NAME\#~', COption::GetOptionString("main", "server_name", $GLOBALS["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_RAW'])){
if (filter_var($fields['EMAIL_RAW'], FILTER_VALIDATE_EMAIL)) {
$email = $fields['EMAIL_RAW'];
}
}
if(isset($fields['EMAIL_BUYER'])){
if (filter_var($fields['EMAIL_BUYER'], FILTER_VALIDATE_EMAIL)) {
$email = $fields['EMAIL_BUYER'];
}
}
if(isset($fields['EMAIL_TO'])){
if (filter_var($fields['EMAIL_TO'], FILTER_VALIDATE_EMAIL)) {
$email = $fields['EMAIL_TO'];
}
}
if(!$email){
$email = 'default@email.ru';
}
if($email && filter_var($email, FILTER_VALIDATE_EMAIL)){
$cl = new OnBeforeEventAddClass;
if($cl->custom_mail($email, $subject, $mask,'','')){//Отправляем письмо
//AddMessage2Log($event, "Сообщение было отправлено");
}else{
//AddMessage2Log($event, "Ошибка. Сообщение отправлено не было");
}
}else{
//AddMessage2Log($event, "Ошибка. Почта не найдена. Почта:");
}
return false;
}else{
//AddMessage2Log($event, "Ошибка. Нет тела письма");
}
}else{
//AddMessage2Log($event, "Ошибка. Не найден шаблон письма");
}
}
public function custom_mail($to, $subject, $message, $additionalHeaders = '', $additional_parameters)
{
// Instantiation and passing `true` enables exceptions
$mail = new PHPMailer(true);
$mail->IsSMTP(true); // enable SMTP
$mail->SMTPDebug = 3; // debugging: 1 = errors and messages, 2 = messages only
$mail->SMTPAuth = true; // authentication enabled
$mail->SMTPSecure = 'ssl'; // secure transfer enabled REQUIRED for GMail
$mail->Host = 'smtp.gmail.com';
$mail->Port = 465; // set the SMTP port for the GMAIL server
$mail->Username = 'email'; // SMTP username
$mail->Password = 'password'; // SMTP password
$mail->CharSet = 'UTF-8';
$mail->addAddress($to);
$mail->setFrom('default@email.ru');
//Set the subject line
$mail->Subject = $subject;
//Read an HTML message body from an external file, convert referenced images to embedded,
//convert HTML into a basic plain-text alternative body
$mail->msgHTML($message);
//Replace the plain text body with one created manually
$mail->AltBody = 'This is a plain-text message body';
$d_message='';
//preg_match('/From: (.+)\n/i', $additionalHeaders, $matches);
//list(, $from) = $matches;
$from = 'admin@YOUR_SITE';
$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->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';
if(!$mail->send()) {
AddMessage2Log($mail->ErrorInfo, "Mailer Error");
return false;
} else {
return true;
}
}
}
//Перехват письма непосредственно перед отправкой
AddEventHandler('main', 'OnBeforeEventSend', Array("OnBeforeEventSendClass", "my_OnBeforeEventSend"));
class OnBeforeEventSendClass
{
function my_OnBeforeEventSend($arFields, $arTemplate)
{
//получим сообщение
}
}
To send emails using phpMailer via smtp.mail.ru , the config should look like this:
$mail = new \PHPMailer\PHPMailer\PHPMailer(true);
$mail->IsSMTP(true); // enable SMTP
$mail->SMTPDebug = 1; // debugging: 1 = errors and messages, 2 = messages only
$mail->SMTPAuth = true; // authentication enabled
$mail->SMTPSecure = 'ssl'; // secure transfer enabled REQUIRED for GMail
$mail->Host = 'ssl://smtp.mail.ru';
$mail->Port = 465; // set the SMTP port for the GMAIL server
$mail->Username = 'USER_NAME'; // SMTP username
$mail->Password = 'USER_PASSWORD'; // SMTP password
Debug with AddMessage2Log
In the dbconn.php file, add the line define ("LOG_FILENAME", $ _SERVER ["DOCUMENT_ROOT"]. "/ log.txt");
the server sent an empty reply in the log msmtp
Add to configг
tls_starttls off
cannot connect to localhost, port 25: Connection refused
After installing a clean Bitrix environment, I often see this error. To fix - use postfix
yum install postfix
service postfix start
chkconfig postfix on
Dealing with bugs
If you are trying to send mail via smtp by Google and you get an error like SMTP connect () failed , then go to your Google account from which sending mail. Open the settings, go to the Security tab, find the item "Unreliable applications that have access to your account", go to it and allow access to unsafe applications ( link )
Fighting the Mail command not found
yum install sendmail
yum -y install mailx
service sendmail start
Transfer of agents to CZK
Editing the file /bitrix/php_interface/dbconn.php
Sometimes you need to comment out the cron support connection strings
define('BX_CRONTAB', true);
define('BX_CRONTAB_SUPPORT', true);
Go to Preferences> Tools> PHP Command Line and execute the following code:
COption::SetOptionString("main", "agents_use_crontab", "Y");
echo COption::GetOptionString("main", "agents_use_crontab", "N");
Let's open the crones settings
crontab -u bitrix -e или crontab -e
Let's add an entry:
*/1 * * * * php -f /home/bitrix/www/bitrix/modules/main/tools/cron_events.php >/dev/null 2>&1
Restarting cron
systemctl restart crond.service
The cron settings are well described in documentation
& nbsp;
You can study the issue in more detail in the official documentation:
Comments