Давняя головная боль, которую все преодолевают по разному. Я нашел такой вот путь, надеюсь кому-нибудь еще пригодится [spoiler] Итак, небольшой ликбез почему так, а не иначе.
Что дано - после того как отправляется письмо с CEvent::Send() оно на самом деле сначала добавляется в таблицу b_event как событие и сработает на следующем хите (фактически на вашем же) - перед добавлением в таблицу вызывается обработчик OnBeforeEventAdd - после добавления в таблицу (на следующем хите) происходит уже отправка письма; как и что там происходит описывать не буду, потому что туда нам не вклинится - там есть обработчик OnBeforeEventSend, но он вызывается, когда письмо уже формируется, фактически перед отправкой и поздно что-то делать.
Вывод: вклиниться надо в OnBeforeEventAdd.
Скачиваем файл с единственной функцией SendAttache() для отправки нашего письма. Внимание! Функция не предусматривает отправки письма без файла. Складируем ее к себе, подключаем файл (я подключил его в момент отправки письма, чтобы постоянно не копилило).
$event, $lid, $arFields передаются по ссылке - их изменение повлечет изменений изначальных переменных. На этом мы и сыграем далее.
В первой строчку я подключаю тот самый файл. Во второй строчке вызываю функцию из файла (переменные те же, что передаются в обработчик + аттач).
А вот третья строчка это чистой воды танец с бубном. Если этого не сделать, то придет два письма по шаблону. Почему? Потому что после обработчика идет добавление в таблицу b_event (см. выше). Но мы то письмо уже отправили (обращаю внимание, что при отправке нашим способом добавления в таблицу не происходит). Значит нам надо сделать так, чтобы будущее добавление в таблицу не повлекло отправку письма. unset у меня почему-то не сработал, поэтому я просто присвоил null.
Вот собственно и все. Хочу заметить, что если в SendAttache четвертым параметром передать не путь, а массив путей, то к письму приложится несколько аттачей.
В обработчике лишь пример как можно использовать данную функцию. Логика у каждого своя, поэтому я не стал изощряться.
UPD По поводу $event = 'null' пару слов еще. Дело в том, что добавление в таблицу произойдет, но система помаркирует ее как "провал при отправке" и письма не отправится, а через несколько дней запись и вовсе удалится автоматически.
Антон, прошу прощения, взбаламутил воду раньше времени. В общем мне нужно было отправлять логотип сайта в почтовых событиях стандартных, битриксовых, которые выполняются ядром (например при восстановлении пароля и отправке контрольной строки). Суппорт разъяснил, что ядро в этом случае выполняет не CEvent::Send, а CEvent::SendImmediate в котором обработчика OnBeforeEventAdd нет ((( Очень жаль. Остается ждать выхода 10ки, в которой, как обещали на партнерке, будет реализован функционал приаттачивания файлов к почтовым событиям.
Антон, спасибо! Воспользовался :)Есть одно замечание с которым не удалось разобраться - отправка дублирующего сообщения на емейл указанный в "E-Mail адрес или список адресов через запятую на который будут дублироваться все исходящие сообщения". Хотелось бы исключить отправку таких писем с атачем. Сам вызов CEvent::Send() в 4-м параметре передаю "N", но все равно дубль отправляется. Не подскажете как победить этот момент?
Странности были при тестировании данного функционала в тестовом хостинге. Все работало. Но при переносе на рабочий сайт письмо не отправлялось. При этом хостинг уже другой. Заработало при коррекции скрипта mail_attach.php:
$head .= "boundary=\"----".$un."\"".$eol.$eol;
поменяли на:
$head .= "boundary=\"----".$un."\"".$eol;
Разумного объяснения дать не могу. Если у кого есть соображения по этому поводу интересно было бы их услышать
Антон, приветствую. Спасибо за наводку, однако, как только скормили его в IDE получили 3 неопределенных переменных и завязанный на них функционал. Вопрос: нужно ли это?
$cSearch = count($arSearch);
foreach ($arSearch as $id => $key)
{
$strCFields .= substr($key, 1, strlen($key)-2)."=".$arReplace[$id];
if ($id < $cSearch-1)
$strCFields .= "&";
}
// Не определены $arSearch, $arReplace
$head .= "X-MID: $messID.".$arMessTpl["ID"]."(".date($DB->DateFormatToPHP(CLang::GetDateFormat("FULL"))).")".$eol;
// Не определен $messID.
После обновления на 12.0 столкнулась со следующей проблемой - отправляется 2 письма: с вложением и без. Т.е. возможно эвент отправки простого письма не отменяется ($event = 'null'). Можете подсказать, пожалуйста, как исправить данную проблему?
AddEventHandler("main", "OnSendUserInfo", Array("MyClass", "bxModifyRegistretionMails"));
class MyClass
{
function bxModifyRegistretionMails(&$arParams){
/*******************************************/
SendAttache($arParams["EVENT_NAME"], $arParams["SITE_ID"], $arParams, $filePath);
unset($arParams);
}
Письмо с аттачем не получает поля из arParams и как тут отменить письмо стандартное ? А то приходит одно письмо стандартное(неизмененное) и второе с вложением но не подставляются вместо #КОДА# значения .
Кирилл, данное событие не перехватить. Ибо оно улетает сразу, не ложась в базу. Только переопределять custom_mail. Может получится как-то зацепиться за событие OnBeforeEventSend. Но не уверен.
Назар, если это не локальная проблема почтовика, которым открываете eml-файл, и не проблема самого файла, то надо изучать заголовки письма, почему именно проблема, и какая. Удаленно ничего не скажешь абсолютно.
Антон, а как можно реализовать, чтобы на почту приходил не прикрепленный файл, а ссылка на него? Сначала формируется сообщение для email, потом создается элемент, файл прикрепляется к элементу
Можно еще расширить функцию добавив $message_id, чтобы могли отправляться разные шаблоны одного типа.
У меня, кстати на 14.5 null-ы не сработали. Упорно 2 письма уходило, пока я сами шаблоны не сделал неактивными. Событие OnBeforeEventAddHandl при этом срабатывает, а отправка штатными средствами уже - нет.
есть такая особенность, из-за которой я немного подзастрял, не мог понять почему не работает: в методе CEvent::Send в параметре $lid можно передавать как id сайта, так и массив id сайтов. А функция SendAttache в одноименном параметре принимает только id сайта и с массивом не дружит, и ничего не отправляет
Здесь я так понмаю что нужно именно закачивать на сайт файл а потом прописывать пути типа "/readme.html" - а напрямую нельзя отправить файл на почту? без залива на сайт!
Разработчикам Битрикса думаю давно нужно было добавить функционал такого рода в систему. У каждого третьего клиента есть необходимость отправлять данные с аттачем. P.S. За класс огромное спасибо. Будем тестить
в D7 обработчик не будет работать! "Старыми", описанными методами - все ровно пашет, кроме момента определения CHARSET в b_lang - у меня почему-то пусто, хотя настройки сайтов выставлены...
Да и видимо добавили таки возможность слать аттачи
CEvent::Send("EVENT_NAME", SITE_ID, $arEventFields, "Y", "", array($file_id));
// где $file_id - это ID файла из таблицы b_file, файлов может быть несколько
Котов Алексей написал: Да и видимо добавили таки возможность слать аттачи
Не всегда работает, судя по всему, есть баг в ядре, если на кроне какое-то событие почтовое висит, а что-то выполняется на хитах, так как таблица эвентов может быть заблокирована и файлы не приаттачатся.
Можно не отправлять письмо дополнительно с помощью функции, а заполнить параметр $files. Письмо отправится стандартным способом и с вложениями.
function OnBeforeEventAddHandler(&$event, &$lid, &$arFields, &$messageId, &$files, &$languageId)
{
if ($event == "SALE_NEW_ORDER_YANDEX")
{
$files = Array("/readme_1.html","/readme_2.html");
// Вместо относительных путей можно указать ID
}
}
Недавно столкнулся со старой версией битрикса у клиента, нужно было реализовать нечто подобное Если в методе CEvent::Send id сайта передан как массив, то в методе SendAttach нужно поправить выборку при обращении к таблице b_event_message
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».