PHP mail: отправка html-письма с вложением

Уууфффффф… Ненавижу разбираться в чужих скриптах, особенно когда они были написаны в 2001-2003 годах.

Дали мне тут на “переделать” сайт, который был написан на PHP3 7 лет назад. Переделать надо было его “под PHP5”. По сути, главный геморой - обработка отправляемых данных - POST, GET, SESSION, FILES, т.к. в то время активно использовали фичу register_globals=on.

Сайт имеет довольно развитую систему администирования пользователей - помимо стандартных добавления/удаления/редактирования/привязки к разл. компаниям/етс.. имеется самописный продвинутый сервис рассылок. И я с этим сервисом честно говоря заебался, споткнувшись о тему, которую решил вынести в сабж данного поста.

Там суть в том, что в этой админке можно делать рассылку с вложениями (различные приглашения, рассылка обновленных прайсов и тд.), и соответственно все письмо полностью генерится на PHP. Пока разбирался, стал в этом деле гуру :)

Ниже пример html-письма, где присутствует html + пара рисунков к нему, а также аттач в виде zip-файла. Я заранее раскрасил его для лучшей наглядности, а также не поленился и нарисовал комментарии к нему! (под картинкой ссылка на их показ).

комментарии к примеру

В разделении письма на части учавствуют несколько полей заголовка.

  • MIME-Version: 1.0 - указывает стандарт, по которому формируется тело многосоставного письма (как у нас). Пока другого стандарта нет, поэтому пишем 1.0, а само поле пишем в основном заголовке письма.

  • Content-type - тип данных. Если письмо составное, то нужно присвоить этому полю значение “multipart/mixed”. Сразу после него нужно объявить маркер - boundary - (помечен красным цветом), который будет разделять наше mixed-содержимое письма на части. По сути части - это “файлы” в письме. В html-письме файлом также является сам html. Если бы это было обычное text-письмо без вложений, то маркер не нужен. Маркер - некая уникальная последовательность, которая не должна встречаться в теле письма. В нашем примере выбраны не совсем удачные маркеры, но это в угоду наглядности. При создании письма на сервере следует сгенерировать случайную последовательность символов.

Обратите внимание далее на пустые строки между частями - их нужно делать обязательно. Давайте пройдемся далее по всему примеру этого письма:

  • После “главного” заголовка идет маркер, который разделяет файлы (html и зипованный файл). Перед каждым маркером надо ставить два дефиса: ”—”, так мы показываем, что начинается следующая часть.

  • Затем идет заголовок части для html. Он также имеет тип данных multipart/mixed, т.к. в html входит 2 картинки. И также нужно придумать еще один, внутренний для html, маркер (помечен синим цветом), который будет разделять на части чистый html, первую и вторую картинки.

  • После синего маркера для объявления новой части - чистого hml, мы пишем к нему заголовок. Теперь уже тип данных text/html, там же указываем кодировку. Затем идет тело голого html

  • Опять указываем синий маркер для границы между частями и пишем заголовок и тело первой картинки. Тип данных, имя, тип кодировки, после чего - сама картинка в текстовом представлении. Аналогично вставляется вторая картинка. Между картинками - маркер синего цвета

  • Все, часть под названием html мы описали, теперь надо ее “закрыть”. Делается это указанием маркера и после него установкой тех самых двух дефисов: ”—”.

  • Теперь идут две оставшиеся части “первого порядка” :) Тут уже попроще, устанавливается начальный маркер красного цвета, пишем заголовок для zip-файла и его тело, представленное в текстовом виде. Последний штрих - закрывающий маркер, объявляющий об окончании письма.

Вот и все, получилось, что все наши файлы, картинки и аттачи влезли в один большой кусок текста, который мы отправляем обычной функцией mail() в теле обычного письма.

Архив обсуждения

Исторические комментарии сохранены из старого блога. Это архив, новые комментарии не добавляются. Всего: 2.

  1. netgoblin

    здрасте.
    я начинающий веб-программист, но имею кое-какой опыт. вот только с рассылкой столкнулся впервые (пишу с нуля). как использовать все выше описанное. хочу отправить подготовленную html-страницу + вложение типа PDF.

    до вложений пока не дошел, сама страница выводится не корректно - не парсятся теги. видимо, я неправильно вывожу - пытаюсь сделать через кеш:
    ob_start();
    include 'email_template.php';
    $email_text = ob_get_contents();
    ob_end_clean();
    mail($email, 'Hello', $email_text);

    подскажете что-да-как?

  2. netgoblin

    =) только написал Вам как сразу нашел решение парсинга HTML-тегов - в mail() не указал заголовок.
    НО всё равно жду ответа о том как использовать выше описанный код.