Уууфффффф…. Ненавижу разбираться в чужих скриптах, особенно когда они были написаны в 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() в теле обычного письма.