Резонный вопрос: зачем аттачить изображения, ведь это утяжеляет письма и увеличивает трафик? А чтобы не было такого:
Данный вид возникает в случае если пользователь читает полученную корреспонденцию оффлайн или почтовый клиент не открывает картинки из внешних источников, например из-за его настроек безопасности. Короче говоря, выглядит это может быть и читабельно, но не эстетично.
Если приаттачить картинки к письму, то оно обретёт целостный вид, и дырок уже не будет, если не допущено ошибок на этапе вёрстки.
Итак, необходимо получить возможность создавать полноценные html-шаблоны писем с картинками для их дальнейшего использования в программе (рассылка, автоматические уведомления и т.п.). В последующем шаблоны сможет готовить человек, занимающийся только версткой, без вмешательства в код программы.
Задача типичная, можно сказать обыденная, и реализаций уже придумано не мало. И чтобы не порождать 100500-й веолосипед, обратимся к небезызвестному Swift Mailer, немного расширив его функциональность применительно к нашей задаче.
Так будет выглядеть условный шаблон письма, назовём его index.html:
<html><head></head><body>
<img src=”images/company_logo.gif” >
Здравствуйте, {username}! Сообщаем Вам, что если сегодня вы навестите наш сайт, то сможете получить {something} абсолютно безвозмездно, то есть даром.
<div>Фото подарка: <img src=”images/{something_photo}”></div>
</body></html>
Структура каталогов для хранения шаблонов может выглядеть таким образом:
email_templates/
template1/
index.html
images/
company_logo.gif
photo1.png
...
photoN.png
template2/
...
Класс:
class SendEMail
{
static $transport = false;
public $filename = 'index.html',
// путь к html шаблону
$tplFolder = '',
// каталог с картинками
$imgFolder = 'images/',
$subject = '',
$from = '',
$fromName = null,
$contentType = 'text/html',
$charset = 'utf-8';
private $message, $data;
public function __construct($options)
{
foreach($options as $option => $value)
$this->$option = $value;
if (!self::$transport)
self::$transport = Swift_SmtpTransport::newInstance();
}
public function Send($data, $email, $name = null)
{
$this->data = $data;
$this->message = Swift_Message::newInstance();
$mess =& $this->message;
// подставляем данные в subject письма, если там есть соответствующие теги
$subject = $this->SubstituteData($this->subject);
$body = $this->GetBody();
// email и имя получателя
$mess->setTo($email, $name);
// от кого
$mess->setFrom($this->from, $this->fromName);
// тема письма
$mess->setSubject($subject);
// сообщение
$mess->setBody($body);
$mess->setContentType($this->contentType);
$mess->setCharset($this->charset);
$mailer = Swift_Mailer::newInstance(self::$transport);
return $mailer->send($this->message);
}
private function GetBody()
{
// считываем шаблон письма
$body = file_get_contents($this->tplPath.$this->filename);
// подставляем данные в шаблон
$body = $this->SubstituteData($body);
// аттачим все картинки, с подходящими imgPath и расширениями jpg, png, gif, заменяем атрибуты src в тегах img
// 'self::AddImage' будет работать для php > 5.3, для 5.2 нужно заменить на array($this, 'AddImage')
return preg_replace_callback('/'.preg_quote($this->imgPath, '/').'((.+).(jpg|png|gif))/i', 'self::AddImage', $body);
}
// прикрепляем картинку, меняем src
private function AddImage($matches)
{
$path = $this->tplPath."/".$matches[0];
return $this->message->embed(Swift_Image::fromPath($path));
}
// заменяем теги на соответствующие данные
private function SubstituteData($str)
{
if (empty($this->data))
return $str;
foreach($this->data as $k => $v)
$str = str_replace($k, $v, $str);
return $str;
}
}
Пример рассылки:
$sm = new SendEMail(array(
'tplPath' => '/path_to_emails/email_templates/template1/',
'subject' => 'Чудесные подарки',
'from' => 'noreply@site.com'
));
$recipients[0] = array(
'email' => 'dima@blabla.com',
'user' => 'Дмитрий Владимирович',
'something' => 'Мялка',
'something_photo' => 'myalka.jpg'
);
$recipients[1] = array(
'email' => 'volodya@blabla.com',
'user' => 'Владимир Анатольевич',
'something' => 'Мешалка',
'something_photo' => 'meshalka.jpg'
);
$success = 0;
foreach($recipients as $rec) {
$data = array('{user}' => $rec['user'], '{something}' => $rec['something'], '{something_photo}' => $rec['something_photo']);
$sended = $sm->Send($data, $rec['email'], $rec['user']);
if ($sended)
$success++;
}
Теперь необходимо следить за размерами создаваемых писем, и не превышать разумные объёмы, проявляя заботу о тех, у кого интернет с телефона, медленный, с оплатой по трафику.
Конечно, данные следует брать из БД, это всего лишь пример. В классе также отсутствуют обработчики ошибок для уменьшения количества строк, лучшей читаемости кода и понимания.
Автор: ekokh