Компонент Mime
Дата обновления перевода 2023-08-21
Компонент Mime
Компонент Mime позволяет взаимодействовать с сообщениями MIME, используемыми для отправки электронных писем, и предоставляет утилиты, связанные с типами MIME.
Установка
1
$ composer require symfony/mime
Note
Если вы устанавливаете этот компонент вне приложения Symfony, вам нужно
подключить файл vendor/autoload.php
в вашем коде для включения механизма
автозагрузки классов, предоставляемых Composer. Детальнее читайте в
этой статье.
Вступление
MIME (Многоцелевые расширения интерне-почты) - это стандарт Интернета, который расширяет первоначальный базовый формат электронных писем для поддержки функций вроде:
- Заголовков и содержания текста, использующих не ASCII символы;
- Тела сообщения с несколькими частями (например, HTML и простое текстовое содержание);
- Нетекстовых вложений: аудио, видео, изображений, и т.д.
Целиком стандарт MIME сложен и огромен, но Symfony отсекает все эти сложности, чтобы предоставить два способа создания MIME-сообщений:
Использование
Используйте класс Email и их образующие цепи методы, чтобы составить сообщение электронного письма полностью:
1 2 3 4 5 6 7 8 9 10 11 12 13
use Symfony\Component\Mime\Email;
$email = (new Email())
->from('fabien@symfony.com')
->to('foo@example.com')
->cc('bar@example.com')
->bcc('baz@example.com')
->replyTo('fabien@symfony.com')
->priority(Email::PRIORITY_HIGH)
->subject('Important Notification')
->text('Lorem ipsum...')
->html('<h1>Lorem ipsum</h1> <p>...</p>')
;
Единственной целью этого компонента является создание сообщений писем. Используйте компонент Mailer для того, чтобы отправлять их.
Интеграция с Twig
Компонент Mime поставляется с отличной интеграцией с Twig, позволяющей вам создавать сообщения из шаблонов Twig, встраивать изображения, CSS и другое. Детальней о том, как использовать эти функции, можно найти в документации Mailer: Twig: HTML & CSS .
Но если вы используете компонент Mime без фреймворка Symfony, вам нужно будет разобраться с некоторыми деталями настройки.
Настройка Twig
Для интеграции с Twig, используйте класс BodyRenderer для отображения шаблона и обновления содержания сообщениям письма с результатами:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// ...
use Symfony\Bridge\Twig\Mime\BodyRenderer;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
// при использовании компонента Mime внутри полностекового приложения Symfony, вам
// не нужно проходить эту настройку Twig. Вам только нужно внедрить сервис 'twig'
$loader = new FilesystemLoader(__DIR__.'/templates');
$twig = new Environment($loader);
$renderer = new BodyRenderer($twig);
// это обновляет объект $email с результатами отображения
// шаблона, определенного ранее в заданном контексте
$renderer->render($email);
Встраивание CSS-стилей (и других расширений)
Чтобы использовать фильтр inline_css , для начала установите расширение Twig:
1
$ composer require twig/cssinliner-extra
Теперь, подключите расширение:
1 2 3 4 5 6
// ...
use Twig\Extra\CssInliner\CssInlinerExtension;
$loader = new FilesystemLoader(__DIR__.'/templates');
$twig = new Environment($loader);
$twig->addExtension(new CssInlinerExtension());
Такой же процесс должен быть использован для подключения других расширений, вроде MarkdownExtension и InkyExtension .
Cоздание неформатированных сообщений электронных писем
Это полезно для продвинутых приложений, которым нужен абсолютны контроль над каждой частью письма. Это не рекомендуется для приложений с обычными требованиями к электронными письмам, потому как добавляет сложностей и не дает преимуществ.
Перед тем, как продолжать, важно посмотреть на структуру нижнего уровня сообщения письма. Рассмотрите сообщение, которое включает в себя некоторое содержание, как текстовое, так и HTML, одно изображение PNG, встроенное в это содержание, и файл PDF, вложенный в него. Стандарт MIME позволяет структурировать это сообщение разными способами, но следующее древо работает для большинства почтовых клиентов:
1 2 3 4 5 6 7
multipart/mixed
├── multipart/related
│ ├── multipart/alternative
│ │ ├── text/plain
│ │ └── text/html
│ └── image/png
└── application/pdf
Цели каждой части сообщения MIME:
multipart/alternative
: используется, когда две или более части являются альтернативами одного и того же (или очень похожего) содержания. Предпочитаемый формат должен быть добавлен последним.multipart/mixed
: используется для отправки разных типов содержания в одном сообщении письма, вроде как при вложении файлов.multipart/related
: используется для обозначения того, что каждая часть сообщения является компонентом совокупного целого. Наиболее распространенное применение - отображение изображений, встроенных в содержание сообщения.
При использовании класса нижнего уровня Message, создайте сообщение письма. Не забывайте обо всем, написанном выше, определяя разные части письма вручную:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
use Symfony\Component\Mime\Header\Headers;
use Symfony\Component\Mime\Message;
use Symfony\Component\Mime\Part\Multipart\AlternativePart;
use Symfony\Component\Mime\Part\TextPart;
$headers = (new Headers())
->addMailboxListHeader('From', ['fabien@symfony.com'])
->addMailboxListHeader('To', ['foo@example.com'])
->addTextHeader('Subject', 'Important Notification')
;
$textContent = new TextPart('Lorem ipsum...');
$htmlContent = new TextPart('<h1>Lorem ipsum</h1> <p>...</p>', null, 'html');
$body = new AlternativePart($textContent, $htmlContent);
$email = new Message($headers, $body);
Встраивание изображений и вложение файлов возможно путем создания соответствующих мультичастей письма:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
// ...
use Symfony\Component\Mime\Part\DataPart;
use Symfony\Component\Mime\Part\Multipart\MixedPart;
use Symfony\Component\Mime\Part\Multipart\RelatedPart;
// ...
$embeddedImage = new DataPart(fopen('/path/to/images/logo.png', 'r'), null, 'image/png');
$imageCid = $embeddedImage->getContentId();
$attachedFile = new DataPart(fopen('/path/to/documents/terms-of-use.pdf', 'r'), null, 'application/pdf');
$textContent = new TextPart('Lorem ipsum...');
$htmlContent = new TextPart(sprintf(
'<img src="cid:%s"/> <h1>Lorem ipsum</h1> <p>...</p>', $imageCid
), null, 'html');
$bodyContent = new AlternativePart($textContent, $htmlContent);
$body = new RelatedPart($bodyContent, $embeddedImage);
$messageParts = new MixedPart($body, $attachedFile);
$email = new Message($headers, $messageParts);
Сериализация сообщений писем
Сообщения писем, созданные с классом Email
или Message
, могут быть
сериализованы, так как они являются простыми объектами данных:
1 2 3 4 5 6
$email = (new Email())
->from('fabien@symfony.com')
// ...
;
$serializedEmail = serialize($email);
Распространенное использование - хранение сериализованных сообщений писем, включение их в сообщение, отправленное с помощью компонента Messenger и их позднейшее воссоздание при отправлении. Используйте класс RawMessage, чтобы воссоздавать сообщения писем из их сериализованного содержания:
1 2 3 4 5 6 7
use Symfony\Component\Mime\RawMessage;
// ...
$serializedEmail = serialize($email);
// позже, воссоздайте изначально сообщение, чтобы действительно отправить его
$message = new RawMessage(unserialize($serializedEmail));
Утилиты типов MIME
Хотя MIME был создан в оснвонмо для создания писем, типы содержания (так же известные как MIME-типы и "медиа-типы"), определенные стандартами MIME, также важны для протоколов коммуникации вне писем, например, для HTTP. Поэтому этот компонент также предоставляет утилиты для работы с MIME-типами.
Класс MimeTypes преобразуется между MIME-типами и расширениями имен файлов:
1 2 3 4 5 6 7 8 9 10 11 12
use Symfony\Component\Mime\MimeTypes;
$mimeTypes = new MimeTypes();
$exts = $mimeTypes->getExtensions('application/javascript');
// $exts = ['js', 'jsm', 'mjs']
$exts = $mimeTypes->getExtensions('image/jpeg');
// $exts = ['jpeg', 'jpg', 'jpe']
$types = $mimeTypes->getMimeTypes('js');
// $types = ['application/javascript', 'application/x-javascript', 'text/javascript']
$types = $mimeTypes->getMimeTypes('apk');
// $types = ['application/vnd.android.package-archive']
Эти методы возвращают массивы с одним или более элементов. Расположение элемента отображает его приоритет, поэтому первое возвращенное расширение является предпочитаемым.
Угадывание MIME-типа
Другая полезная утилита позволяет угадывать MIME-тип любого заданного файла:
1 2 3 4 5 6
use Symfony\Component\Mime\MimeTypes;
$mimeTypes = new MimeTypes();
$mimeType = $mimeTypes->guessMimeType('/some/path/to/image.gif');
// Угадывание не основывается на имени файла, поэтому $mimeType будет 'image/gif'
// только, если заданный файл действительно является изображением GIF
Угадывание MIME-типа - времязатратный процесс, требующий исследования части содержания файла. Symfony применяет множество механизмов угадывания, один из которых основывается на PHP-расширении fileinfo. Рекомендуется установить это расширение, чтобы улучшить производительность угадывания.
Добавление угадывателя MIME-типа
Вы можете добавлять собственного угадывателя MIME-типа, создавая класс, реалищующий MimeTypeGuesserInterface:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
namespace App;
use Symfony\Component\Mime\MimeTypeGuesserInterface;
class SomeMimeTypeGuesser implements MimeTypeGuesserInterface
{
public function isGuesserSupported(): bool
{
// вернуть true, если угадыватель поддерживается (может зависеть от OS, к примеру)
return true;
}
public function guessMimeType(string $path): ?string
{
// исследовать содержание файла, хранящегося в $path, чтобы угадать его
// тип и вернуть валидный MIME-тип ... или null, если тип неизвестен
return '...';
}
}
Угадыватели MIME-типа должны быть зарегистрированы как сервисы
и тегированы тегом mime.mime_type_guesser
.
Если вы используете
конфигурацию services.yaml по умолчанию ,
это уже сделано за вас, благодаря автоконфигурации .