Компонент Mime

Дата оновлення перекладу 2022-11-12

Компонент Mime

Компонент Mime дозволяє взаємодіяти з MIME-повідомленнями, використовуваними для відправки електронних листів, та надає утиліти, повʼязані з MIME-типами.

Установка

1
$ composer require symfony/mime

Note

Якщо ви встановлюєте цей компонент поза додатком Symfony, вам потрібно підключити файл vendor/autoload.phpу вашому коді для включення механізму автозавантаження класів, наданих Composer. Детальніше можна прочитати у цій статті.

Вступ

MIME (Багатоцільові розширення для інтернет-пошти) - це стандарт Інтернету, який розширює початковий базовий формат електронних листів для підтримки функцій на кшталт:

  • Заголовків та змісту тексту, що використовують не-ASCII символи;
  • Тіла повідомлення з декількома частинами (наприклад, HTML і простий текстовий зміст);
  • Нетекстових вкладень: аудіо, відео, зображень і т.д.

Цілком стандарт MIME складний та величезний, але Symfony відсікає всі ці складнощі, щоб надати два способи створення MIME-повідомлень:

  • API високого рівня, заснованого на класі Email для швидкого створення повідомлень листів з усіма розповсюдженими функціями;
  • API низького рівня, заснованого на класі Message для абсолютного контролю над кожною частиною повідомлення листа.

Використання

Використайте клас 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 .

Створення неформатованих повідомень електронних листів

Це корисно для просунутих додатків, яким потрібний абсолютний контроль над кожною частиною листа. Це не рекомендовано для додатків зі звичайними вимогами до електронних листів, так як додає складностей і не надає переваг.

Перед тим, як продовжувати, важливо подивитися на структуру нижнього рівня повідомлення листа. Розгляньте повідомлення, яке включає в себе деякий зміст, як текстовий, так і 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, якщо вгадувач підтримується (може залежати від ОС, наприклад)
        return true;
    }

    public function guessMimeType(string $path): ?string
    {
        // дослідити зміст файлу, що зберігається в $path, щоб вгадати його тип
        // і повернути валідний MIME-тип ... або null, якщо тип невідомий

        return '...';
    }
}

Вгадувачі MIME-типу повинні бути зареєстровані як сервіси і теговані тегом mime.mime_type_guesser.
Якщо ви використовуєте конфігурацію services.yaml за замовчуванням , це вже зроблено за вас, завдяки автоконфігурації .