Introduction
メール送信は複雑である必要はありません。Laravelは、人気のある Symfony Mailer コンポーネントによって支えられたクリーンでシンプルなメールAPIを提供します。LaravelとSymfony Mailerは、SMTP、Mailgun、Postmark、Resend、Amazon SES、および sendmail
を介してメールを送信するためのドライバーを提供し、選択したローカルまたはクラウドベースのサービスを通じて迅速にメールを送信することができます。
Configuration
Laravelのメールサービスは、アプリケーションの config/mail.php
設定ファイルを介して構成できます。このファイル内で構成された各メール送信者は、独自の設定を持つことができ、特定のメールメッセージを送信するために異なるメールサービスを使用することができます。たとえば、アプリケーションは、トランザクションメールを送信するためにPostmarkを使用し、バルクメールを送信するためにAmazon SESを使用することがあります。
mail
設定ファイル内には、mailers
設定配列が見つかります。この配列には、Laravelがサポートする主要なメールドライバー/トランスポートの各サンプル設定エントリが含まれており、default
設定値は、アプリケーションがメールメッセージを送信する必要があるときに使用されるデフォルトのメール送信者を決定します。
Driver / Transport Prerequisites
Mailgun、Postmark、Resend、MailerSendなどのAPIベースのドライバーは、SMTPサーバーを介してメールを送信するよりも簡単で迅速であることが多いです。可能な限り、これらのドライバーのいずれかを使用することをお勧めします。
Mailgun Driver
Mailgunドライバーを使用するには、Composerを介してSymfonyのMailgun Mailerトランスポートをインストールします:
composer require symfony/mailgun-mailer symfony/http-client
次に、アプリケーションの config/mail.php
設定ファイル内で default
オプションを mailgun
に設定し、mailers
の配列に次の設定配列を追加します:
'mailgun' => [
'transport' => 'mailgun',
// 'client' => [
// 'timeout' => 5,
// ],
],
アプリケーションのデフォルトのメール送信者を構成した後、config/services.php
設定ファイルに次のオプションを追加します:
'mailgun' => [
'domain' => env('MAILGUN_DOMAIN'),
'secret' => env('MAILGUN_SECRET'),
'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
'scheme' => 'https',
],
アメリカ合衆国の Mailgun地域 を使用していない場合は、services
設定ファイルで地域のエンドポイントを定義できます:
'mailgun' => [
'domain' => env('MAILGUN_DOMAIN'),
'secret' => env('MAILGUN_SECRET'),
'endpoint' => env('MAILGUN_ENDPOINT', 'api.eu.mailgun.net'),
'scheme' => 'https',
],
Postmark Driver
Postmark ドライバーを使用するには、Composerを介してSymfonyのPostmark Mailerトランスポートをインストールします:
composer require symfony/postmark-mailer symfony/http-client
次に、アプリケーションの config/mail.php
設定ファイル内で default
オプションを postmark
に設定します。アプリケーションのデフォルトのメール送信者を構成した後、config/services.php
設定ファイルに次のオプションが含まれていることを確認します:
'postmark' => [
'token' => env('POSTMARK_TOKEN'),
],
特定のメール送信者が使用するPostmarkメッセージストリームを指定したい場合は、メール送信者の設定配列に message_stream_id
設定オプションを追加できます。この設定配列は、アプリケーションの config/mail.php
設定ファイルにあります:
'postmark' => [
'transport' => 'postmark',
'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'),
// 'client' => [
// 'timeout' => 5,
// ],
],
この方法で、異なるメッセージストリームを持つ複数のPostmarkメール送信者を設定することもできます。
Resend Driver
Resend ドライバーを使用するには、Composerを介してResendのPHP SDKをインストールします:
composer require resend/resend-php
次に、アプリケーションの config/mail.php
設定ファイル内で default
オプションを resend
に設定します。アプリケーションのデフォルトのメール送信者を構成した後、config/services.php
設定ファイルに次のオプションが含まれていることを確認します:
'resend' => [
'key' => env('RESEND_KEY'),
],
SES Driver
Amazon SESドライバーを使用するには、まずAmazon AWS SDK for PHPをインストールする必要があります。このライブラリはComposerパッケージマネージャーを介してインストールできます:
composer require aws/aws-sdk-php
次に、config/mail.php
設定ファイル内の default
オプションを 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 一時的な資格情報 をセッショントークンを介して利用するには、アプリケーションのSES設定に token
キーを追加できます:
'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の サブスクリプション管理機能 と対話するには、メールメッセージの headers
メソッドによって返される配列に X-Ses-List-Management-Options
ヘッダーを返すことができます:
/**
* Get the message headers.
*/
public function headers(): Headers
{
return new Headers(
text: [
'X-Ses-List-Management-Options' => 'contactListName=MyContactList;topicName=MyTopic',
],
);
}
Laravelがメールを送信する際にAWS SDKの SendEmail
メソッドに渡す 追加オプション を定義したい場合は、ses
設定内に options
配列を定義できます:
'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'],
],
],
],
MailerSend Driver
MailerSend は、トランザクションメールとSMSサービスであり、Laravel用の独自のAPIベースのメールドライバーを維持しています。ドライバーを含むパッケージは、Composerパッケージマネージャーを介してインストールできます:
composer require mailersend/laravel-driver
パッケージがインストールされたら、アプリケーションの .env
ファイルに MAILERSEND_API_KEY
環境変数を追加します。さらに、MAIL_MAILER
環境変数は mailersend
として定義する必要があります:
MAIL_MAILER=mailersend
MAIL_FROM_ADDRESS=
MAIL_FROM_NAME="App Name"
MAILERSEND_API_KEY=your-api-key
最後に、アプリケーションの config/mail.php
設定ファイルの mailers
配列にMailerSendを追加します:
'mailersend' => [
'transport' => 'mailersend',
],
MailerSendについての詳細、特にホストされたテンプレートの使用方法については、MailerSendドライバーのドキュメントを参照してください。
Failover Configuration
時には、アプリケーションのメールを送信するために構成された外部サービスがダウンしていることがあります。このような場合、プライマリ配信ドライバーがダウンした場合に使用される1つ以上のバックアップメール配信構成を定義することが有用です。
これを実現するには、アプリケーションの mail
設定ファイル内で failover
トランスポートを使用するメール送信者を定義する必要があります。アプリケーションの failover
メール送信者の設定配列には、構成されたメール送信者が配信のために選択される順序を参照する mailers
の配列が含まれている必要があります:
'mailers' => [
'failover' => [
'transport' => 'failover',
'mailers' => [
'postmark',
'mailgun',
'sendmail',
],
],
// ...
],
フェイルオーバーメール送信者が定義されたら、アプリケーションの mail
設定ファイル内で default
設定キーの値としてそのメール送信者の名前を指定することによって、このメール送信者をアプリケーションで使用されるデフォルトのメール送信者として設定する必要があります:
'default' => env('MAIL_MAILER', 'failover'),
Round Robin Configuration
roundrobin
トランスポートを使用すると、複数のメール送信者にメールの作業負荷を分散できます。始めるには、アプリケーションの mail
設定ファイル内で roundrobin
トランスポートを使用するメール送信者を定義します。アプリケーションの roundrobin
メール送信者の設定配列には、配信に使用される構成されたメール送信者を参照する mailers
の配列が含まれている必要があります:
'mailers' => [
'roundrobin' => [
'transport' => 'roundrobin',
'mailers' => [
'ses',
'postmark',
],
],
// ...
],
ラウンドロビンメール送信者が定義されたら、アプリケーションの mail
設定ファイル内で default
設定キーの値としてそのメール送信者の名前を指定することによって、このメール送信者をアプリケーションで使用されるデフォルトのメール送信者として設定する必要があります:
'default' => env('MAIL_MAILER', 'roundrobin'),
ラウンドロビントランスポートは、構成されたメール送信者のリストからランダムなメール送信者を選択し、次のメールごとに次の利用可能なメール送信者に切り替えます。 高可用性 を達成するのに役立つ failover
トランスポートとは対照的に、roundrobin
トランスポートは 負荷分散 を提供します。
Generating Mailables
Laravelアプリケーションを構築する際、アプリケーションによって送信される各タイプのメールは「マイベール」クラスとして表されます。これらのクラスは app/Mail
ディレクトリに保存されます。このディレクトリがアプリケーションに表示されない場合でも心配しないでください。最初のマイベールクラスを make:mail
Artisanコマンドを使用して作成すると、自動的に生成されます:
php artisan make:mail OrderShipped
Writing Mailables
マイベールクラスを生成したら、それを開いて内容を探求しましょう。マイベールクラスの設定は、envelope
、content
、および attachments
メソッドを含むいくつかのメソッドで行われます。
envelope
メソッドは、メッセージの件名と、場合によっては受信者を定義する Illuminate\Mail\Mailables\Envelope
オブジェクトを返します。content
メソッドは、メッセージ内容を生成するために使用される Illuminate\Mail\Mailables\Content
オブジェクトを返します。
Configuring the Sender
Using the Envelope
まず、メールの送信者を構成する方法を探求しましょう。つまり、メールが「送信元」として誰になるかです。送信者を構成する方法は2つあります。まず、メッセージの封筒で「送信元」アドレスを指定できます:
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Envelope;
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
from: new Address('', 'Jeffrey Way'),
subject: 'Order Shipped',
);
}
必要に応じて、replyTo
アドレスを指定することもできます:
return new Envelope(
from: new Address('', 'Jeffrey Way'),
replyTo: [
new Address('', 'Taylor Otwell'),
],
subject: 'Order Shipped',
);
Using a Global from Address
ただし、アプリケーションがすべてのメールに同じ「送信元」アドレスを使用する場合、生成する各マイベールクラスにそれを追加するのは面倒になる可能性があります。代わりに、config/mail.php
設定ファイルにグローバルな「送信元」アドレスを指定できます。このアドレスは、マイベールクラス内で他の「送信元」アドレスが指定されていない場合に使用されます:
'from' => [
'address' => env('MAIL_FROM_ADDRESS', ''),
'name' => env('MAIL_FROM_NAME', 'Example'),
],
さらに、config/mail.php
設定ファイル内にグローバルな「reply_to」アドレスを定義できます:
'reply_to' => ['address' => '', 'name' => 'App Name'],
Configuring the View
マイベールクラスの content
メソッド内で、メールの内容をレンダリングする際に使用する view
を定義できます。各メールは通常、内容をレンダリングするために Bladeテンプレート を使用するため、メールのHTMLを構築する際にBladeテンプレートエンジンの完全な力と便利さを利用できます:
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'mail.orders.shipped',
);
}
すべてのメールテンプレートを格納する resources/views/emails
ディレクトリを作成することをお勧めしますが、resources/views
ディレクトリ内の任意の場所に配置することも自由です。
Plain Text Emails
メールのプレーンテキストバージョンを定義したい場合は、メッセージの Content
定義を作成する際にプレーンテキストテンプレートを指定できます。view
パラメータと同様に、text
パラメータはメールの内容をレンダリングするために使用されるテンプレート名である必要があります。メッセージのHTMLバージョンとプレーンテキストバージョンの両方を定義することができます:
/**
* Get the message content definition.
*/
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 Data
Via Public Properties
通常、メールのHTMLをレンダリングする際に利用できるデータをビューに渡したいと思います。ビューにデータを利用可能にする方法は2つあります。まず、マイベールクラスで定義された任意のパブリックプロパティは、自動的にビューに利用可能になります。たとえば、マイベールクラスのコンストラクタにデータを渡し、そのデータをクラスで定義されたパブリックプロパティに設定できます:
<?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;
/**
* Create a new message instance.
*/
public function __construct(
public Order $order,
) {}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'mail.orders.shipped',
);
}
}
データがパブリックプロパティに設定されると、それは自動的にビューで利用可能になり、Bladeテンプレート内の他のデータにアクセスするのと同様にアクセスできます:
<div>
Price: {{ $order->price }}
</div>
Via the with Parameter:
メールのデータの形式をカスタマイズしてからテンプレートに送信したい場合は、Content
定義の with
パラメータを介して手動でデータをビューに渡すことができます。通常、マイベールクラスのコンストラクタを介してデータを渡しますが、このデータを 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;
/**
* Create a new message instance.
*/
public function __construct(
protected Order $order,
) {}
/**
* Get the message content definition.
*/
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
メールに添付ファイルを追加するには、メッセージの attachments
メソッドによって返される配列に添付ファイルを追加します。まず、fromPath
メソッドを使用してファイルパスを提供することで添付ファイルを追加できます:
use Illuminate\Mail\Mailables\Attachment;
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [
Attachment::fromPath('/path/to/file'),
];
}
メッセージにファイルを添付する際、as
および withMime
メソッドを使用して添付ファイルの表示名および/またはMIMEタイプを指定することもできます:
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [
Attachment::fromPath('/path/to/file')
->as('name.pdf')
->withMime('application/pdf'),
];
}
Attaching Files From Disk
ファイルシステムディスクの1つにファイルを保存している場合は、fromStorage
添付メソッドを使用してメールに添付できます:
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [
Attachment::fromStorage('/path/to/file'),
];
}
もちろん、添付ファイルの名前とMIMEタイプを指定することもできます:
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [
Attachment::fromStorage('/path/to/file')
->as('name.pdf')
->withMime('application/pdf'),
];
}
fromStorageDisk
メソッドは、デフォルトのディスク以外のストレージディスクを指定する必要がある場合に使用できます:
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [
Attachment::fromStorageDisk('s3', '/path/to/file')
->as('name.pdf')
->withMime('application/pdf'),
];
}
Raw Data Attachments
fromData
添付メソッドは、生のバイト列を添付ファイルとして添付するために使用できます。たとえば、メモリ内でPDFを生成し、それをディスクに書き込まずにメールに添付したい場合にこのメソッドを使用することがあります。fromData
メソッドは、生データバイトと添付ファイルに割り当てる名前を解決するクロージャを受け入れます:
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [
Attachment::fromData(fn () => $this->pdf, 'Report.pdf')
->withMime('application/pdf'),
];
}
Inline Attachments
メールにインライン画像を埋め込むことは通常面倒ですが、Laravelはメールに画像を添付する便利な方法を提供します。インライン画像を埋め込むには、メールテンプレート内の embed
メソッドを使用します。Laravelは自動的に $message
変数をすべてのメールテンプレートに利用可能にするため、手動で渡す必要はありません:
<body>
Here is an image:
<img src="{{ $message->embed($pathToImage) }}">
</body>
$message
変数は、プレーンテキストメッセージテンプレートでは利用できません。プレーンテキストメッセージはインライン添付ファイルを利用しないためです。
Embedding Raw Data Attachments
メールテンプレートに埋め込みたい生の画像データ文字列がすでにある場合は、embedData
メソッドを $message
変数で呼び出すことができます。embedData
メソッドを呼び出す際には、埋め込む画像に割り当てるファイル名を提供する必要があります:
<body>
Here is an image from raw data:
<img src="{{ $message->embedData($data, 'example-image.jpg') }}">
</body>
Attachable Objects
メッセージにファイルを添付する際に単純な文字列パスを使用することはしばしば十分ですが、多くの場合、アプリケーション内の添付可能なエンティティはクラスによって表されます。たとえば、アプリケーションがメッセージに写真を添付している場合、アプリケーションにはその写真を表す 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
{
/**
* Get the attachable representation of the model.
*/
public function toMailAttachment(): Attachment
{
return Attachment::fromPath('/path/to/file');
}
}
添付可能なオブジェクトを定義したら、メールメッセージを構築する際に attachments
メソッドからそのオブジェクトのインスタンスを返すことができます:
/**
* Get the attachments for the message.
*
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [$this->photo];
}
もちろん、添付データはAmazon S3などのリモートファイルストレージサービスに保存される場合があります。したがって、Laravelは、アプリケーションの ファイルシステムディスク の1つに保存されているデータから添付インスタンスを生成することも許可します:
// Create an attachment from a file on your default disk...
return Attachment::fromStorage($this->path);
// Create an attachment from a file on a specific disk...
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');
Headers
時には、送信メッセージに追加のヘッダーを添付する必要がある場合があります。たとえば、カスタム Message-Id
やその他の任意のテキストヘッダーを設定する必要があるかもしれません。
これを実現するには、マイベールに headers
メソッドを定義します。headers
メソッドは Illuminate\Mail\Mailables\Headers
インスタンスを返す必要があります。このクラスは、messageId
、references
、および text
パラメータを受け入れます。もちろん、特定のメッセージに必要なパラメータのみを提供できます:
use Illuminate\Mail\Mailables\Headers;
/**
* Get the message headers.
*/
public function headers(): Headers
{
return new Headers(
messageId: '',
references: [''],
text: [
'X-Custom-Header' => 'Custom Value',
],
);
}
Tags and Metadata
MailgunやPostmarkなどの一部のサードパーティのメールプロバイダーは、アプリケーションによって送信されたメールをグループ化および追跡するために使用できるメッセージ「タグ」および「メタデータ」をサポートしています。メールメッセージにタグとメタデータを追加するには、Envelope
定義を介して行います:
use Illuminate\Mail\Mailables\Envelope;
/**
* Get the message 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を使用してメールを送信している場合は、metadata
メソッドを使用してメッセージに SES「タグ」 を添付する必要があります。
Customizing the Symfony Message
Laravelのメール機能はSymfony Mailerによって支えられています。Laravelは、メッセージを送信する前にSymfony Messageインスタンスで呼び出されるカスタムコールバックを登録することを許可します。これにより、メッセージが送信される前に深くカスタマイズする機会が得られます。これを実現するには、using
パラメータを Envelope
定義に定義します:
use Illuminate\Mail\Mailables\Envelope;
use Symfony\Component\Mime\Email;
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Order Shipped',
using: [
function (Email $message) {
// ...
},
]
);
}
Markdown Mailables
Markdownマイベールメッセージを使用すると、マイベール内の メール通知 の事前構築されたテンプレートとコンポーネントを活用できます。メッセージはMarkdownで書かれているため、Laravelはメッセージの美しいレスポンシブHTMLテンプレートをレンダリングでき、プレーンテキストの対応物も自動的に生成されます。
Generating Markdown Mailables
対応するMarkdownテンプレートを持つマイベールを生成するには、--markdown
オプションを make:mail
Artisanコマンドで使用します:
php artisan make:mail OrderShipped --markdown=mail.orders.shipped
次に、マイベール Content
定義を content
メソッド内で構成する際に、markdown
パラメータを view
パラメータの代わりに使用します:
use Illuminate\Mail\Mailables\Content;
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
markdown: 'mail.orders.shipped',
with: [
'url' => $this->orderUrl,
],
);
}
Writing Markdown Messages
Markdownマイベールは、BladeコンポーネントとMarkdown構文の組み合わせを使用して、メールメッセージを簡単に構築し、Laravelの事前構築されたメールUIコンポーネントを活用できます:
⟨x-mail::message⟩
# Order Shipped
ご注文が発送されました!
⟨x-mail::button :url="$url"⟩
注文を表示
⟨/x-mail::button⟩
ありがとうございます、⟨br⟩
{{ config('app.name') }}
⟨/x-mail::message⟩
Markdownメールを書く際に過剰なインデントを使用しないでください。Markdownの標準に従い、Markdownパーサーはインデントされたコンテンツをコードブロックとしてレンダリングします。
Button Component
ボタンコンポーネントは、中央に配置されたボタンリンクをレンダリングします。このコンポーネントは、url
とオプションの color
の2つの引数を受け入れます。サポートされている色は primary
、success
、および error
です。メッセージにボタンコンポーネントをいくつでも追加できます:
<x-mail::button :url="$url" color="success">
View Order
</x-mail::button>
Panel Component
パネルコンポーネントは、メッセージの残りの部分とはわずかに異なる背景色を持つパネル内に指定されたテキストブロックをレンダリングします。これにより、特定のテキストブロックに注意を引くことができます:
<x-mail::panel>
This is the panel content.
</x-mail::panel>
Table Component
テーブルコンポーネントを使用すると、MarkdownテーブルをHTMLテーブルに変換できます。このコンポーネントは、Markdownテーブルをその内容として受け入れます。テーブルの列の配置は、デフォルトのMarkdownテーブル配置構文を使用してサポートされています:
<x-mail::table>
| Laravel | Table | Example |
| ------------- | :-----------: | ------------: |
| Col 2 is | Centered | $10 |
| Col 3 is | Right-Aligned | $20 |
</x-mail::table>
Customizing the Components
すべてのMarkdownメールコンポーネントをカスタマイズのためにアプリケーションにエクスポートできます。コンポーネントをエクスポートするには、vendor:publish
Artisanコマンドを使用して laravel-mail
アセットタグを公開します:
php artisan vendor:publish --tag=laravel-mail
このコマンドは、Markdownメールコンポーネントを resources/views/vendor/mail
ディレクトリに公開します。mail
ディレクトリには、各利用可能なコンポーネントのそれぞれの表現を含む html
および text
ディレクトリが含まれます。これらのコンポーネントを自由にカスタマイズできます。
Customizing the CSS
コンポーネントをエクスポートした後、resources/views/vendor/mail/html/themes
ディレクトリには default.css
ファイルが含まれます。このファイル内のCSSをカスタマイズすると、スタイルはMarkdownメールメッセージのHTML表現内で自動的にインラインCSSスタイルに変換されます。
新しいテーマをLaravelのMarkdownコンポーネント用に完全に構築したい場合は、html/themes
ディレクトリ内にCSSファイルを配置できます。CSSファイルの名前を付けて保存した後、アプリケーションの config/mail.php
設定ファイルの theme
オプションを新しいテーマの名前に一致するように更新します。
個々のマイベールのテーマをカスタマイズするには、マイベールクラスの $theme
プロパティを、送信時に使用されるテーマの名前に設定します。
Sending Mail
メッセージを送信するには、to
メソッドを Mail
ファサード で使用します。to
メソッドは、メールアドレス、ユーザーインスタンス、またはユーザーのコレクションを受け入れます。オブジェクトまたはオブジェクトのコレクションを渡すと、メール送信者は自動的にそれらの email
および name
プロパティを使用してメールの受信者を決定しますので、これらの属性がオブジェクトに利用可能であることを確認してください。受信者を指定したら、send
メソッドにマイベールクラスのインスタンスを渡すことができます:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
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
{
/**
* Ship the given order.
*/
public function store(Request $request): RedirectResponse
{
$order = Order::findOrFail($request->order_id);
// Ship the order...
Mail::to($request->user())->send(new OrderShipped($order));
return redirect('/orders');
}
}
メッセージを送信する際に「宛先」受信者を指定するだけではありません。「宛先」、「CC」、および「BCC」受信者をそれぞれのメソッドを連鎖させて設定することができます:
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->send(new OrderShipped($order));
Looping Over Recipients
時には、受信者の配列/メールアドレスのリストに対してマイベールを送信する必要がある場合があります。ただし、to
メソッドは、メール送信者の受信者リストにメールアドレスを追加するため、ループを通じて各反復で以前の受信者全員に別のメールが送信されます。したがって、各受信者のためにマイベールインスタンスを再作成する必要があります:
foreach (['', ''] as $recipient) {
Mail::to($recipient)->send(new OrderShipped($order));
}
Sending Mail via a Specific Mailer
デフォルトでは、Laravelはアプリケーションの mail
設定ファイル内で default
メール送信者として構成されたメール送信者を使用してメールを送信します。ただし、mailer
メソッドを使用して特定のメール送信者構成を使用してメッセージを送信することができます:
Mail::mailer('postmark')
->to($request->user())
->send(new OrderShipped($order));
Queueing Mail
Queueing a Mail Message
メールメッセージを送信すると、アプリケーションの応答時間に悪影響を与える可能性があるため、多くの開発者はバックグラウンドで送信するためにメールメッセージをキューに入れることを選択します。Laravelは、組み込みの 統一キューAPI を使用してこれを簡単にします。メールメッセージをキューに入れるには、queue
メソッドを Mail
ファサードで使用し、メッセージの受信者を指定します:
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->queue(new OrderShipped($order));
このメソッドは、メッセージがバックグラウンドで送信されるようにジョブをキューにプッシュすることを自動的に処理します。この機能を使用する前に、キューを構成する 必要があります。
Delayed Message Queueing
キューに入れたメールメッセージの配信を遅延させたい場合は、later
メソッドを使用できます。最初の引数として、later
メソッドはメッセージが送信されるべき時期を示す DateTime
インスタンスを受け入れます:
Mail::to($request->user())
->cc($moreUsers)
->bcc($evenMoreUsers)
->later(now()->addMinutes(10), new OrderShipped($order));
Pushing to Specific Queues
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);
Queueing by Default
常にキューに入れたいマイベールクラスがある場合は、そのクラスに ShouldQueue
コントラクトを実装できます。これにより、メール送信時に send
メソッドを呼び出しても、マイベールは依然としてキューに入れられます。
use Illuminate\Contracts\Queue\ShouldQueue;
class OrderShipped extends Mailable implements ShouldQueue
{
// ...
}
Queued Mailables and Database Transactions
キューに入れられたマイベールがデータベーストランザクション内でディスパッチされると、データベーストランザクションがコミットされる前にキューによって処理される場合があります。この場合、データベーストランザクション中にモデルやデータベースレコードに加えた更新がデータベースにまだ反映されていない可能性があります。さらに、トランザクション内で作成されたモデルやデータベースレコードは、データベースに存在しない可能性があります。マイベールがこれらのモデルに依存している場合、キューに入れられたマイベールを送信するジョブが処理されるときに予期しないエラーが発生する可能性があります。
キュー接続の after_commit
設定オプションが false
に設定されている場合でも、メールメッセージを送信する際に afterCommit
メソッドを呼び出すことで、特定のキューに入れられたマイベールがすべてのオープンデータベーストランザクションがコミットされた後にディスパッチされるべきであることを示すことができます:
Mail::to($request->user())->send(
(new OrderShipped($order))->afterCommit()
);
または、マイベールのコンストラクタから afterCommit
メソッドを呼び出すこともできます:
<?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;
/**
* Create a new message instance.
*/
public function __construct()
{
$this->afterCommit();
}
}
これらの問題を回避する方法について詳しくは、キューされたジョブとデータベーストランザクション に関するドキュメントを確認してください。
メールのレンダリング
時には、メールを送信せずにメールのHTMLコンテンツをキャプチャしたい場合があります。これを実現するために、メールのrender
メソッドを呼び出すことができます。このメソッドは、メールの評価されたHTMLコンテンツを文字列として返します:
use App\Mail\InvoicePaid;
use App\Models\Invoice;
$invoice = Invoice::find(1);
return (new InvoicePaid($invoice))->render();
ブラウザでのメールのプレビュー
メールのテンプレートを設計する際、通常のBladeテンプレートのようにブラウザでレンダリングされたメールをすぐにプレビューできるのは便利です。このため、Laravelでは、ルートクロージャまたはコントローラから直接任意のメールを返すことができます。メールが返されると、それはレンダリングされ、ブラウザに表示され、実際のメールアドレスに送信することなくデザインをすぐにプレビューできます:
Route::get('/mailable', function () {
$invoice = App\Models\Invoice::find(1);
return new App\Mail\InvoicePaid($invoice);
});
メールのローカライズ
Laravelでは、リクエストの現在のロケールとは異なるロケールでメールを送信することができ、メールがキューに入れられた場合はこのロケールを記憶します。
これを実現するために、Mail
ファサードは、希望する言語を設定するためのlocale
メソッドを提供します。アプリケーションは、メールのテンプレートが評価されるときにこのロケールに変更され、評価が完了すると前のロケールに戻ります:
Mail::to($request->user())->locale('es')->send(
new OrderShipped($order)
);
ユーザーの好みのロケール
時には、アプリケーションが各ユーザーの好みのロケールを保存します。モデルの1つ以上でHasLocalePreference
契約を実装することで、Laravelにメールを送信する際にこの保存されたロケールを使用するよう指示できます:
use Illuminate\Contracts\Translation\HasLocalePreference;
class User extends Model implements HasLocalePreference
{
/**
* Get the user's preferred locale.
*/
public function preferredLocale(): string
{
return $this->locale;
}
}
インターフェースを実装すると、Laravelは自動的にモデルにメールや通知を送信する際に好みのロケールを使用します。したがって、このインターフェースを使用する際にlocale
メソッドを呼び出す必要はありません:
Mail::to($request->user())->send(new OrderShipped($order));
テスト
メールのコンテンツのテスト
Laravelは、メールの構造を検査するためのさまざまなメソッドを提供します。さらに、Laravelは、メールが期待されるコンテンツを含んでいることをテストするための便利なメソッドをいくつか提供します。これらのメソッドは、assertSeeInHtml
、assertDontSeeInHtml
、assertSeeInOrderInHtml
、assertSeeInText
、assertDontSeeInText
、assertSeeInOrderInText
、assertHasAttachment
、assertHasAttachedData
、assertHasAttachmentFromStorage
、およびassertHasAttachmentFromStorageDisk
です。
予想通り、”HTML”アサーションは、メールのHTMLバージョンが指定された文字列を含んでいることを確認し、”text”アサーションは、メールのプレーンテキストバージョンが指定された文字列を含んでいることを確認します:
use App\Mail\InvoicePaid;
use App\Models\User;
test('mailable content', function () {
$user = User::factory()->create();
$mailable = new InvoicePaid($user);
$mailable->assertFrom('');
$mailable->assertTo('');
$mailable->assertHasCc('');
$mailable->assertHasBcc('');
$mailable->assertHasReplyTo('');
$mailable->assertHasSubject('Invoice Paid');
$mailable->assertHasTag('example-tag');
$mailable->assertHasMetadata('key', 'value');
$mailable->assertSeeInHtml($user->email);
$mailable->assertSeeInHtml('Invoice Paid');
$mailable->assertSeeInOrderInHtml(['Invoice Paid', 'Thanks']);
$mailable->assertSeeInText($user->email);
$mailable->assertSeeInOrderInText(['Invoice Paid', 'Thanks']);
$mailable->assertHasAttachment('/path/to/file');
$mailable->assertHasAttachment(Attachment::fromPath('/path/to/file'));
$mailable->assertHasAttachedData($pdfData, 'name.pdf', ['mime' => 'application/pdf']);
$mailable->assertHasAttachmentFromStorage('/path/to/file', 'name.pdf', ['mime' => 'application/pdf']);
$mailable->assertHasAttachmentFromStorageDisk('s3', '/path/to/file', 'name.pdf', ['mime' => 'application/pdf']);
});
use App\Mail\InvoicePaid;
use App\Models\User;
public function test_mailable_content(): void
{
$user = User::factory()->create();
$mailable = new InvoicePaid($user);
$mailable->assertFrom('');
$mailable->assertTo('');
$mailable->assertHasCc('');
$mailable->assertHasBcc('');
$mailable->assertHasReplyTo('');
$mailable->assertHasSubject('Invoice Paid');
$mailable->assertHasTag('example-tag');
$mailable->assertHasMetadata('key', 'value');
$mailable->assertSeeInHtml($user->email);
$mailable->assertSeeInHtml('Invoice Paid');
$mailable->assertSeeInOrderInHtml(['Invoice Paid', 'Thanks']);
$mailable->assertSeeInText($user->email);
$mailable->assertSeeInOrderInText(['Invoice Paid', 'Thanks']);
$mailable->assertHasAttachment('/path/to/file');
$mailable->assertHasAttachment(Attachment::fromPath('/path/to/file'));
$mailable->assertHasAttachedData($pdfData, 'name.pdf', ['mime' => 'application/pdf']);
$mailable->assertHasAttachmentFromStorage('/path/to/file', 'name.pdf', ['mime' => 'application/pdf']);
$mailable->assertHasAttachmentFromStorageDisk('s3', '/path/to/file', 'name.pdf', ['mime' => 'application/pdf']);
}
メールの送信のテスト
メールのコンテンツを、特定のユーザーに”送信された”ということを主張するテストとは別にテストすることをお勧めします。通常、メールのコンテンツはテストしているコードに関連しないため、Laravelに特定のメールを送信するよう指示されたことを主張するだけで十分です。
``````php
<?php
use App\Mail\OrderShipped;
use Illuminate\Support\Facades\Mail;
test('orders can be shipped', function () {
Mail::fake();
// Perform order shipping...
// Assert that no mailables were sent...
Mail::assertNothingSent();
// Assert that a mailable was sent...
Mail::assertSent(OrderShipped::class);
// Assert a mailable was sent twice...
Mail::assertSent(OrderShipped::class, 2);
// Assert a mailable was sent to an email address...
Mail::assertSent(OrderShipped::class, '');
// Assert a mailable was sent to multiple email addresses...
Mail::assertSent(OrderShipped::class, ['', '...']);
// Assert a mailable was not sent...
Mail::assertNotSent(AnotherMailable::class);
// Assert 3 total mailables were sent...
Mail::assertSentCount(3);
});
`
<?php
namespace Tests\Feature;
use App\Mail\OrderShipped;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_orders_can_be_shipped(): void
{
Mail::fake();
// Perform order shipping...
// Assert that no mailables were sent...
Mail::assertNothingSent();
// Assert that a mailable was sent...
Mail::assertSent(OrderShipped::class);
// Assert a mailable was sent twice...
Mail::assertSent(OrderShipped::class, 2);
// Assert a mailable was sent to an email address...
Mail::assertSent(OrderShipped::class, '');
// Assert a mailable was sent to multiple email addresses...
Mail::assertSent(OrderShipped::class, ['', '...']);
// Assert a mailable was not sent...
Mail::assertNotSent(AnotherMailable::class);
// Assert 3 total mailables were sent...
Mail::assertSentCount(3);
}
}
バックグラウンドでメールを配信するためにキューに入れている場合は、assertQueued
メソッドをassertSent
の代わりに使用する必要があります:
Mail::assertQueued(OrderShipped::class);
Mail::assertNotQueued(OrderShipped::class);
Mail::assertNothingQueued();
Mail::assertQueuedCount(3);
``````php
Mail::assertSent(function (OrderShipped $mail) use ($order) {
return $mail->order->id === $order->id;
});
`
``````php
Mail::assertSent(OrderShipped::class, function (OrderShipped $mail) use ($user) {
return $mail->hasTo($user->email) &&
$mail->hasCc('...') &&
$mail->hasBcc('...') &&
$mail->hasReplyTo('...') &&
$mail->hasFrom('...') &&
$mail->hasSubject('...');
});
`
メールインスタンスには、メールの添付ファイルを検査するための便利なメソッドもいくつか含まれています:
use Illuminate\Mail\Mailables\Attachment;
Mail::assertSent(OrderShipped::class, function (OrderShipped $mail) {
return $mail->hasAttachment(
Attachment::fromPath('/path/to/file')
->as('name.pdf')
->withMime('application/pdf')
);
});
Mail::assertSent(OrderShipped::class, function (OrderShipped $mail) {
return $mail->hasAttachment(
Attachment::fromStorageDisk('s3', '/path/to/file')
);
});
Mail::assertSent(OrderShipped::class, function (OrderShipped $mail) use ($pdfData) {
return $mail->hasAttachment(
Attachment::fromData(fn () => $pdfData, 'name.pdf')
);
});
メールが送信されなかったことを主張するための2つのメソッド、assertNotSent
とassertNotQueued
があることに気付いたかもしれません。時には、送信されなかったまたはキューに入れられなかったことを主張したい場合があります。これを実現するために、assertNothingOutgoing
とassertNotOutgoing
メソッドを使用できます:
Mail::assertNothingOutgoing();
Mail::assertNotOutgoing(function (OrderShipped $mail) use ($order) {
return $mail->order->id === $order->id;
});
メールとローカル開発
メールを送信するアプリケーションを開発する際、実際のメールアドレスにメールを送信したくない場合が多いでしょう。Laravelは、ローカル開発中にメールの実際の送信を”無効にする”いくつかの方法を提供します。
ログドライバー
メールを送信する代わりに、log
メールドライバーは、すべてのメールメッセージをログファイルに書き込み、検査できるようにします。通常、このドライバーはローカル開発中にのみ使用されます。環境ごとにアプリケーションを構成する方法についての詳細は、構成ドキュメントを参照してください。
HELO / Mailtrap / Mailpit
代わりに、HELOやMailtrapのようなサービスとsmtp
ドライバーを使用して、メールメッセージを”ダミー”メールボックスに送信し、真のメールクライアントでそれらを表示できます。このアプローチの利点は、Mailtrapのメッセージビューワーで最終的なメールを実際に検査できることです。
Laravel Sailを使用している場合、Mailpitを使用してメッセージをプレビューできます。Sailが実行されているとき、Mailpitインターフェースには次のURLでアクセスできます:http://localhost:8025
。
グローバル宛先の使用
最後に、alwaysTo
メソッドを呼び出すことで、グローバル”to”アドレスを指定できます。このメソッドは、アプリケーションのサービスプロバイダーのboot
メソッドから呼び出すべきです:
use Illuminate\Support\Facades\Mail;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
if ($this->app->environment('local')) {
Mail::alwaysTo('');
}
}
イベント
Laravelは、メールメッセージを送信する際に2つのイベントをディスパッチします。MessageSending
イベントはメッセージが送信される前にディスパッチされ、MessageSent
イベントはメッセージが送信された後にディスパッチされます。これらのイベントは、メールが送信されるときにディスパッチされることを忘れないでください。キューに入れられたときではありません。これらのイベントに対してイベントリスナーをアプリケーション内で作成できます:
use Illuminate\Mail\Events\MessageSending;
// use Illuminate\Mail\Events\MessageSent;
class LogMessage
{
/**
* Handle the given event.
*/
public function handle(MessageSending $event): void
{
// ...
}
}
カスタムトランスポート
Laravelにはさまざまなメールトランスポートが含まれていますが、Laravelが標準でサポートしていない他のサービスを介してメールを配信するために独自のトランスポートを作成したい場合があります。始めるには、Symfony\Component\Mailer\Transport\AbstractTransport
クラスを拡張するクラスを定義します。次に、トランスポートでdoSend
およびtoString()
メソッドを実装します:
use MailchimpTransactional\ApiClient;
use Symfony\Component\Mailer\SentMessage;
use Symfony\Component\Mailer\Transport\AbstractTransport;
use Symfony\Component\Mime\Address;
use Symfony\Component\Mime\MessageConverter;
class MailchimpTransport extends AbstractTransport
{
/**
* Create a new Mailchimp transport instance.
*/
public function __construct(
protected ApiClient $client,
) {
parent::__construct();
}
/**
* {@inheritDoc}
*/
protected function doSend(SentMessage $message): void
{
$email = MessageConverter::toEmail($message->getOriginalMessage());
$this->client->messages->send(['message' => [
'from_email' => $email->getFrom(),
'to' => collect($email->getTo())->map(function (Address $email) {
return ['email' => $email->getAddress(), 'type' => 'to'];
})->all(),
'subject' => $email->getSubject(),
'text' => $email->getTextBody(),
]]);
}
/**
* Get the string representation of the transport.
*/
public function __toString(): string
{
return 'mailchimp';
}
}
カスタムトランスポートを定義したら、Mail
ファサードが提供するextend
メソッドを介してそれを登録できます。通常、これはアプリケーションのAppServiceProvider
サービスプロバイダーのboot
メソッド内で行うべきです。extend
メソッドに提供されたクロージャに$config
引数が渡されます。この引数には、アプリケーションのconfig/mail.php
構成ファイルで定義されたメール送信者の構成配列が含まれます:
use App\Mail\MailchimpTransport;
use Illuminate\Support\Facades\Mail;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Mail::extend('mailchimp', function (array $config = []) {
return new MailchimpTransport(/* ... */);
});
}
カスタムトランスポートが定義され、登録されたら、アプリケーションのconfig/mail.php
構成ファイル内で新しいトランスポートを利用するメール送信者の定義を作成できます:
'mailchimp' => [
'transport' => 'mailchimp',
// ...
],
追加のSymfonyトランスポート
Laravelは、MailgunやPostmarkなどの既存のSymfonyメンテナンスメールトランスポートをサポートしています。ただし、追加のSymfonyメンテナンストランスポートをサポートするためにLaravelを拡張したい場合があります。その場合、Composerを介して必要なSymfonyメール送信者を要求し、Laravelにトランスポートを登録できます。たとえば、”Brevo”(以前の”Sendinblue”)Symfonyメール送信者をインストールして登録できます:
composer require symfony/brevo-mailer symfony/http-client
Brevoメール送信者パッケージがインストールされたら、アプリケーションのservices
構成ファイルにBrevo API資格情報のエントリを追加できます:
'brevo' => [
'key' => 'your-api-key',
],
次に、Mail
ファサードのextend
メソッドを使用して、Laravelにトランスポートを登録できます。通常、これはサービスプロバイダーのboot
メソッド内で行うべきです:
use Illuminate\Support\Facades\Mail;
use Symfony\Component\Mailer\Bridge\Brevo\Transport\BrevoTransportFactory;
use Symfony\Component\Mailer\Transport\Dsn;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Mail::extend('brevo', function () {
return (new BrevoTransportFactory)->create(
new Dsn(
'brevo+api',
'default',
config('services.brevo.key')
)
);
});
}
トランスポートが登録されたら、アプリケーションのconfig/mail.php構成ファイル内で新しいトランスポートを利用するメール送信者の定義を作成できます:
'brevo' => [
'transport' => 'brevo',
// ...
],