Почта
Содержание:
Введение
Laravel предосталвяет простой и понятный API для популярной
библиотеку SwiftMailer с драйверами
для SMTP, Mailgun, Postmark, Amazon SES и sendmail
. Это позволяет вам начать
отправлять почту на локальной версии или сервисе основанным на облаке, на ваш выбор.
Требования к драйверу
Основанные на API драйверы, такие как Mailgun или Postmark часто проще и быстрее чем сервера SMTP.
Если возможно, вам стоит использовать один из этих драйверов. Все API драйверы требуют
библиотеку HTTP Guzzle, которая может быть установлена через Composer:
composer require guzzlehttp/guzzle
Драйвер Mailgun
Чтобы использовать драйвер Mailgun, нужно сначала установить Guzzle, после чего установить
значение опции driver
в файле конфигурации config/mail.php
на
mailgun
. Следующим шагом необходимо убедиться в том, что ваш файл конфигурации
config/services.php
содержит следующие строки:
'mailgun' => [
'domain' => 'your-mailgun-domain',
'secret' => 'your-mailgun-key',
],
Если вы не используете "US"
регион Mailgun,
вы можете определить ваш регион в файле конфигурации services
:
'mailgun' => [
'domain' => 'your-mailgun-domain',
'secret' => 'your-mailgun-key',
'endpoint' => 'api.eu.mailgun.net',
],
Драйвер Postmark
Чтобы использовать драйвер Postmark, установить SwiftMailer для Postmark через Composer:
composer require wildbit/swiftmailer-postmark
После чего необходимо установить Guzzle и прописать опцию driver
как postmark
в вашем файле конфигурации config/mail.php
. Наконец, необходимо провести сверку
в вашем файле конфиграции config/services.php
на предмет наличия следующих строк:
'postmark' => [
'token' => 'your-postmark-token',
],
Драйвер SES
Чтобы использовать драйвер Amazon SES понадобится установить AWS SDK для PHP.
Вы можете установить эту библиотеку путём добавления следующих строк для файла composer.json
секции require
и запустить команду composer update
:
"aws/aws-sdk-php": "~3.0"
После, установите опцию driver
в вашем файле конфигурации config/mail.php
в значение ses
и проведите проверку наличия следующих строк в файле
config/services.php
:
'ses' => [
'key' => 'your-ses-key',
'secret' => 'your-ses-secret',
'region' => 'ses-region', // e.g. us-east-1
],
Если вам необходимо включить
дополнительные опции,
при выполнении запроса SES SendRawEmail
, вы можете определить массив options
внутри
вашей конфигурации ses
:
'ses' => [
'key' => 'your-ses-key',
'secret' => 'your-ses-secret',
'region' => 'ses-region', // e.g. us-east-1
'options' => [
'ConfigurationSetName' => 'MyConfigurationSet',
'Tags' => [
[
'Name' => 'foo',
'Value' => 'bar',
],
],
],
],
Генерация почты
В Ларавел каждый тип электронной почты, отправляемый вашем приложением,
представлен как класс "mailable"
Эти классы хранятся в папке app/Mail
.
Не нужно беспокоится, если вы не видите такой папки в приложении,
потому что она будем создана в момент, когда вы первый раз создадите класс mailable
используя команду make:mail
:
php artisan make:mail OrderShipped
Написание почты
Вся конфигурация класса mailable
уже реализована в методе build
.
Внутри этого метода вы можете вызывать различные методы такие как from
,
subject
, view
, и attach
, чтобы настроить вид письма и
другие данные отправки такие как от
, тема
.
Настройка отправителя
Использование метода from
Во-первых, давайте настроим отправителя письма. Или какой адрес в письме будет
отображаться для поля "from". Существует 2 способа настроить отправителя.
Во-первых, вы можете использовать метод from
внутри класса mailable
метода build
:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from('example@example.com')
->view('emails.orders.shipped');
}
Использование глобального адреса from
Если ваше приложение использует одинаковый адрес "from" для всех писмем электронной почты,
может быть не практично вызывать метод from
в каждом классе, который вы сгенерировали.
Вместо этого, вы можете указать глобальный "from" в файле конфигурации config/mail.php
.
Этот адрес будет использоваться по умолчанию, если не указан другой "from" внутри класса:
'from' => ['address' => 'example@example.com', 'name' => 'App Name'],
In addition, you may define a global "reply_to" address within your config/mail.php
configuration file:
'reply_to' => ['address' => 'example@example.com', 'name' => 'App Name'],
Настройка вида
Внутри метода build
класса mailable
, вы можете использовать
метод view
для указания шаблона, который необходимо использовать
при генерации содержимого письма. В силу того, что каждое электронное письмо использует
шаблонизатор Blade для отображения контента,
вы можете использовать всю мощь шаблонизатора Blade
при составлениии электронных писем:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped');
}
Вы можете создать директорию resources/views/emails
для хранения всех ваших
шаблонов писем. Можно располагать и в любой другой папке внутри директории
resources/views
.
Обычные текстовые письма
Если вы хотите определить обычную версию вашего электронного письма, вы можете использовать
метод text
. Как и в случае с методом view
, метод text
принимает метод шаблона, который будет использован для отображения контента электронного письма.
Вы можете определить как HTML версию письма, так и текстовую версию сообщения:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped')
->text('emails.orders.shipped_plain');
}
Отображение данных
Через публичные свойства
Обычно, вы хотите передать некоторые данные в ваше представлеине, которые вы можете использовать
при рендеринге HTML электронного письма. Есть два способа сделать данные доступными для представления.
Во-первых, любые публичные свойства, определённые в вашем классе mailable, будут автоматически доступны
для вашего представления. Поэтому, например, вы можете передать данные в конструктор почтового класса
и установить данные как общедоступные свойства, определённые на классе:
<?php
namespace App\Mail;
use App\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class OrderShipped extends Mailable
{
use Queueable, SerializesModels;
/**
* The order instance.
*
* @var Order
*/
public $order;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped');
}
}
После добавления данных в публичные свойства, они атоматически будут доступны
для вашего представления, поэтому вы сможете обратиться к ним также,
как и к любым другим данным в шаблоне Blade:
<div>
Price: {{ $order->price }}
</div>
Через метод with
:
Если вы хотите настроить данные электронного письма до момента их отправки в шаблон,
вы можете вручную передать ваше данные в представление через метод with
.
Обыкновенно, вы все равно будете передавать данные через конструктор. Однако, для данных установлены
свойства protected
или private
, таким образом данные не доступны для
шаблона автоматически. Поэтому, необходимо передавать данные в виде массива
через вызов метод with
:
<?php
namespace App\Mail;
use App\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class OrderShipped extends Mailable
{
use Queueable, SerializesModels;
/**
* The order instance.
*
* @var Order
*/
protected $order;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped')
->with([
'orderName' => $this->order->name,
'orderPrice' => $this->order->price,
]);
}
}
После того, как данные были прикреплены через метод with
,
вы можете использовать их также, как и любые другие данные в вашем Blade шаблоне:
<div>
Price: {{ $orderPrice }}
</div>
Прикреплённые фалы
Чтобы добавить вложения к письму, используйте метод attach
внутри метода build
почтового класса. Метод attach
принимает полный путь
до файла в качестве первого аргумента:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped')
->attach('/path/to/file');
}
Прикрепляя файл к сообщению, вы можете также указать отображаемое имя и / или MIME тип
путём передачи массива в качестве второго аргумента в метод attach
:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped')
->attach('/path/to/file', [
'as' => 'name.pdf',
'mime' => 'application/pdf',
]);
}
Прикрепление файлов из диска
Если вы храните файл на одном из ваших дисков,
вы можте прикрепить их к электронному письму используя метод attachFromStorage
:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('email.orders.shipped')
->attachFromStorage('/path/to/file');
}
Если необходимо, вы можете указать имя для прикрепляемого файла и дополнительные опции используя
второй и третий аргумент для метода attachFromStorage
:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('email.orders.shipped')
->attachFromStorage('/path/to/file', 'name.pdf', [
'mime' => 'application/pdf'
]);
}
Метод attachFromStorageDisk
можно использовать в случае, когда необходимо
указать диск хранения, который отличается от диска по умолчанию:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('email.orders.shipped')
->attachFromStorageDisk('s3', '/path/to/file');
}
Прикрепление необработанных данных
Метод attachData
может быть использован для того, чтобы прикрепить набор данных
в качестве вложения. Например, вы можете использовать этот метод, если вы хотите сгенерировать
файл PDF в памяти и хотите вложить этот файл в письмо без сохранения на диск.
Метод attachData
принимает набор данных в качестве первого аргумента,
название в качестве второго аргумента и массив опций как третий аргумент:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->view('emails.orders.shipped')
->attachData($this->pdf, 'name.pdf', [
'mime' => 'application/pdf',
]);
}
Вписанные файлы
Вложение изображений в ваши электронные письма обычно может быть обременительным.
Ларавел предоставляет удобный способ присоединить изображения в ваши электронные письма
и получить соответсвующий CID. Чтобы добавить изображение используйте метод embed
для переменной $message
внутри вашего шаблона письма. Ларавел автоматически делает
переменную $message
доступной для всех ваших шаблонов писем,
поэтому у вас нет необходимости беспокоится о том, чтобы передавать переменную вручную:
<body>
Here is an image:
<img src="{{ $message->embed($pathToImage) }}">
</body>
Переменная $message
не доступна для текстовых сообщений в силу того,
что сами вложения не доступны для таких вложений.
Вписать необработанные данные во вложения
Если у вас есть данные, которые вы хотели бы вписать в шаблон электронного письма,
вы можете использовать метод embedData
для переменной $message
:
<body>
Here is an image from raw data:
<img src="{{ $message->embedData($data, $name) }}">
</body>
Настройка сообщений SwiftMailer
Метод withSwiftMessage
для класса Mailable
позволяет вам
регистрировать обратную связь, которая будет вызвана с необработанных экземпляром сообщения SwiftMailer
до момента отправки сообщения.
Это даёт вам возможность настроить сообщение до того, как оно будет доставлено:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$this->view('emails.orders.shipped');
$this->withSwiftMessage(function ($message) {
$message->getHeaders()
->addTextHeader('Custom-Header', 'HeaderValue');
});
}
Шаблоны писем
Разметка писем позволяет вам получить все преимущества предварительного построения
шаблонов и компонентов в ваших письмах. В силу того, что письма написаны в Markdown,
Laravel позволяет генерировать красивые, адаптивные шаблоны HTML для сообщений,
в тоже время как автоматически генерируется аналог обычного письма.
Генерация шаблонов писем
Чтобы сгенерировать шаблон с разметкой Markdown, вы можете использовать опцию --markdown
для команды Artisan make:mail
:
php artisan make:mail OrderShipped --markdown=emails.orders.shipped
После, при настройке писем внутри метода build
, вызывайте метод markdown
вместео метода view
. Метод markdown
принимает имя шаблона Markdown и
опционально массив данных для доступа в шаблон:
/**
* Build the message.
*
* @return $this
*/
public function build()
{
return $this->from('example@example.com', 'Example')
->markdown('emails.orders.shipped');
}
Написаине шаблона письма
Шаблоны используют комбинацию компонентов Blade и синтакс Markdown, который позволяет
вам легко строить сообщения при использовании готовых компонентов Laravel:
@component('mail::message')
# Order Shipped
Your order has been shipped!
@component('mail::button', ['url' => $url])
View Order
@endcomponent
Thanks,<br>
{{ config('app.name') }}
@endcomponent
Не используйте лишние отступы при написании писем с Markdown, потому что парсер выведет
содержимое с отступами как блоки кода.
Компонент Button
Компонент Button отображает центрированную ссылку в виде кнопки. Компонент принимает два аргумента:
url
и дополнительный color
. Есть ряд поддерживаемых цветов:
primary
, success
, и error
.
Вы можете добавить так много кнопок в сообщение как считаете нужным:
@component('mail::button', ['url' => $url, 'color' => 'success'])
View Order
@endcomponent
Компонент Panel
Компонент отображает данный блок текста в панели, у которой немного отличается цвет фона
от остального сообщения. Это позволяет вам обратить внимание на данный блок текста:
@component('mail::panel')
This is the panel content.
@endcomponent
Компонент Table
Компонент позволяет вам трансформировать таблицу Markdown в обыкновенную HTML таблицу.
Компонент принимает таблицу в качестве содержимого. Поддерживается различное центрирование
в колонках при помощи синтаксиса Markdown для таблиц:
@component('mail::table')
| Laravel | Table | Example |
| ------------- |:-------------:| --------:|
| Col 2 is | Centered | $10 |
| Col 3 is | Right-Aligned | $20 |
@endcomponent
Настрока компонентов
Вы можете экспортировать все компоненты писем Markdown в ваше приложение для настройки.
Чтобы это сделать, можно использовать команду Artisan vendor:publish
для публикации тэга 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 в файле
и ваши стили будут автоматически вписаны внутри HTML представления вашего сообщения.
Если вы хотите построить построить полностью новую тему для компонентов Laravel Markdown,
вы можете разместить файл CSS внутри директории html/themes
. После того,
как вы назвали и сохранили файл CSS, обновите опцию theme
файла конфигурации
mail
таким образом, чтобы оно соответсвовало названию вашей новой темы.
Для настройки темы для индивидуального сообщения, вы можете установить свойство $theme
класса mailable как имя темы, которая будет использована при отправке сообщения.
Отправка почты
Для отправки сообщения, используйте метод to
для фасада Mail
.
Метод to
принимает адрес электронной почты, экземпляр пользователя
или коллекцию пользователей. Если вы передадите объект или коллекцию объектов, почтовик
автоматически использует их свойтсва email
и name
при установке
получателей электронной почты. Поэтому, убедитесь в том, что эти атрибуды доступны для
ваших объектов. После того, как вы указали получателей, вы можете передать экзепляр
класса почты в метод send
:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Mail\OrderShipped;
use App\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
class OrderController extends Controller
{
/**
* Ship the given order.
*
* @param Request $request
* @param int $orderId
* @return Response
*/
public function ship(Request $request, $orderId)
{
$order = Order::findOrFail($orderId);
// Ship order...
Mail::to($request->user())->send(new OrderShipped($order));
}
}
Вы не ограничены тем, чтобы просто указывать получателей "to" при отправке сообщения.
Вы можете указывать получателей "to", "cc", и "bcc"
внутри одного одиночного замкнутого вызова метода:
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->send(new OrderShipped($order));
Очереди писем
Постановка в очередь сообщений
В силу того, что отправка большого числа сообщений может существенным образом увеличить время ответа
вашего приложения, много разработчкиов выбирают постановку сообщений в очередь для фоновой отправки.
Ларавел позволяет сделать это легко используя встроенное
унифицированне API для очередей.
Чтобы добавить сообщение почты, используйте метод queue
для фасада
Mail
после указания получателей сообщений:
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->queue(new OrderShipped($order));
Этот метод автоматически добавляет пункт в очередь, таким образом сообщение отправляется фоном.
Вам потребуется настроить ваши очереди до использования этой особенности.
Отложенна очередь сообщений
Если вы хотите отложить доставку сообщения из очереди, вы можете использовать метод
later
. В качестве первого аргумента, метод later
принимает
экземпляр DateTime
, который показывает когда сообщение должно отправляться:
$when = now()->addMinutes(10);
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->later($when, new OrderShipped($order));
Проталкивание к определённым очередям
В силу того, что все почтовые классы сгенерированные с использованием команды make:mail
используют трейт Illuminate\Bus\Queueable
, вы можете применить методы
onQueue
и onConnection
к любому почтовому класса.
Они позволяют вам указать соединение и имя очереди для сообщения:
$message = (new OrderShipped($order))
->onConnection('sqs')
->onQueue('emails');
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->queue($message);
Постановка в очередь по умолчанию
Если у вас есть почтовые классы, которые вы бы хотели видеть всегда в очереди,
вы можете расширить контракт ShouldQueue
классам. Теперь , даже если
вы вызываете метод send
при работе, то сообщение все равно будет
добавляться в очередь в силу расширения контракта, а не отправляться напрямую:
use Illuminate\Contracts\Queue\ShouldQueue;
class OrderShipped extends Mailable implements ShouldQueue
{
//
}
Генерация писем
Иногда вы можете захотеть получить HTML контент письма без его отправки.
Чтобы справится с этим, вы можете вызвать метод render
.
Этот метод вернёт конечный контент письма в качестве строки:
$invoice = App\Invoice::find(1);
return (new App\Mail\InvoicePaid($invoice))->render();
Предпросмотр письма в браузере
При разработке шаблона письма, удобно просматривать сгенерированное письма в вашем браузере
как обчный шаблон Blade. По этой причине, Ларавел позоляет вам возвращать
любое письмо напрямую из пути или контроллера. Когда письмо возвращается, оно будет
отрисовано и отобразится в вашем браузере. Этот позволяет быстро просматривать содержимое
письма без необходимости отправлять его на определённый почтовый ящик:
Route::get('mailable', function () {
$invoice = App\Invoice::find(1);
return new App\Mail\InvoicePaid($invoice);
});
Локализация почты
Ларавел позволяет вам отправлять сообщения на различных языках, в том числе отличных от текущего.
Даже запомнит указанный язык, если письмо добавлено в очередь.
Чтобы справиться с этой задачей, фасад Mail
предлагает метод locale
для установки языка. Приложение автоматически поменяет на эту локаль
во время форматирования сообщения и вернёт предыдущую локаль после завершения форматирования:
Mail::to($request->user())->locale('es')->send(
new OrderShipped($order)
);
Избранные локали пользователя
Иногда, приложения хранят выбранные локали для каждого пользователя. Путём расширения
контракта HasLocalePreference
одной или более вашей модели, вы можете
научить Ларавел использовать сохранённые локали при отправке письма:
use Illuminate\Contracts\Translation\HasLocalePreference;
class User extends Model implements HasLocalePreference
{
/**
* Get the user's preferred locale.
*
* @return string
*/
public function preferredLocale()
{
return $this->locale;
}
}
После вашего расширения интрефейса, Ларавел будет автоматически использовать выбранную локаль
при отправке писем и уведомлений в модель. Поэтому, больше нет необходимости вызывать
метод locale
при использовании интерфейса:
Mail::to($request->user())->send(new OrderShipped($order));
Почта и локальная разработка
При разработке приложений, которые должны отправлять письма, вам и не нужно отправлять сообщения
на реальный почтовый ящик. Ларавел предлагает несколько путей для отмены фактической отправки
писем во время локальной разработки.
Лог-драйвер
Вместо отправки сообщений, драйвер почты log
будет записывать все ваши сообщения
в ваши лог-файлы для инспектирования. Для большей информации о таком окружении для приложения
проверьте документацию
конфигурации.
Универсальное поле "кому"
Другое решение включенное в Ларавел — это установить универсального получателя писем фреймворка.
В этом случае, все письма сгенерированные приложением будут отправлять на указанный адрес,
вместо адреса, указанного при отправке сообщение. Так можно сделать через опцию
to
в файле конфигурации config/mail.php
:
'to' => [
'address' => 'example@example.com',
'name' => 'Example'
],
Mailtrap
Наконец, вы можете использовать сервис, такой как Mailtrap и
драйвер smtp
для отправки электронных сообщений на виртуальный почтовый ящик,
где вы можете просмотерть их в реальном почтовом клиенте. Такой подход предоставляет возможность
инспектировать конечные письма через клиент Mailtrap.
События
Ларавел запускает два события в процессе отправки сообщений почты.
Событие MessageSending
запускается до момента отправки сообщения, в то время как
событие MessageSent
будет запущено после отправки сообщения. Нужно запомнить, эти события
запускаются при запускаются при отправке sent сообщений, а не при добавления в очередь.
Вы можете зараегистрировать слушателя события для этого события в вашем
EventServiceProvider
:
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'Illuminate\Mail\Events\MessageSending' => [
'App\Listeners\LogSendingMessage',
],
'Illuminate\Mail\Events\MessageSent' => [
'App\Listeners\LogSentMessage',
],
];