Прикрепление файлов к письму на windows-1251

31 мая, 18:13
Андрей
Андрей
31 мая, 18:13
525
0

Уже достаточно давно в продукте появилось поддержка прикрепления файлов к почтовым событиям.

Прикрепить файл просто: вызываем метод Bitrix\Main\Mail\Event::send, в ключе FILE передаем либо массив ID из базы, либо массив путей. В старом методе CEvent::Send, который по факту уже является оберткой для нового, указываем параметр $files (описан в документации).

При передаче путей, Битрикс предварительно сохраняет файлы в таблицу b_file с помощью CFile::SaveFile. Общая логика такая:

  • Добавляется событие (b_event)
  • Сохраняются файлы в таблицу b_file (в случае указания путей)
  • Добавляется запись в таблицу b_event_attachment, которая содержит ID события (EVENT_ID) и ID файла (FILE_ID).
  • Агент рассылает письма, выбирая эти данные.

Все выглядит отлично, но «счастливые» обладатели сайтов на windows-1251 могут столкнуться с проблемами при прикреплении файлов с русскими именами.

Пусть у нас есть:

  • почтовое событие SOME_EVENT
  • почтовый шаблон для события SOME_EVENT с заранее заполненным полем «Кому»
  • два файла в корне file.jpg и file.jpg.

и мы хотим отправить письмо с этими файлами.

Следующий код успешно отправит письмо с 2 вложениями, но только на кодировке utf-8:

use Bitrix\Main\Mail\Event;

Event::send([ 
    "EVENT_NAME" => "SOME_EVENT",
    "LID" => "s1",
    "C_FIELDS" => [],
    "FILE" => [
        $_SERVER["DOCUMENT_ROOT"]."/файл.jpg",
        $_SERVER["DOCUMENT_ROOT"]."/file.jpg"
    ]
);

С windows-1251, в лучшем случае, в письме придет только один файл.

Необходимо правильно указать путь, так как кодировка сайта у нас windows-1251, а кодировка файловой системы – utf-8.

Полный код будет выглядеть следующим образом:

use \Bitrix\Main\Mail\Event;
use \Bitrix\Main\IO;

Event::send([
    "EVENT_NAME" => "SOME_EVENT",
    "LID" => "s1",
    "C_FIELDS" => [],
    "FILE" => [
        IO\Path::ConvertLogicalToPhysical($_SERVER["DOCUMENT_ROOT"]."/файл.jpg"),
        $_SERVER["DOCUMENT_ROOT"]."/file.jpg"
    ]
]);

Стоит отметить, что Битрикс не выдает вообще никакой ошибки в первом варианте (когда CFile::SaveFile отработал некорректно), а просто заносит в таблицу b_event_attachment в поле FILE_ID значение 0.

C IO\Path::ConvertLogicalToPhysical файл сохраняется корректно.

Вроде бы задача решена. Но если мы попробуем сейчас выполнить этот код, то придет 2 файла:

«file.jpg» - нормальный, а «файл.jpg» с нулевой длиной.

Происходит это из-за бага, который есть внутри ядра. Тикет создан в феврале 2017 с категорией «Ошибки», пока исправления нет. Суть в том, что агент, который отправляет письма производит двойную конвертацию имени файла. Сначала в CFile::MakeFileArray, а затем в классе Bitrix\Main\Mail\Mail:: setAttachment при вызове Bitrix\Main\IO\File::getFileContents.

«Исправляем» это:

  1. Открываем файл /bitrix/modules/main/lib/mail/mail.php
  2. И вносим правки в ядро :), добавляя в метод setAttachment блок исключения:
  3. Было:

    try {
        $fileContent = File::getFileContents($attachment["PATH"]);
    } catch (\Exception $exception) {
        $fileContent = '';
    }
    

    Стало:

    try {
        $fileContent = File::getFileContents($attachment["PATH"]);
    } catch (\Bitrix\Main\IO\FileNotFoundException $exception) {
        try {
            $fileContent = File::getFileContents(\Bitrix\Main\IO\Path::convertPhysicalToLogical($attachment["PATH"]));
        } catch (\Exception $exception) {
            $fileContent = '';
        }
    } catch (\Exception $exception) {
      $fileContent = '';
    }
    

    Т.е. если при попытке получить содержимое файла вывалилось исключение «Файл не найден», пробуем получить содержимое по сконвертированному в обратную сторону имени файла. Теперь все файлы отправляются.

    Андрей
    Автор
    Андрей
Дмитрий Севальнев
Канал про развитие бизнеса
от Дмитрия Севальнева
Перейти
Сергей Просветов
Канал про SEO‑продвижение
от Сергея Просветова
Перейти
Подписывайтесь
на рассылку
Я согласен на обработку
персональных данных

Подписаться


Понравилась статья?
Оставить комментарий

Введено символов: 0 / 1200

Комментариев пока что нет

Наши достижения

Входим в число лучших компаний России в сферах интернет-рекламы и разработки сайтов по результатам самых авторитетных рейтингов

Победитель в номинации «SEO для e-commerce» по итогам WORKSPACE DIGITAL AWARDS 2025
Победитель в номинации «SEO под ключ» по итогам WORKSPACE DIGITAL AWARDS 2024
Рейтинг с самой прозрачной методологией SEO глазами клиентов 2023
SEO глазами клиентов 2023
Рейтинг известности SEO-компаний 2020 по версии SEO-news
SEO-news
Другие статьи автора
Вернуться в раздел
Другие статьи рубрики
Вернуться в раздел
Оставьте заявку

Нужна помощь с сайтом? Заполните форму, и наши менеджеры проконсультируют вас уже сегодня!

* — Поля, обязательные к заполнению.
Получайте полезные письма
Присылаем экспертные исследования и кейсы по SEO и интернет-маркетингу,
а также спецпредложения только для подписчиков!


Оставьте ваш e-mail:*
Я согласен на обработку
персональных данных

Принципиально новые условия сотрудничества в SEO — зарабатываем только вместе!

Уникальный тариф «Оборот», где доход агентства больше не зависит от визитов и позиций вашего сайта, а привязан исключительно к росту оборота вашей компании.

Тариф, который хотели сделать многие, но реализовали только мы.

К тарифу «Оборот»