Статьи
Портфолио
Друзья
Контакты

Последние статьи

06.07.2010 Memcache и Zend: у Вас "падает" Memcache? 4 коммент.

06.07.2010 Collabtive - web-based project management software 2 коммент.

03.06.2010 Ускоряем ZF-проекты: автолоад и сборка в один файл 2 коммент.

Все

Категории

PHP 2 стат.

Zend Framework 25 стат.

Javascript 3 стат.

Другое 12 стат.

Книги 1 стат.

Украина 1 стат.

Все

RSS

Статьи

Комментарии

Портфолио

Облако тегов

программирование  Программы  портфолио  php  zend framework  Zend_Db  Smarty  Zend_Form  паттерны  javascript  niceforms  jQuery  Zend_Mail  веб  Google  Zend_Rest  Zend_View_Helper  zend casts  Zend_View  Zend_Layout  speedUp  интернет  Загрузчик фотографий  Flash  ВКонтакте  zend  localization  zend_translate  gettext  антон шевчук  подарки  Я читаю  Книги  sphinx  релизы 

Все

Реклама



Статистика



Rambler's Top100

Главная > Статьи > Zend Framework > Zend_Mail. Массовые рассылки, кодировки, вложения
26.12.08 Zend_Mail. Массовые рассылки, кодировки, вложения

Здравствуйте, дорогие читатели. Решил поведать Вам о своих проблемах с Zend_Mail и поделиться их решением.

 

Программировал как-то я уведомления о новых комментариях на почту. Использовал Zend_Mail и натолкнулся на целую кучу проблем связанных с этим. Вот они:

  1. Как организовать мгновенные массовые рассылки?
  2. Проблемы с кодировками писем;
  3. Проблемы с вложениями в письмах;

Давайте вместе разложим все по полочкам и решим эти проблемы. Итак, поехали!

 

 

Быть или не быть?


 

Для реализации рассылок о новых комментариях к статьям на почту, я поставил себе такие задачи:

  1. После добавления комментария, человек, пожелавший подписаться на рассылку, заносится в БД;
  2. Далее происходит выборка подписчиков и мгновенная рассылка комментария (тут возник вопрос: как сделать это, чтобы отправитель комментария не чувствовал задержек при рассылке?);
  3. Письма должны быть в UTF-8 (вопрос: почему на почту приходят крякозябры?);
  4. Нужно красиво оформить содержимое письма (вопрос: а как вставить картинку в письмо и вообще красиво оформить его?).

Почтовый ящик

 

Первое, не относится к теме поста, поэтому рассматривать этот пункт не буду. Так что сразу перейдём ко второму.

 

Для мгновенной рассылки нужно использовать Zend_Mail_Transport_Smtp. Такое решение является самым быстрым из доступных на сегодняшний день, тем более что такой способ рассылки более гибче в плане настроек. Пример использования далее в статье.

 

 

Кодировки писем - решаем все вопросы


 

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

 

Когда мне пришлось решать вопросы с кодировками в Zend_Mail, я много чего перечитал, пересмотрел и обсудил с людьми. Поняв что готового решения мне не найти – начал искать сам и нашел!

 

ЛаптопНекоторые программисты высказывали мнение, что проблема с кодировками в письмах возникает из-за того, что почтовые клиенты не поддерживают эти кодировки. В частности нарекали на то, что кодировку UTF-8 корректно воспринимают единицы почтовых клиентов. Откровенно Вам скажу, что всё это выдумки тех, кто не справился с задачей.… Когда я решил все вопросы с кодировками - лично убедился в этом. Правы были те, кто говорил, что собака зарыта в Zend_Mail.

 

Дело в том, что если при отправке письма указать кодировку и кинуть тексты в этой кодировке, то письма отображаются нормально, но кроме заголовков. Я долго искал решение проблемы. Детально ознакомившись со спецификацией RFC 1522, которой руководствуется Zend_Mail, я понял, что Zend_Mail не правильно разбивает заголовки, просто символом перевода строки, пользуясь константой Zend_Mime:: LINELENGTH (т.е. вставляет символ перевода строки через 72 символа). Благодаря SMTP заглушке, я смог увидеть такую нездоровую вещь и начал уже работать в конкретном направлении.

 

Я нашел метод, в котором идет работа с заголовками в Zend_Mail. И увидел, что переписав данный метод, вполне реально избавится от неверной разбивки на строки. Я унаследовал класс Zend_Mail и просто переписал нужный метод, поправив в нём все необходимое. Для понимания кода и для того, чтобы обойтись без лишних объяснений, я хорошо задокументировал класс.

 

Итак, смотрим:

Немножко обьясню. В соответсвии со спецификацией RFC 1522, заголовок должен рабиваться на строки по такому правилу: каждая новая строка, должна быть разделена символом перевода строки и пробелом, после чего, формирование строки должно начинаться с указания кодировки (т.е. предыдущая строка закрывается символом ?=, а новая начинается после символа перевода строки, пробела, и например, такой строчки =?UTF-8?Q?).

 

Каждая строка заголовка должна раделяться символом перевода строки, пробелом и иметь такой формат:

 

=?кодировка?Q?значение?=

 

Теперь при использовании выше приведенного класса, строка "Комментарий к статье "Практическая реализация паттерна Singleton на PHP"" превратится в:

После того, как Вы начнете использовать данный класс проблем с крякозябрами в заголовках быть не должно. Этот фикс исправляет все проблемы в HTML-письмах и в обычных текстовых рассылках.

 

 

Аттачи (вложения файлов в письмо)


Почтовая марка

 

Также мне пришлось разобраться и с вложениями в письмах, например, картинки. Мне советовали с этим не заморачиваться и грузить картинку просто прописав на неё ссылку, но такой способ, увы, не катит. Почему? Дело в том, что некоторые почтовые клиенты блокируют загрузку файлов с внешних серверов и такой способ не надёжный, поэтому я решил, что нужно создавать вложение.

 

Приступим. Чтобы создать вложение в Вашем письме необходимо:

  1. Считать файл;
  2. Преобразовать его в бинарную строку;
  3. Закодировать;
  4. Добавить в письмо;

Большинство этих пунктов решает класс Zend_Mime_Part. Вам только нужно будет считать файл, и задать параметры для вложения.

 

Приведу пример создания вложения и добавления его в письмо. Код хорошо документирован, поэтому, я считаю, лишних объяснений не нужно.

Обратите внимание на то, что я указал тип контента не «image/gif», а «application/octet-stream». Я сделал это потому, что некоторые почтовые клиенты отображают картинку в конце письма, а ведь нам нужно просто вложить файл и показать его в нужном месте, а не где захочет почтовик, верно?

 

Теперь использовать вложенный элемент очень просто. Как вы можете увидеть, я указал свойству id экземпляра объекта Zend_Mime_Part определённый идентификатор. Теперь, когда Вам надо вставить картинку в нужном месте вы можете написать, например:

Видите, как всё просто?

 

 

А теперь все вместе!


 

В качестве итога, я хочу показать Вам полный пример такой почтовой рассылки:

 

Надеюсь, Вам будет полезна такая информация. Все возражения, пожелания, замечания как всегда жду в комментариях.

 

P.S. Счастливых Вам новогодних праздников!

Теги:  zend framework, php, программирование, Zend_Mail

Другие категории:

■ PHP ■ Zend Framework ■ Javascript ■ Другое ■ Книги ■ Украина
Комментарии к статье
  Юра

30.01.09 00:10:53

Где ж Вы раньше были?

Пол месяца назад выслал к 700 пользователям e-mail с заголовком длиннее чем 72 знака ...Плачет

Хорошо что с работы не выгнали...

Спасибо большое за статью.

  illusive

30.01.09 11:38:37

@Юра:

Пожалуйста.

Кстати в ZF уже сделали фикс этой баги. В следующем релизе таких проблем быть не должно.

  roma

30.01.09 11:39:52

спасибо!!! Пол инета облазил, нашел :)

  illusive

30.01.09 11:46:15

Пожалуйста!

  illusive

30.01.09 12:05:43

К сожелению обнаружил, что это решение не везде работает Хмурый, появляются левые знаки...

Кажется веб-мейлы работают не так, как требует этого стандарт RFC1522

В любом случае, письма, которые генерит мой патч, четко соответсвуют стандарту RFC1522 (смотрел через SMTP-заглушку) Невинность

  Celdweller

30.01.09 12:08:51

Спасибо. Хорошая статья. Так держать!

  Ghost

10.03.09 16:15:47

в таком варианте бьются некоторые символы

я предлагаю кодровать в base64

что-то типа такого у меня получилось (с ним символы не бьются)

  illusive

11.03.09 12:21:38

@Ghost

Спасибо за предложеный вариант. На досуге посмотрю и отпишу свои мысли.

 

P.S. Для вывода програмного кода, пользуйтесь, пожалуйста, кнопкой "вставка кода".

  NorthFace

01.04.09 14:33:09

или второй вариант:

  illusive

03.04.09 16:41:01

Спасибо за Ваше решение. Я обязательно его опробую и отпишусь

  MaxNag

06.04.09 15:23:46

Хорошая статья!!! Спасибо, очень пригодилась.

Позволю себе заметить, что вы не раскрыли полностью второй вопрос. Дело в том, что если у вас подписчиков 1000 чел, то тут надо либо через крон, либо какого-то демона. Просто так с браузера не получить, зависате.

Что вы можете порекомендовать?

Мои решения следующие.

  1. Рассылку с юзерами пишем в БД с пометкой не отправлено
  2. Начинаем отправку, при удаче пишем - отправлено
  3. Скрипт запускаем по крону

Минусы

  • не все хостеры разрешат дергать скрипт каждые 5 минут
  • не все хостеры разрешает делать бесконечное число заданий на крон

Плюсы

  • нет ограничения на работу скрипта
  • юзер ничего не замечает

Можно еще сделать (для админа) страницу которая будет отправлять по 10 писем, потом отдых и JS запускает заново, пока все письма не отправятся....

Еще раз повторюсь, раз Вы написали статью, значит нашли пути решения, если можете поделитесь Обалдел

СПАСИБО.

 

  Андрей

26.08.09 18:45:37

ксожалению при использовании вашего класса мэйл.ру отображает какую то фигню

  illusive

30.08.09 06:42:02

Я тоже это заметил - есть определенные проблемы. Не знаю, я вроде бы получаю результат описанный в RFC 1522. Тогда могу предложить другой вариант, в последних версиях ZF он отлично работает:

  Snowcore

08.12.09 15:44:58

Классная статья, спасибо. А мне недавно приходилось отправлять почту при помощи Zend_Mail через GMail SMTP.

Оставить свой комментарий

 
Статьи | Портфолио | Друзья | Контакты
Идея и мозги: Васильев Андрей © 2008-2010 Web-Blog Кисточка и фантазия: Зелинский Богдан