Пошта · Laravel
Частину підрозділів ще не перекладено, вони показані англійською нижче в тексті або лишились в оригіналі. Готові фрагменти вже перевірені редактором.
Вступ
Надсилання пошти не мусить бути складним. Laravel дає охайний і простий поштовий API, побудований на популярному компоненті Symfony Mailer. Laravel і Symfony Mailer надають драйвери для надсилання пошти через SMTP, Cloudflare, Mailgun, Postmark, Resend, Amazon SES і sendmail, тож ви швидко почнете надсилати листи через локальний або хмарний сервіс на свій вибір.
Конфігурація
Поштові сервіси Laravel налаштовуються у файлі конфігурації config/mail.php. Кожен mailer, описаний у цьому файлі, може мати власну конфігурацію і навіть власний «транспорт», завдяки чому застосунок може надсилати різні листи різними поштовими сервісами. Наприклад, ваш застосунок може використовувати Postmark для транзакційних листів і Amazon SES для масових розсилок.
У файлі конфігурації mail ви знайдете масив mailers. Цей масив містить приклад конфігурації для кожного з основних поштових драйверів / транспортів, які підтримує Laravel, а значення default визначає, який mailer використовується за замовчуванням, коли застосунку треба надіслати лист.
Вимоги драйверів / транспортів
Драйвери на основі API, як-от Mailgun, Postmark і Resend, зазвичай простіші та швидші за надсилання пошти через SMTP-сервери. Коли це можливо, радимо використовувати саме такий драйвер.
Драйвер Cloudflare
Щоб використати драйвер Cloudflare, установіть Symfony HTTP Client через Composer:
composer require symfony/http-client
Далі потрібно зробити дві зміни у файлі конфігурації config/mail.php. По-перше, встановіть mailer за замовчуванням на cloudflare:
'default' => env('MAIL_MAILER', 'cloudflare'),
По-друге, додайте такий масив конфігурації до масиву mailers:
'cloudflare' => [
'transport' => 'cloudflare',
],
Після налаштування mailer за замовчуванням додайте такі опції до файлу конфігурації config/services.php:
'cloudflare' => [
'account_id' => env('CLOUDFLARE_ACCOUNT_ID'),
'key' => env('CLOUDFLARE_KEY'),
],
Драйвер Mailgun
Щоб використати драйвер Mailgun, установіть транспорт Symfony Mailgun Mailer через Composer:
composer require symfony/mailgun-mailer symfony/http-client
Далі потрібно зробити дві зміни у файлі конфігурації config/mail.php. По-перше, встановіть mailer за замовчуванням на mailgun:
'default' => env('MAIL_MAILER', 'mailgun'),
По-друге, додайте такий масив конфігурації до масиву mailers:
'mailgun' => [
'transport' => 'mailgun',
// 'client' => [
// 'timeout' => 5,
// ],
],
Після налаштування mailer за замовчуванням додайте такі опції до файлу конфігурації config/services.php:
'mailgun' => [
'domain' => env('MAILGUN_DOMAIN'),
'secret' => env('MAILGUN_SECRET'),
'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
'scheme' => 'https',
],
Якщо ви не в американському регіоні Mailgun, укажіть endpoint свого регіону у файлі конфігурації services:
'mailgun' => [
'domain' => env('MAILGUN_DOMAIN'),
'secret' => env('MAILGUN_SECRET'),
'endpoint' => env('MAILGUN_ENDPOINT', 'api.eu.mailgun.net'),
'scheme' => 'https',
],
Драйвер Postmark
Щоб використати драйвер Postmark, установіть транспорт Symfony Postmark Mailer через Composer:
composer require symfony/postmark-mailer symfony/http-client
Далі встановіть опцію default у файлі конфігурації config/mail.php на postmark. Після налаштування mailer за замовчуванням переконайтеся, що файл конфігурації config/services.php містить такі опції:
'postmark' => [
'key' => env('POSTMARK_API_KEY'),
],
Якщо потрібно вказати Postmark message stream для конкретного mailer, додайте опцію конфігурації message_stream_id до масиву конфігурації цього mailer. Цей масив конфігурації міститься у файлі config/mail.php:
'postmark' => [
'transport' => 'postmark',
'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'),
// 'client' => [
// 'timeout' => 5,
// ],
],
Таким чином ви також можете налаштувати кілька Postmark-mailer з різними message streams.
Драйвер Resend
Щоб використати драйвер Resend, установіть PHP SDK від Resend через Composer:
composer require resend/resend-php
Далі встановіть опцію default у файлі конфігурації config/mail.php на resend. Після налаштування mailer за замовчуванням переконайтеся, що файл конфігурації config/services.php містить такі опції:
'resend' => [
'key' => env('RESEND_API_KEY'),
],
Драйвер SES
Щоб використати драйвер Amazon SES, спершу треба встановити Amazon AWS SDK для PHP. Цю бібліотеку можна встановити через менеджер пакетів Composer:
composer require aws/aws-sdk-php
Далі встановіть опцію default у файлі конфігурації config/mail.php на ses і переконайтеся, що файл конфігурації config/services.php містить такі опції:
'ses' => [
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],
Щоб скористатися тимчасовими обліковими даними AWS через session token, додайте ключ token до конфігурації SES у своєму застосунку:
'ses' => [
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'token' => env('AWS_SESSION_TOKEN'),
],
Щоб працювати з можливостями керування підписками SES, поверніть заголовок X-Ses-List-Management-Options у масиві, який повертає метод headers поштового повідомлення:
/**
* Отримати заголовки повідомлення.
*/
public function headers(): Headers
{
return new Headers(
text: [
'X-Ses-List-Management-Options' => 'contactListName=MyContactList;topicName=MyTopic',
],
);
}
Щоб надіслати лист через тенант SES, поверніть заголовок X-Ses-Tenant-Name із методу headers. Laravel передасть значення цього заголовка до SES як опцію TenantName під час надсилання повідомлення:
public function headers(): Headers
{
return new Headers(
text: [
'X-Ses-Tenant-Name' => 'tenant-id',
],
);
}
Якщо ви хочете визначити додаткові опції, які Laravel має передавати методу SendEmail з AWS SDK під час надсилання листа, опишіть масив options у конфігурації ses:
'ses' => [
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'options' => [
'ConfigurationSetName' => 'MyConfigurationSet',
'EmailTags' => [
['Name' => 'foo', 'Value' => 'bar'],
],
],
],
Конфігурація failover
Іноді зовнішній сервіс, налаштований для надсилання пошти, може бути недоступним. У таких випадках корисно мати одну чи кілька резервних конфігурацій доставки, які використовуватимуться, якщо основний драйвер не працює.
Для цього опишіть у файлі конфігурації mail mailer, який використовує транспорт failover. Масив конфігурації цього mailer має містити масив mailers із порядком, у якому налаштовані mailer обираються для доставки:
'mailers' => [
'failover' => [
'transport' => 'failover',
'mailers' => [
'postmark',
'mailgun',
'sendmail',
],
'retry_after' => 60,
],
// ...
],
Після того, як ви налаштували mailer із транспортом failover, встановіть його як mailer за замовчуванням у файлі .env, щоб задіяти цю функціональність:
MAIL_MAILER=failover
Конфігурація round robin
Транспорт roundrobin дає змогу розподілити навантаження розсилки між кількома mailer. Спершу опишіть у файлі конфігурації mail mailer, який використовує транспорт roundrobin. Масив конфігурації цього mailer має містити масив mailers із переліком налаштованих mailer, які використовуватимуться для доставки:
'mailers' => [
'roundrobin' => [
'transport' => 'roundrobin',
'mailers' => [
'ses',
'postmark',
],
'retry_after' => 60,
],
// ...
],
Після того, як round robin mailer описано, встановіть його як mailer за замовчуванням, указавши його імʼя значенням ключа конфігурації default у файлі конфігурації mail:
'default' => env('MAIL_MAILER', 'roundrobin'),
Транспорт round robin обирає випадковий mailer зі списку налаштованих, а для кожного наступного листа переходить до наступного доступного mailer. На відміну від транспорту failover, який допомагає досягти високої доступності, транспорт roundrobin забезпечує балансування навантаження.
Генерація mailable-класів
У застосунках на Laravel кожен тип листа, який надсилає застосунок, представлений класом «mailable». Ці класи зберігаються в каталозі app/Mail. Не хвилюйтеся, якщо не бачите цього каталогу: він створиться, коли ви згенеруєте перший mailable-клас Artisan-командою make:mail:
php artisan make:mail OrderShipped
Написання mailable-класів
Згенерувавши mailable-клас, відкрийте його, щоб роздивитися вміст. Конфігурація mailable-класу відбувається в кількох методах: envelope, content і attachments.
Метод envelope повертає обʼєкт Illuminate\Mail\Mailables\Envelope, який визначає тему листа і, подекуди, отримувачів повідомлення. Метод content повертає обʼєкт Illuminate\Mail\Mailables\Content, який визначає шаблон Blade, що використовуватиметься для генерації вмісту повідомлення.
Налаштування відправника
Використання Envelope
Спершу розберімося з налаштуванням відправника листа. Іншими словами, від кого лист надходить. Є два способи налаштувати відправника. По-перше, ви можете вказати адресу «from» в envelope повідомлення:
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Envelope;
/**
* Отримати envelope повідомлення.
*/
public function envelope(): Envelope
{
return new Envelope(
from: new Address('jeffrey@example.com', 'Jeffrey Way'),
subject: 'Order Shipped',
);
}
За бажання можна також указати адресу replyTo:
return new Envelope(
from: new Address('jeffrey@example.com', 'Jeffrey Way'),
replyTo: [
new Address('taylor@example.com', 'Taylor Otwell'),
],
subject: 'Order Shipped',
);
Використання глобальної адреси from
Якщо ж застосунок використовує ту саму адресу «from» для всіх листів, додавати її до кожного згенерованого mailable-класу стає марудно. Замість цього вкажіть глобальну адресу «from» у файлі конфігурації config/mail.php. Ця адреса використовуватиметься, якщо в mailable-класі не вказано іншої адреси «from»:
'from' => [
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
'name' => env('MAIL_FROM_NAME', 'Example'),
],
Крім того, у файлі конфігурації config/mail.php можна визначити глобальну адресу «reply_to»:
'reply_to' => [
'address' => 'example@example.com',
'name' => 'App Name',
],
Налаштування представлення
У методі content mailable-класу ви можете визначити view, тобто який шаблон використовувати під час рендерингу вмісту листа. Оскільки кожен лист зазвичай рендерить свій вміст через шаблон Blade, під час побудови HTML листа вам доступна вся потужність і зручність шаблонізатора Blade:
/**
* Отримати визначення вмісту повідомлення.
*/
public function content(): Content
{
return new Content(
view: 'mail.orders.shipped',
);
}
[!NOTE] Можливо, вам захочеться створити каталог
resources/views/mailдля всіх поштових шаблонів; утім, ви можете розміщувати їх де завгодно всередині каталогуresources/views.
Листи у вигляді простого тексту
Якщо ви хочете визначити текстову версію листа, укажіть текстовий шаблон під час створення визначення Content повідомлення. Як і параметр view, параметр text має бути іменем шаблону, який використовуватиметься для рендерингу вмісту листа. Ви вільні визначити і HTML-, і текстову версію повідомлення:
/**
* Отримати визначення вмісту повідомлення.
*/
public function content(): Content
{
return new Content(
view: 'mail.orders.shipped',
text: 'mail.orders.shipped-text'
);
}
Для ясності параметр html можна використовувати як псевдонім параметра view:
return new Content(
html: 'mail.orders.shipped',
text: 'mail.orders.shipped-text'
);
Дані для представлення
Через публічні властивості
Зазвичай вам потрібно передати у представлення (view) якісь дані, щоб використати їх під час рендерингу HTML листа. Є два способи зробити дані доступними для представлення. По-перше, будь-яка публічна властивість, визначена у вашому mailable-класі, автоматично стане доступною у представленні. Наприклад, ви можете передати дані в конструктор mailable-класу і присвоїти їх публічним властивостям класу:
<?php
namespace App\Mail;
use App\Models\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Queue\SerializesModels;
class OrderShipped extends Mailable
{
use Queueable, SerializesModels;
/**
* Створити новий екземпляр повідомлення.
*/
public function __construct(
public Order $order,
) {}
/**
* Отримати визначення вмісту повідомлення.
*/
public function content(): Content
{
return new Content(
view: 'mail.orders.shipped',
);
}
}
Щойно дані присвоєно публічній властивості, вони автоматично стають доступними у представленні, тож ви звертаєтеся до них так само, як до будь-яких інших даних у шаблонах Blade:
<div>
Price: {{ $order->price }}
</div>
Через параметр with
Якщо ви хочете змінити формат даних листа перед тим, як вони потраплять у шаблон, передайте дані у представлення вручну через параметр with визначення Content. Зазвичай дані все одно передаються через конструктор mailable-класу; проте присвоюйте їх властивостям protected або private, щоб вони не ставали автоматично доступними шаблону:
<?php
namespace App\Mail;
use App\Models\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Queue\SerializesModels;
class OrderShipped extends Mailable
{
use Queueable, SerializesModels;
/**
* Створити новий екземпляр повідомлення.
*/
public function __construct(
protected Order $order,
) {}
/**
* Отримати визначення вмісту повідомлення.
*/
public function content(): Content
{
return new Content(
view: 'mail.orders.shipped',
with: [
'orderName' => $this->order->name,
'orderPrice' => $this->order->price,
],
);
}
}
Щойно дані передано через параметр with, вони автоматично стають доступними у представленні, тож ви звертаєтеся до них так само, як до будь-яких інших даних у шаблонах Blade:
<div>
Price: {{ $orderPrice }}
</div>
Вкладення
Щоб додати вкладення до листа, додайте їх у масив, який повертає метод attachments повідомлення. Найпростіше додати вкладення, передавши шлях до файлу методу fromPath класу Attachment:
use Illuminate\Mail\Mailables\Attachment;
/**
* Отримати вкладення повідомлення.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [
Attachment::fromPath('/path/to/file'),
];
}
Прикріплюючи файли до повідомлення, ви також можете вказати відображуване імʼя і / або MIME-тип вкладення методами as і withMime:
/**
* Отримати вкладення повідомлення.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [
Attachment::fromPath('/path/to/file')
->as('name.pdf')
->withMime('application/pdf'),
];
}
Прикріплення файлів із диска
Якщо файл збережено на одному з ваших дисків файлової системи, прикріпіть його до листа методом fromStorage:
/**
* Отримати вкладення повідомлення.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [
Attachment::fromStorage('/path/to/file'),
];
}
Звісно, ви можете вказати й імʼя та MIME-тип вкладення:
/**
* Отримати вкладення повідомлення.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [
Attachment::fromStorage('/path/to/file')
->as('name.pdf')
->withMime('application/pdf'),
];
}
Метод fromStorageDisk знадобиться, якщо потрібно вказати диск, відмінний від диска за замовчуванням:
/**
* Отримати вкладення повідомлення.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [
Attachment::fromStorageDisk('s3', '/path/to/file')
->as('name.pdf')
->withMime('application/pdf'),
];
}
Вкладення із сирих даних
Метод fromData дає змогу прикріпити сирий рядок байтів як вкладення. Наприклад, він згодиться, якщо ви згенерували PDF у памʼяті і хочете прикріпити його до листа, не записуючи на диск. Метод fromData приймає замикання, яке повертає сирі байти даних, а також імʼя, яке слід присвоїти вкладенню:
/**
* Отримати вкладення повідомлення.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [
Attachment::fromData(fn () => $this->pdf, 'Report.pdf')
->withMime('application/pdf'),
];
}
Вбудовані вкладення
Вбудовування зображень у листи зазвичай марудне; проте Laravel пропонує зручний спосіб прикріпити зображення до листа. Щоб вбудувати зображення, викличте метод embed на змінній $message у поштовому шаблоні. Laravel автоматично робить змінну $message доступною в усіх поштових шаблонах, тож передавати її вручну не потрібно:
<body>
Here is an image:
<img src="{{ $message->embed($pathToImage) }}">
</body>
[!WARNING] Змінна
$messageнедоступна в шаблонах текстових повідомлень, оскільки прості текстові повідомлення не використовують вбудованих вкладень.
Вбудовування вкладень із сирих даних
Якщо у вас уже є рядок сирих даних зображення, який ви хочете вбудувати в поштовий шаблон, викличте метод embedData на змінній $message. Викликаючи embedData, вам потрібно передати імʼя файлу, яке буде присвоєно вбудованому зображенню:
<body>
Here is an image from raw data:
<img src="{{ $message->embedData($data, 'example-image.jpg') }}">
</body>
Обʼєкти, які можна вкладати
Прикріплення файлів через прості рядки-шляхи часто достатньо, але в багатьох випадках сутності, які ви прикріплюєте, представлені класами. Наприклад, якщо застосунок прикріплює до повідомлення фотографію, у ньому, імовірно, є й модель Photo, що представляє цю фотографію. Чи не зручно було б у такому разі просто передати модель Photo методу attach? Саме це і дають обʼєкти, які можна вкладати.
Для початку реалізуйте інтерфейс Illuminate\Contracts\Mail\Attachable на обʼєкті, який можна буде прикріплювати до повідомлень. Цей інтерфейс вимагає, щоб ваш клас визначив метод toMailAttachment, який повертає екземпляр Illuminate\Mail\Attachment:
<?php
namespace App\Models;
use Illuminate\Contracts\Mail\Attachable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Mail\Attachment;
class Photo extends Model implements Attachable
{
/**
* Отримати представлення моделі у вигляді вкладення.
*/
public function toMailAttachment(): Attachment
{
return Attachment::fromPath('/path/to/file');
}
}
Описавши такий обʼєкт, ви можете повернути його екземпляр із методу attachments під час побудови листа:
/**
* Отримати вкладення повідомлення.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [$this->photo];
}
Звісно, дані вкладення можуть зберігатися у віддаленому файловому сховищі на кшталт Amazon S3. Тож Laravel дає змогу створювати екземпляри вкладень і з даних, що лежать на одному з дисків файлової системи вашого застосунку:
// Створити вкладення з файлу на диску за замовчуванням...
return Attachment::fromStorage($this->path);
// Створити вкладення з файлу на конкретному диску...
return Attachment::fromStorageDisk('backblaze', $this->path);
Крім того, ви можете створювати екземпляри вкладень із даних у памʼяті. Для цього передайте замикання методу fromData. Замикання має повернути сирі дані, що представляють вкладення:
return Attachment::fromData(fn () => $this->content, 'Photo Name');
Laravel також надає додаткові методи для налаштування вкладень. Наприклад, методами as і withMime можна задати імʼя файлу і MIME-тип:
return Attachment::fromPath('/path/to/file')
->as('Photo Name')
->withMime('image/jpeg');
Заголовки
Іноді потрібно додати до вихідного повідомлення додаткові заголовки. Наприклад, встановити власний Message-Id чи інші довільні текстові заголовки.
Для цього визначте в mailable метод headers. Він має повертати екземпляр Illuminate\Mail\Mailables\Headers. Цей клас приймає параметри messageId, references і text. Звісно, ви можете передати лише ті параметри, які потрібні для конкретного повідомлення:
use Illuminate\Mail\Mailables\Headers;
/**
* Отримати заголовки повідомлення.
*/
public function headers(): Headers
{
return new Headers(
messageId: 'custom-message-id@example.com',
references: ['previous-message@example.com'],
text: [
'X-Custom-Header' => 'Custom Value',
],
);
}
Теги й метадані
Деякі сторонні поштові провайдери, як-от Mailgun і Postmark, підтримують «теги» й «метадані» повідомлень, за якими можна групувати й відстежувати листи, надіслані застосунком. Додати теги й метадані до листа можна через визначення Envelope:
use Illuminate\Mail\Mailables\Envelope;
/**
* Отримати envelope повідомлення.
*
* @return \Illuminate\Mail\Mailables\Envelope
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Order Shipped',
tags: ['shipment'],
metadata: [
'order_id' => $this->order->id,
],
);
}
Якщо застосунок використовує драйвер Mailgun, докладніше про теги і метадані читайте в документації Mailgun. Так само в документації Postmark є більше інформації про підтримку тегів і метаданих.
Якщо застосунок надсилає пошту через Amazon SES, для прикріплення «тегів» SES до повідомлення використовуйте метод metadata.
Кастомізація Symfony Message
Поштові можливості Laravel побудовані на Symfony Mailer. Laravel дає змогу зареєструвати власні колбеки, які викликаються з екземпляром Symfony Message перед надсиланням повідомлення. Це дає нагоду глибоко налаштувати повідомлення перед відправленням. Для цього визначте параметр using у визначенні Envelope:
use Illuminate\Mail\Mailables\Envelope;
use Symfony\Component\Mime\Email;
/**
* Отримати envelope повідомлення.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Order Shipped',
using: [
function (Email $message) {
// ...
},
]
);
}
Markdown-mailable
Markdown-повідомлення дають змогу використовувати готові шаблони й компоненти поштових сповіщень у ваших mailable-класах. Оскільки повідомлення написані в Markdown, Laravel рендерить для них гарні адаптивні HTML-шаблони й автоматично генерує текстовий відповідник.
Генерація Markdown-mailable
Щоб згенерувати mailable з відповідним Markdown-шаблоном, скористайтеся опцією --markdown Artisan-команди make:mail:
php artisan make:mail OrderShipped --markdown=mail.orders.shipped
Далі, налаштовуючи визначення Content у методі content, використовуйте параметр markdown замість параметра view:
use Illuminate\Mail\Mailables\Content;
/**
* Отримати визначення вмісту повідомлення.
*/
public function content(): Content
{
return new Content(
markdown: 'mail.orders.shipped',
with: [
'url' => $this->orderUrl,
],
);
}
Написання Markdown-повідомлень
Markdown-mailable поєднують компоненти Blade і синтаксис Markdown, що дає змогу легко будувати поштові повідомлення, спираючись на готові UI-компоненти листів від Laravel:
<x-mail::message>
# Order Shipped
Your order has been shipped!
<x-mail::button :url="$url">
View Order
</x-mail::button>
Thanks,<br>
{{ config('app.name') }}
</x-mail::message>
[!NOTE] Не робіть зайвих відступів, коли пишете Markdown-листи. За стандартами Markdown парсери рендерять вміст із відступами як блоки коду.
Компонент Button
Компонент button рендерить центроване посилання-кнопку. Компонент приймає два аргументи: url і необовʼязковий color. Підтримувані кольори: primary, success і error. Ви можете додати до повідомлення скільки завгодно компонентів button:
<x-mail::button :url="$url" color="success">
View Order
</x-mail::button>
Компонент Panel
Компонент panel рендерить заданий блок тексту в панелі, колір тла якої трохи відрізняється від решти повідомлення. Так можна привернути увагу до певного блоку тексту:
<x-mail::panel>
This is the panel content.
</x-mail::panel>
Компонент Table
Компонент table перетворює таблицю Markdown на HTML-таблицю. Компонент приймає таблицю Markdown як свій вміст. Вирівнювання колонок підтримується через стандартний синтаксис вирівнювання таблиць Markdown:
<x-mail::table>
| Laravel | Table | Example |
| ------------- | :-----------: | ------------: |
| Col 2 is | Centered | $10 |
| Col 3 is | Right-Aligned | $20 |
</x-mail::table>
Кастомізація компонентів
Ви можете експортувати всі Markdown-компоненти пошти у свій застосунок для налаштування. Щоб експортувати компоненти, скористайтеся Artisan-командою vendor:publish і опублікуйте asset-тег laravel-mail:
php artisan vendor:publish --tag=laravel-mail
Ця команда опублікує Markdown-компоненти пошти в каталог resources/views/vendor/mail. Каталог mail міститиме каталоги html і text, кожен із відповідними представленнями кожного доступного компонента. Ви можете налаштовувати ці компоненти як завгодно.
Кастомізація CSS
Після експорту компонентів каталог resources/views/vendor/mail/html/themes міститиме файл default.css. Ви можете змінити CSS у цьому файлі, і ваші стилі автоматично перетворяться на інлайнові CSS-стилі в HTML-представленнях ваших Markdown-листів.
Якщо ви хочете зробити цілком нову тему для Markdown-компонентів Laravel, покладіть CSS-файл у каталог html/themes. Назвавши і зберігши свій CSS-файл, оновіть опцію theme у файлі конфігурації config/mail.php, щоб вона відповідала назві нової теми.
Щоб задати тему для окремого mailable, встановіть властивість $theme цього mailable-класу на назву теми, яку слід використати під час надсилання.
Надсилання пошти
Щоб надіслати повідомлення, скористайтеся методом to фасаду Mail. Метод to приймає email-адресу, екземпляр користувача або колекцію користувачів. Якщо ви передаєте обʼєкт або колекцію обʼєктів, mailer автоматично використає їхні властивості email і name для визначення отримувачів, тож переконайтеся, що ці атрибути доступні на ваших обʼєктах. Указавши отримувачів, передайте екземпляр свого mailable-класу методу send:
<?php
namespace App\Http\Controllers;
use App\Mail\OrderShipped;
use App\Models\Order;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
class OrderShipmentController extends Controller
{
/**
* Відправити вказане замовлення.
*/
public function store(Request $request): RedirectResponse
{
$order = Order::findOrFail($request->order_id);
// Відправити замовлення...
Mail::to($request->user())->send(new OrderShipped($order));
return redirect('/orders');
}
}
Надсилаючи повідомлення, ви не обмежені лише отримувачами «to». Ви вільні задати отримувачів «to», «cc» і «bcc», ланцюжком викликавши відповідні методи:
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->send(new OrderShipped($order));
Ітерація по отримувачах
Іноді потрібно надіслати mailable списку отримувачів, проходячи в циклі масив отримувачів / email-адрес. Але оскільки метод to додає email-адреси до списку отримувачів mailable, кожна ітерація циклу надсилатиме ще один лист усім попереднім отримувачам. Тому завжди створюйте новий екземпляр mailable для кожного отримувача:
foreach (['taylor@example.com', 'dries@example.com'] as $recipient) {
Mail::to($recipient)->send(new OrderShipped($order));
}
Надсилання пошти через конкретний mailer
За замовчуванням Laravel надсилає листи через mailer, указаний як default у файлі конфігурації mail. Проте ви можете скористатися методом mailer, щоб надіслати повідомлення конкретною конфігурацією mailer:
Mail::mailer('postmark')
->to($request->user())
->send(new OrderShipped($order));
Постановка пошти в чергу
Постановка поштового повідомлення в чергу
Оскільки надсилання листів може негативно впливати на час відповіді застосунку, багато розробників ставлять листи в чергу для фонового надсилання. Laravel робить це просто завдяки вбудованому уніфікованому API черг. Щоб поставити поштове повідомлення в чергу, скористайтеся методом queue фасаду Mail після того, як вказали отримувачів:
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->queue(new OrderShipped($order));
Цей метод автоматично подбає про те, щоб покласти завдання (job) у чергу і повідомлення надіслалося у фоні. Перед використанням цієї можливості потрібно налаштувати черги.
Відкладена постановка повідомлення в чергу
Якщо ви хочете відкласти доставку поштового повідомлення з черги, скористайтеся методом later. Першим аргументом метод later приймає екземпляр DateTime, який указує, коли повідомлення має бути надіслане:
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->later(now()->plus(minutes: 10), new OrderShipped($order));
Надсилання в конкретні черги
Оскільки всі mailable-класи, згенеровані командою make:mail, використовують трейт Illuminate\Bus\Queueable, ви можете викликати методи onQueue і onConnection на будь-якому екземплярі mailable-класу, вказавши зʼєднання та імʼя черги для повідомлення:
$message = (new OrderShipped($order))
->onConnection('sqs')
->onQueue('emails');
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->queue($message);
Крім того, зʼєднання і чергу можна вказати атрибутами Connection і Queue на mailable-класі:
use Illuminate\Queue\Attributes\Connection;
use Illuminate\Queue\Attributes\Queue;
#[Connection('sqs')]
#[Queue('emails')]
class OrderShipped extends Mailable
{
// ...
}
Постановка в чергу за замовчуванням
Якщо у вас є mailable-класи, які завжди мають потрапляти в чергу, реалізуйте на класі контракт ShouldQueue. Тепер навіть якщо ви викличете метод send, mailable все одно потрапить у чергу, бо клас реалізує цей контракт:
use Illuminate\Contracts\Queue\ShouldQueue;
class OrderShipped extends Mailable implements ShouldQueue
{
// ...
}
Mailable у черзі й транзакції бази даних
Коли mailable з черги диспатчиться всередині транзакції бази даних, черга може обробити його ще до того, як транзакцію буде закомічено. У такому разі оновлення, які ви зробили моделям чи записам БД під час транзакції, можуть ще не відобразитися в базі. Ба більше, моделі чи записи, створені всередині транзакції, можуть у базі не існувати. Якщо ваш mailable залежить від цих моделей, під час обробки завдання, що надсилає лист, можуть виникнути несподівані помилки.
Якщо опція конфігурації after_commit вашого зʼєднання черги має значення false, ви все одно можете вказати, що конкретний mailable з черги слід диспатчити після коміту всіх відкритих транзакцій БД, викликавши метод afterCommit під час надсилання повідомлення:
Mail::to($request->user())->send(
(new OrderShipped($order))->afterCommit()
);
Або ж викличте метод afterCommit із конструктора свого mailable:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class OrderShipped extends Mailable implements ShouldQueue
{
use Queueable, SerializesModels;
/**
* Створити новий екземпляр повідомлення.
*/
public function __construct()
{
$this->afterCommit();
}
}
[!NOTE] Щоб дізнатися більше про обхід цих проблем, перегляньте документацію про завдання в черзі й транзакції бази даних.
Збої листів у черзі
Коли лист із черги завершується збоєм, викликається метод failed mailable-класу, якщо його визначено. Екземпляр Throwable, що спричинив збій, передається в метод failed:
<?php
namespace App\Mail;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Throwable;
class OrderDelayed extends Mailable implements ShouldQueue
{
use SerializesModels;
/**
* Обробити збій листа з черги.
*/
public function failed(Throwable $exception): void
{
// ...
}
}
Рендеринг mailable-класів
Іноді потрібно отримати HTML-вміст mailable, не надсилаючи його. Для цього викличте метод render на mailable. Цей метод поверне обчислений HTML-вміст mailable у вигляді рядка:
use App\Mail\InvoicePaid;
use App\Models\Invoice;
$invoice = Invoice::find(1);
return (new InvoicePaid($invoice))->render();
Попередній перегляд у браузері
Коли ви проєктуєте шаблон mailable, зручно швидко переглянути відрендерений результат у браузері, як звичайний шаблон Blade. Тому Laravel дає змогу повертати будь-який mailable просто із замикання маршруту або контролера. Повернутий mailable буде відрендерено і показано в браузері, тож ви швидко переглянете його дизайн без надсилання на реальну поштову адресу:
Route::get('/mailable', function () {
$invoice = App\Models\Invoice::find(1);
return new App\Mail\InvoicePaid($invoice);
});
Локалізація mailable-класів
Laravel дає змогу надсилати mailable у локалі, відмінній від поточної локалі запиту, і навіть памʼятає цю локаль, якщо лист поставлено в чергу.
Для цього фасад Mail пропонує метод locale, який задає потрібну мову. Застосунок перемкнеться на цю локаль на час обчислення шаблону mailable, а потім поверне попередню локаль:
Mail::to($request->user())->locale('es')->send(
new OrderShipped($order)
);
Бажані локалі користувача
Іноді застосунки зберігають бажану локаль кожного користувача. Реалізувавши контракт HasLocalePreference на одній чи кількох моделях, ви вкажете Laravel використовувати збережену локаль під час надсилання пошти:
use Illuminate\Contracts\Translation\HasLocalePreference;
class User extends Model implements HasLocalePreference
{
/**
* Отримати бажану локаль користувача.
*/
public function preferredLocale(): string
{
return $this->locale;
}
}
Після реалізації інтерфейсу Laravel автоматично використовуватиме бажану локаль під час надсилання mailable і сповіщень цій моделі. Тож викликати метод locale при використанні цього інтерфейсу не потрібно:
Mail::to($request->user())->send(new OrderShipped($order));
Тестування
Тестування вмісту mailable
Laravel надає низку методів для перевірки структури вашого mailable. Крім того, є кілька зручних методів для тестування того, що mailable містить очікуваний вміст:
use App\Mail\InvoicePaid;
use App\Models\User;
test('mailable content', function () {
$user = User::factory()->create();
$mailable = new InvoicePaid($user);
$mailable->assertFrom('jeffrey@example.com');
$mailable->assertTo('taylor@example.com');
$mailable->assertHasCc('abigail@example.com');
$mailable->assertHasBcc('victoria@example.com');
$mailable->assertHasReplyTo('tyler@example.com');
$mailable->assertHasSubject('Invoice Paid');
$mailable->assertHasTag('example-tag');
$mailable->assertHasMetadata('key', 'value');
$mailable->assertSeeInHtml($user->email);
$mailable->assertDontSeeInHtml('Invoice Not Paid');
$mailable->assertSeeInOrderInHtml(['Invoice Paid', 'Thanks']);
$mailable->assertSeeInText($user->email);
$mailable->assertDontSeeInText('Invoice Not Paid');
$mailable->assertSeeInOrderInText(['Invoice Paid', 'Thanks']);
решта розділу ще не перекладена - Testing Mailable Content (кінець підрозділу, зокрема варіант PHPUnit і перевірки вкладень), Testing Mailable Sending, Mail and Local Development, Events, Custom Transports, Additional Symfony Transports.
Перекладаємо з офіційної документації, розділ за розділом, і не ховаємо недоперекладене. Помітили неточність у терміні чи реченні: напишіть, виправимо.