В Битриксе, начиная с версии 7.1.3, появилась возможность переопределить стандартный механизм отправки почты.
Когда может быть полезен такой финт ушами? К примеру, когда в конторе есть какой-то централизованный сервис отправки почты, который должны использовать все приложения (SMTP-сервер на другой машине, веб-служба, что угодно). Для примера, рассмотрим GMail в качестве такого сервиса.[spoiler]
Механика простая: везде, где должна вызываться функция mail(), вызывается bxmail(). А уже в этой функции, перед вызовом стандартной функции mail(), Битрикс проверяет, определена ли функция custom_mail() и, если да, вызывает её вместо mail(). Соответственно, чтобы переопределить механизм отправки, нужно всего лишь написать функцию custom_mail() (в /bitrix/php_interface/init.php, к примеру (если хотим, чтобы такой механизм отправки действовал для всех сайтов на данной копии)).
Приступим к делу! Лично мне для отправки почты через GMail ближе всего Zend_Mail, но... Ни эта библиотека, ни другие не позволяют установить "сырые" заголовки для письма. А разбирать $additional_headers мне что-то не очень хочется. Следовательно, выбор перепадает на PEAR::Net_SMTP, как на механизм прямой работы с SMTP-сервером.
Итак, ближе к коду!
require_once 'Net/SMTP.php';
/**
* Отпраляем почту через SMTP-сервер GMail (пользователь: user@gmail.com).
*
* @see CEvent::HandleEvent()
* @see bxmail()
*
* @param string $to Адрес получателя.
* @param string $subject Тема.
* @param string $message Текст сообщения.
* @param string $additionalHeaders Дополнительные заголовки передаются Битриксом почти всегда ("FROM" передаётся здесь).
*
* @return bool
*/
function custom_mail($to, $subject, $message, $additionalHeaders = '')
{
/*
* Настройки можно (нужно) вынести в админку, но это уже домашнее задание :)
*/
$smtpServerHost = 'ssl://smtp.gmail.com';
$smtpServerHostPort = 465;
$smtpServerUser = 'user@gmail.com';
$smtpServerUserPassword = 'password';
if (!($smtp = new Net_SMTP($smtpServerHost, $smtpServerHostPort))) {
return false;
}
if (PEAR::isError($e = $smtp->connect())) {
return false;
}
if (PEAR::isError($e = $smtp->auth($smtpServerUser, $smtpServerUserPassword))) {
return false;
}
preg_match('/From: (.+)\n/i', $additionalHeaders, $matches);
list(, $from) = $matches;
$smtp->mailFrom($from);
$smtp->rcptTo($to);
/*
* Получаем идентификатор конца строки у Битрикса.
*/
$eol = CAllEvent::GetMailEOL();
$additionalHeaders .= $eol . 'Subject: ' . $subject;
if (PEAR::isError($e = $smtp->data($additionalHeaders . "\r\n\r\n" . $message))) {
return false;
}
$smtp->disconnect();
return true;
}
Вынесение настроек в админку, создание статического объекта соединения (чтобы не тратить время при отправке множества писем за раз) — это всё задания на дом
Руслан Хаитов, стоит использовать правильный вариант (MailChimp, SendGrid). Тем более, что установка там такая же по сложности + бесплатные тарифы даже есть.
Майоров Федор, некоторое время пытался вкурить, в чем же фишка этой магической строки. Пока не дошло, что для phpMailer надо продублировать заголовки из $additional_headers. У меня в итоге вот такой вариант получился. Корректно шлет html и текст, с аттачами и без них. https://gist.github.com/igorbarkowsky/...833838fea5
function custom_mail ($to, $subject, $message, $additional_headers, $additional_parameters)
{
/*\AddMessage2Log(
'To: '.$to.PHP_EOL.
'Subject: '.$subject.PHP_EOL.
'Message: '.$message.PHP_EOL.
'Headers: '.$additional_headers.PHP_EOL.
'Params: '.$additional_parameters.PHP_EOL
);*/
require_once $_SERVER['DOCUMENT_ROOT'].'/vendor/autoload.php';
$to = str_replace(' ','',$to);
$mail = new PHPMailer;
$mail->CharSet = 'UTF-8';
$address = explode(',', $to);
foreach ($address as $addr)
$mail->addAddress($addr);
// Просматриваем заголовки на предмет аттачей
$headers = explode("\n", $additional_headers);
// Определить аттачи легко - передается сепаратор таким вот образом
$attachHeader = 'Content-Type: multipart/mixed; boundary=';
foreach( $headers as $h )
{
// Если есть заголовок с ограничиителем
if( stripos($h, $attachHeader) === 0 )
{
// Вытаскиваем значение сепаратора
$bndr = substr($h, strlen($attachHeader));
$bndr = trim($bndr, '"');
// И дублируем его же, но в свойство phpMailer.
$mail->ContentType = 'multipart/mixed; boundary="' . $bndr . '"';
// I know its dirty hack
break;
}
}
if (substr_count($message, "Content-Type: text/html"))
{
// $mail->Encoding = '8bit';
}
else
{
// $mail->Encoding = '8bit';
//$mail->isHTML(true); // Set email format to HTML
}
$mail->Subject = $subject;
$mail->Body = $message;
if( defined('PROJECT_SMTP_HOST') )
{
$mail->IsSMTP();
$mail->SMTPDebug = defined('PROJECT_SMTP_DEBUG_LEVEL') ? PROJECT_SMTP_DEBUG_LEVEL : 0;
$mail->Host = PROJECT_SMTP_HOST;
$mail->SMTPAuth = true; // enable SMTP authentication
$mail->Username = PROJECT_SMTP_USERNAME;
$mail->Password = PROJECT_SMTP_PASSWORD;
$mail->From = PROJECT_SMTP_FROM;
$mail->FromName = PROJECT_SMTP_FROMNAME;
$mail->SMTPSecure = PROJECT_SMTP_SECURITY; // "tls" or "ssl"
$mail->Port = PROJECT_SMTP_PORT;
//HACK: Dirty hack! if ssl not configured at hosting
$mail->SMTPOptions = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
),
);
}
if( !$mail->send() )
{
\AddMessage2Log('Mailer Error: ' . $mail->ErrorInfo);
return false;
}
return true;
}
Чуев Василий, нет особой разницы, с помощью чего вы шлете почту со своего сервера. В спам оно попадает, потому что гмайл видит, что вы отправили почту не с сервера с доменным именем вашего сайта. А с некоего технического домена. Тут вам надо бороться именно с гмайлом:) И в первую очередь, конечно надо добавить для домена вашего сайта spf-записи, типа таких
В этом случае почтовый сервер яндекса, который по факту и занимается доставкой вашей почты на адреса реципиентов, начнет воспринимать ваш сервер как доверенный и будет помечать в заголовке письма, что оно отправлено с разрешенного сервера.
Ну а если эта запись не поможет против гмайла, то есть еще такой рецепт:
v=spf1 ip4:тут.айпи.вашего.сайта a mx include:_spf.google.com ~all
К слову сказать, у вас в настройках яндекс.почты опечатка
Добрый день. Запутался маленько, получается с помощью данного механизма можно разделить почту по типам. В стиле информация о задачах с 1 почты, информация о событиях календаря с другой?
Добрый день. В чем суть проблемы: Битрикс умеет отправляет почту через php функцию mail(), которая в свою очередь использует настройку PHP sendmail_path.
Можно задать отправку через консольный клиент msmtp, либо через локальный smtp сервер (postfix, exim, sendmail и так далее). Мы будем отправлять через msmtp, настроенный на отправку через Яндекс Почту.
При отправке писем Битрикс формирует почтовые заголовки, в частности From, исходя из настроек в админке, в главном модуле. При этом имя пользователя при авторизации на почтовом сервере и в заголовке From должно совпадать. При одном сайте/одном домене проблем нет. При нескольких отдельных сайтах/доменах тоже проблем нет.
В конфиге msmtp прописывается почтовый аккаунт для каждого сайта и в админке соответствующего сайта можно указать какой аккаунт из конфига использовать.
Но несколько сайтов/доменов, работающих на многосайтовости, то есть общем ядре и значит админке, не позволяют использовать такой способ.
Единственный вариант, который я нашел, это использовать возможность Битрикса по переопределению функции отправки почты и создания custom_mail(), которая в зависимости от сайта/домена будет подставлять соответствющий аккаунт при вызове msmtp.
Зарипов Данис, да, работает, настроил отправку почты через Яндекс по данной инструкции.
Есть другая проблема: при отправке почты сразу нескольким получателям почта уходит только на первый указанный адрес, именно на первый, а не на какой-то особенный из списка. Отправляем на "test1@test.ru,test2@test.ru" - придет только на test1, отправляем на "test2@test.ru,test1@test.ru" - придет только на test2. В Яндекс уже обращался, они не видят проблем на своей стороне, может быть кто-то знает с чем это может быть связано?
Постников Алексей, "В конфиге msmtp прописывается почтовый аккаунт для каждого сайта и в админке соответствующего сайта можно указать какой аккаунт из конфига использовать." Помогите разобраться. Коробочная версия CRM "1С-Битрикс24: Корпоративный портал 250". CRM сайт - s1. Все работает. Уведомления отправляются от email админа (adminS1crm@yandex.ru). После добавления второго сайта - s2 и изменения почты E-Mail отдела продаж в "Рабочий стол - Настройки - Настройки продукта - Настройки модулей" на свой (otdelProdazhS2@yandex.ru) вместо email админа (adminS1crm@yandex.ru), перестали приходить уведомления о заказах на сайте S2. Можно это решить прописав в конфиге msmtp аккаунт для сайта - s2. Сейчас прописано для сайта Default. В консоли настройки BitrixVM отображается только один сайт.
Можно ли это использовать, чтобы отправлять почту не через один ящик как сейчас, а напрямую? Наверное, надо как-то определить ящик отправитель и подставить соответствующие ему параметры авторизации $smtpServerUser = 'user@gmail.com'; $smtpServerUserPassword = 'password'; Правильно?
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».