Bitrix does not send mail or gets into spam
Rus
Eng
Битрикс не отправляется почта или попадает в спам
I solve complex technical challenges for Bitrix and 1C—ranging from auditing existing code to website development and configuring complex integrations—with a guarantee of results.
Recommended

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.

Attention: A free alternative to SMTP email delivery services

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

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

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

error
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:

Aleksandr Tichiy
Author

Aleksandr Tichiy

Fullstack developer · 1C-Bitrix

I build and modernize online stores and corporate portals on 1C-Bitrix. Integrations with 1C, high-load performance, 152-FZ compliance. Writing about architecture and e-commerce.


Comments

There are no comments yet, you can be the first to leave it

Leave a comment

The site uses a comment pre-moderation system, so your message will be published only after approval by the moderator

You are replying to a user's comment

Send

FEEDBACK

Email me

Please message me to discuss the task. I work remotely and officially (as a self-employed professional); my hourly rate is 1,800 RUB, and I can dedicate 3–4 hours a day to the project. I respond quickly, and the consultation is free.

An error occurred while sending, please try again after a while
Message sent successfully

Phones

+7(993) 007-18-96

Email

info@tichiy.ru

Address

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

By submitting the form, you automatically confirm that you have read and accept the Privacy Policy site