Laravel 9.x メール

イントロダクション

メール送信を複雑にする必要はありません。Laravelは、ポピュラーなSymfony Mailerコンポーネントによる、クリーンでシンプルなメールAPIを提供しています。LaravelとSymfony Mailerは、SMTP、Mailgun、Postmark、Amazon SES、sendmail経由でメールを送信するドライバを提供しており、ローカルまたはクラウドベースのサービスを通じて、すぐにメール送信を開始できます。

設定

Laravelのメールサービスは、アプリケーションのconfig/mail.php設定ファイルを介して設定できます。このファイル内で設定された各メーラーには、独自の設定と独自の「トランスポート」があり、アプリケーションがさまざまな電子メールサービスを使用して特定の電子メールメッセージを送信できるようにします。たとえば、アプリケーションでPostmarkを使用してトランザクションメールを送信し、AmazonSESを使用して一括メールを送信するなどです。

mail設定ファイル内に、mailers設定配列があります。この配列には、Laravelがサポートしている主要なメールドライバ/トランスポートごとのサンプル設定エントリが含まれています。その中でdefault設定値は、アプリケーションが電子メールメッセージを送信する必要があるときにデフォルトで使用するメーラーを決定します。

ドライバ/トランスポートの前提条件

MailgunやPostmarkなどのAPIベースドライバは、SMTPサーバを経由してメールを送信するよりもシンプルで高速です。可能であれば、こうしたドライバのいずれかを使用することをお勧めします。

Mailgunドライバ

Mailgunドライバを使用する場合は、Composerで、SymfonyのMailgun Mailerトランスポートをインストールします。

composer require symfony/mailgun-mailer symfony/http-client

次に、アプリケーションのconfig/mail.php設定ファイルにある、defaultオプションをmailgunに設定します。アプリケーションのデフォルトメーラーを設定したら、config/services.php設定ファイルへ以下のオプションがあることを確認してください。

'mailgun' => [
    'domain' => env('MAILGUN_DOMAIN'),
    'secret' => env('MAILGUN_SECRET'),
],

米国のMailgunリージョンを使用していない場合は、services設定ファイルでリージョンのエンドポイントを定義できます。

'mailgun' => [
    'domain' => env('MAILGUN_DOMAIN'),
    'secret' => env('MAILGUN_SECRET'),
    'endpoint' => env('MAILGUN_ENDPOINT', 'api.eu.mailgun.net'),
],

Postmarkドライバ

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'),
],

この方法で、メッセージストリームが異なる複数のPostmarkメーラを設定することもできます。

SESドライバ

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'),
],

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'],
        ],
    ],
],

フェイルオーバー設定

アプリケーションのメールを送信するように設定した外部サービスがダウンすることがあります。このような場合には、プライマリ配信ドライバがダウンした場合に使用する、1つ以上のバックアップメール配信設定を定義できると便利です。

これを実現するには、アプリケーションのmail設定ファイルで、failoverトランスポートを使用するメーラーを定義する必要があります。アプリケーションのfailoverメーラー設定配列に、配送に使うメールドライバを選択する順序を規定するmailersの配列を含める必要があります。

'mailers' => [
    'failover' => [
        'transport' => 'failover',
        'mailers' => [
            'postmark',
            'mailgun',
            'sendmail',
        ],
    ],

    // ...
],

フェイルオーバーメーラーを定義したら、アプリケーションのmail設定ファイル内のdefault設定キーの値に、その名前を指定して、このメーラーをアプリケーションが使用するデフォルトメーラーとして設定する必要があります。

'default' => env('MAIL_MAILER', 'failover'),

Mailableの生成

Laravelアプリケーションを構築する場合、アプリケーションが送信する各タイプの電子メールは"Mailable"クラスとして表します。これらのクラスはapp/Mailディレクトリに保存されます。アプリケーションにこのディレクトリが存在しなくても心配ありません。make:mail Artisanコマンドを使用して最初のメール可能なクラスを作成するときに、生成されます。

php artisan make:mail OrderShipped

Mailableの記述

Mailableクラスを生成したら、それを開いて、その内容を調べてください。まず、メール可能なクラスの設定はすべてbuildメソッドで行われることに注意してください。このメソッド内でfromsubjectviewattachなどのさまざまなメソッドを呼び出して、電子メールの表示と配信を設定できます。

Tip!! Mailableのbuildメソッドではタイプヒントで依存を指定できます。Laravelのサービスコンテナは、これらの依存を自動的に注入します。

Senderの設定

fromメソッドの使用

まず、メールの送信者の設定について見ていきましょう。言い換えると、電子メールを送信したのは誰かです。送信者を設定するには2つの方法があります。まず、Mailableクラスのbuildメソッド内でfromメソッドを使用する方法です。

/**
 * メッセージの作成
 *
 * @return $this
 */
public function build()
{
    return $this->from('example@example.com', 'Example')
                ->view('emails.orders.shipped');
}

グローバルfromアドレスの使用

ただし、アプリケーションがすべての電子メールに同じ「送信者」アドレスを使用している場合、生成する各メール可能クラスでfromメソッドを呼び出すのは面倒です。代わりに、config/mail.php設定ファイルでグローバルな「送信者」アドレスを指定できます。このアドレスは、Mailableクラス内で「送信者」アドレスを指定しない場合に使用します。

'from' => ['address' => 'example@example.com', 'name' => 'App Name'],

また、config/mail.php設定ファイル内でグローバルな"reply_to"アドレスも定義できます。

'reply_to' => ['address' => 'example@example.com', 'name' => 'App Name'],

ビューの設定

Mailableクラスのbuildメソッド内で、viewメソッドを使用して、電子メールのコンテンツをレンダするときに使用するテンプレートを指定できます。通常、各メールはBladeテンプレートを使用してコンテンツをレンダするため、メールのHTMLを作成するときにBladeテンプレートエンジンの能力と利便性を最大限に活用できます。

/**
 * メッセージの作成
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped');
}

Tip!! すべてのメールテンプレートを格納するためにresources/views/emailsディレクトリを作成することを推奨します。ただし、resources/viewsディレクトリ内ならば好きな場所へ自由に配置できます。

平文テキストの電子メール

電子メールの平文テキストバージョンを定義する場合は、textメソッドを使用します。viewメソッドと同様に、textメソッドは電子メールの内容をレンダするために使用するテンプレート名を引数に取ります。メッセージのHTMLバージョンと平文テキストバージョンの両方を自由に定義できます。

/**
 * メッセージの作成
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped')
                ->text('emails.orders.shipped_plain');
}

ビューデータ

Publicなプロパティ経由

通常、電子メールのHTMLをレンダするときに使用するデータをビューへ渡す必要があります。ビューでデータを利用できるようにする方法は2つあります。まず、Mailableクラスで定義したパブリックプロパティは、自動的にビューで使用できるようになります。したがって、たとえばMailableクラスのコンストラクタにデータを渡し、そのデータをクラスで定義したパブリックプロパティに設定できます。

<?php

namespace App\Mail;

use App\Models\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class OrderShipped extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * 注文インスタンス
     *
     * @var \App\Models\Order
     */
    public $order;

    /**
     * 新しいメッセージインスタンスの生成
     *
     * @param  \App\Models\Order  $order
     * @return void
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    /**
     * メッセージを作成
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.orders.shipped');
    }
}

データをパブリックプロパティへ設定すると、ビューで自動的に利用できるようになるため、Bladeテンプレートの他のデータにアクセスするのと同じようにアクセスできます。

<div>
    Price: {{ $order->price }}
</div>

withメソッド経由

テンプレートへ送信する前にメールのデータの形式をカスタマイズしたい場合は、withメソッドを使用して手作業でデータをビューへ渡せます。通常、Mailableクラスのコンストラクターを介してデータを渡します。ただし、このデータをprotectedまたはprivateプロパティに設定して、データがテンプレートで自動的に使用可能にならないようにする必要があります。次に、withメソッドを呼び出すときに、テンプレートで使用できるようにするデータの配列を渡します。

<?php

namespace App\Mail;

use App\Models\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class OrderShipped extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * 注文インスタンス
     *
     * @var \App\Models\Order
     */
    protected $order;

    /**
     * 新しいメッセージインスタンスの生成
     *
     * @param  \App\Models\Order  $order
     * @return void
     */
    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    /**
     * メッセージを作成
     *
     * @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>

添付

電子メールに添付ファイルを追加するには、Mailableクラスのbuildメソッド内でattachメソッドを使用します。attachメソッドは、ファイルへのフルパスを最初の引数に受けます。

/**
 * メッセージの作成
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped')
                ->attach('/path/to/file');
}

メッセージにファイルを添付する場合、arrayattachメソッドの2番目の引数に渡すことにより、表示名やMIMEタイプを指定することもできます。

/**
 * メッセージの作成
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped')
                ->attach('/path/to/file', [
                    'as' => 'name.pdf',
                    'mime' => 'application/pdf',
                ]);
}

ディスクからファイルを添付

ファイルシステムディスクのいずれかにファイルを保存している場合は、attachFromStorageメソッドを使用してファイルを電子メールに添付できます。

/**
 * メッセージの作成
 *
 * @return $this
 */
public function build()
{
   return $this->view('emails.orders.shipped')
               ->attachFromStorage('/path/to/file');
}

必要に応じて、attachFromStorageメソッドの2番目と3番目の引数を使用して、ファイルの添付ファイル名と追加オプションを指定できます。

/**
 * メッセージの作成
 *
 * @return $this
 */
public function build()
{
   return $this->view('emails.orders.shipped')
               ->attachFromStorage('/path/to/file', 'name.pdf', [
                   'mime' => 'application/pdf'
               ]);
}

デフォルトのディスク以外のストレージディスクを指定する必要がある場合は、attachFromStorageDiskメソッドを使用します。

/**
 * メッセージの作成
 *
 * @return $this
 */
public function build()
{
   return $this->view('emails.orders.shipped')
               ->attachFromStorageDisk('s3', '/path/to/file');
}

素のデータの添付ファイル

attachDataメソッドを使用して、素のバイト文字列を添付ファイルとして添付できます。たとえば、メモリ内にPDFを生成し、ディスクに書き込まずに電子メールに添付する場合は、この方法を使用できます。attachDataメソッドは、最初の引数に素のデータバイトを取り、2番目の引数にファイルの名前、3番目の引数にオプションの配列を取ります。

/**
 * メッセージの作成
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped')
                ->attachData($this->pdf, 'name.pdf', [
                    'mime' => 'application/pdf',
                ]);
}

インライン添付

インライン画像をメールに埋め込むのは、通常面倒です。ただし、Laravelはメールに画像を添付する便利な方法を提供しています。インライン画像を埋め込むには、メールテンプレート内の$message変数でembedメソッドを使用します。Laravelは自動的に$message変数をすべてのメールテンプレートで利用できるようにするので、手作業で渡すことを心配する必要はありません。

<body>
    Here is an image:

    <img src="{{ $message->embed($pathToImage) }}">
</body>

Note: 平文ンテキストメッセージはインライン添付ファイルを利用しないため、$message変数は平文テキストメッセージテンプレートでは使用できません。

素のデータの添付ファイルへの埋め込み

電子メールテンプレートに埋め込みたい素の画像データ文字列がすでにある場合は、$message変数でembedDataメソッドを呼び出すことができます。embedDataメソッドを呼び出すときは、埋め込み画像に割り当てる必要のあるファイル名を指定する必要があります。

<body>
    Here is an image from raw data:

    <img src="{{ $message->embedData($data, 'example-image.jpg') }}">
</body>

Attachableオブジェクト

単純な文字列のパスを介してメッセージへファイルを添付すれば十分なことがある一方で、多くの場合、アプリケーション内の添付可能なエンティティはクラスによって表されます。例えば、アプリケーションがメッセージに写真を添付している場合、アプリケーションはその写真を表すPhotoモデルを用意することもできます。その場合、Photoモデルをattachメソッドに渡せれば、便利ですよね?添付可能なAttachableオブジェクトを使用すれば、それが実行できます。

この機能を利用するには、メッセージへ添付できるオブジェクトに、Illuminate\Contracts\Mail\Attachableインターフェイスを実装します。このインターフェイスは、そのクラスがIlluminate\Mail\Attachmentインスタンスを返すtoMailAttachmentメソッドを定義するよう指示します:

<?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.
     *
     * @return \Illuminate\Mail\Attachment
     */
    public function toMailAttachment()
    {
        return Attachment::fromPath('/path/to/file');
    }
}

Once you have defined your attachable object, you may simply pass an instance of that object to the attach method when building an email message:

/**
 * Build the message.
 *
 * @return $this
 */
public function build()
{
    return $this->view('photos.resized')
                ->attach($this->photo);
}

Of course, attachment data may be stored on a remote file storage service such as Amazon S3. So, Laravel also allows you to generate attachment instances from data that is stored on one of your application's filesystem disks:

// 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);

In addition, you may create attachment instances via data that you have in memory. To accomplish this, provide a closure to the fromData method. The closure should return the raw data that represents the attachment:

return Attachment::fromData(fn () => $this->content);

Laravel also provides additional methods that you may use to customize your attachments. For example, you may use the as and withMime methods to customize the file's name and MIME type:

return Attachment::fromPath('/path/to/file')
        ->as('Photo Name')
        ->withMime('image/jpeg');

タグとメタデータ

MailgunやPostmarkなどのサードパーティのメールプロバイダーは、メッセージの「タグ」や「メタデータ」をサポートしており、アプリケーションから送信されたメールをグループ化して追跡するために使用することができます。タグやメタデータは、tagメソッドやmetadataメソッドにより、メールメッセージへ追加できます。

/**
 * メッセージの構築
 *
 * @return $this
 */
public function build()
{
    return $this->view('emails.orders.shipped')
                ->tag('shipment')
                ->metadata('order_id', $this->order->id);
}

アプリケーションでMailgunドライバを使用している場合、タグメタデータの詳細は、Mailgunのドキュメントを参照してください。同様に、Postmarkのドキュメントも、タグメタデータのサポートについて、詳しい情報を得るために参照できます。

アプリケーションがAmazon SESを使用してメールを送信している場合、metadataメソッドを使用して、メッセージへSES 「タグ」を添付する必要があります。

Symfonyメッセージのカスタマイズ

MailableベースクラスのwithSymfonyMessageメソッドは、メッセージ送信前にSymfonyのメッセージインスタンスで呼び出されるクロージャを登録可能です。これにより、メッセージが配信される前に、メッセージを詳細にカスタマイズする機会が得られます。

use Symfony\Component\Mime\Email;

/**
 * メッセージの作成
 *
 * @return $this
 */
public function build()
{
    $this->view('emails.orders.shipped');

    $this->withSymfonyMessage(function (Email $message) {
        $message->getHeaders()->addTextHeader(
            'Custom-Header', 'Header Value'
        );
    });

    return $this;
}

Markdown Mailable

Markdown Mailableメッセージを使用すると、Mailableでメール通知の事前に作成されたテンプレートとコンポーネントを利用できます。メッセージはMarkdownで記述されているため、Laravelはメッセージの美しくレスポンシブなHTMLテンプレートをレンダすると同時に、平文テキスト版も自動的に生成できます。

Markdown Mailableの生成

対応するMarkdownテンプレートを使用してMailableファイルを生成するには、make:mail Artisanコマンドの--markdownオプションを使用します。

php artisan make:mail OrderShipped --markdown=emails.orders.shipped

次に、Mailableオブジェクトをそのbuildメソッド内で設定するときに、viewメソッドの代わりにmarkdownメソッドを呼び出します。markdownメソッドは、Markdownテンプレートの名前と、テンプレートで使用するデータ配列をオプションとして引数に取ります。

/**
 * メッセージの作成
 *
 * @return $this
 */
public function build()
{
    return $this->from('example@example.com')
                ->markdown('emails.orders.shipped', [
                    'url' => $this->orderUrl,
                ]);
}

Markdownメッセージの記述

Markdown Mailableは、BladeコンポーネントとMarkdown構文の組み合わせを使用して、Laravelに組み込まれた電子メールUIコンポーネントを活用しながら、メールメッセージを簡単に作成できるようにします。

@component('mail::message')
# 発送

注文を発送しました。

@component('mail::button', ['url' => $url])
注文の確認
@endcomponent

Thanks,<br>
{{ config('app.name') }}
@endcomponent

Tip!! Markdownメールを書くときに余分なインデントを使用しないでください。Markdown標準に従って、Markdownパーサーはインデントされたコンテンツをコードブロックとしてレンダリングします。

ボタンコンポーネント

ボタンコンポーネントは、中央に配置されたボタンリンクをレンダします。コンポーネントは、urlとオプションのcolorの2つの引数を取ります。サポートしている色は、primarysuccesserrorです。メッセージには、必要なだけのボタンコンポーネントを追加できます。

@component('mail::button', ['url' => $url, 'color' => 'success'])
注文の確認
@endcomponent

パネルコンポーネント

パネルコンポーネントは、メッセージの残りの部分とはわずかに異なる背景色を持つパネルで、指定するテキストのブロックをレンダします。これにより、特定のテキストブロックに注意を引くことができます。

@component('mail::panel')
ここはパネルの本文。
@endcomponent

テーブルコンポーネント

テーブルコンポーネントを使用すると、MarkdownテーブルをHTMLテーブルに変換できます。コンポーネントは、そのコンテンツとしてMarkdownテーブルを受け入れます。テーブルの列の配置は、デフォルトのMarkdownテーブルの配置構文をサポートします。

@component('mail::table')
| Laravel       | テーブル         | 例  |
| ------------- |:-------------:| --------:|
| Col 2 is      | Centered      | $10      |
| Col 3 is      | Right-Aligned | $20      |
@endcomponent

コンポーネントのカスタマイズ

カスタマイズするために、すべてのMarkdownメールコンポーネントを自身のアプリケーションへエクスポートできます。コンポーネントをエクスポートするには、vendor:publish Artisanコマンドを使用して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をカスタマイズすると、MarkdownメールメッセージのHTML表現内でスタイルが自動的にインラインCSSスタイルに変換されます。

LaravelのMarkdownコンポーネント用にまったく新しいテーマを作成したい場合は、CSSファイルをhtml/themesディレクトリに配置できます。CSSファイルに名前を付けて保存した後、アプリケーションのconfig/mail.php設定ファイルのthemeオプションを更新して、新しいテーマの名前と一致させます。

個々のMailableのテーマをカスタマイズするには、Mailableクラスの$themeプロパティを、そのMailableを送信するときに使用するテーマの名前に設定します。

メール送信

メッセージを送信するには、Mailファサードtoメソッドを使用します。toメソッドは、電子メールアドレス、ユーザーインスタンス、またはユーザーのコレクションを受け入れます。オブジェクトまたはオブジェクトのコレクションを渡すと、メーラーは電子メールの受信者を決定するときに自動的にemailおよびnameプロパティを使用するため、これらの属性がオブジェクトで使用可能であることを確認してください。受信者を指定したら、Mailableクラスのインスタンスをsendメソッドに渡すことができます。

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Mail\OrderShipped;
use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;

class OrderShipmentController extends Controller
{
    /**
     * 指定注文を発送
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $order = Order::findOrFail($request->order_id);

        // 注文の発送処理…

        Mail::to($request->user())->send(new OrderShipped($order));
    }
}

メッセージを送信するときに「宛先」の受信者を指定するだけに限定されません。それぞれのメソッドをチェーン化することで、「to」、「cc」、「bcc」の受信者を自由に設定できます。

Mail::to($request->user())
    ->cc($moreUsers)
    ->bcc($evenMoreUsers)
    ->send(new OrderShipped($order));

受信者をループする

場合によっては、受信者/電子メールアドレスの配列を反復処理して、受信者のリストにMailableファイルを送信する必要が起きるでしょう。しかし、toメソッドはメールアドレスをMailable受信者のリストに追加するため、ループを繰り返すたびに、以前のすべての受信者に別のメールが送信されます。したがって、受信者ごとにMailableインスタンスを常に再作成する必要があります。

foreach (['taylor@example.com', 'dries@example.com'] as $recipient) {
    Mail::to($recipient)->send(new OrderShipped($order));
}

特定のメーラーを介してメールを送信

デフォルトでは、Laravelはアプリケーションのmail設定ファイルでdefaultメーラーとして設定されたメーラーを使用してメールを送信します。しかし、mailerメソッドを使用して、特定のメーラー設定を使用してメッセージを送信することができます。

Mail::mailer('postmark')
        ->to($request->user())
        ->send(new OrderShipped($order));

メールのキュー投入

メールメッセージのキュー投入

電子メールメッセージの送信はアプリケーションのレスポンス時間に悪影響を与える可能性があるため、多くの開発者はバックグラウンド送信のために電子メールメッセージをキューに投入することを選択します。Laravelは組み込みの統一キューAPIを使用してこれを簡単にしています。メールメッセージをキューに投入するには、メッセージの受信者を指定した後、Mailファサードでqueueメソッドを使用します。

Mail::to($request->user())
    ->cc($moreUsers)
    ->bcc($evenMoreUsers)
    ->queue(new OrderShipped($order));

このメソッドは、メッセージがバックグラウンドで送信されるように、ジョブをキューへ自動的に投入処理します。この機能を使用する前に、キューを設定しておく必要があります。

遅延メッセージキュー

キューに投入した電子メールメッセージの配信を遅らせたい場合は、laterメソッドを使用します。laterメソッドは最初の引数にメッセージの送信時期を示すDateTimeインスタンスを取ります。。

Mail::to($request->user())
    ->cc($moreUsers)
    ->bcc($evenMoreUsers)
    ->later(now()->addMinutes(10), new OrderShipped($order));

特定のキューへの投入

make:mailコマンドを使用して生成したすべてのMailableクラスはIlluminate\Bus\Queueableトレイトを利用するため、任意のMailableクラスインスタンスでonQueueメソッドとonConnectionメソッドを呼び出して、メッセージに使う接続とキュー名を指定できます。

$message = (new OrderShipped($order))
                ->onConnection('sqs')
                ->onQueue('emails');

Mail::to($request->user())
    ->cc($moreUsers)
    ->bcc($evenMoreUsers)
    ->queue($message);

デフォルトでのキュー投入

常にキューに入れたいMailableクラスがある場合は、クラスにShouldQueue契約を実装できます。これで、メール送信時にsendメソッドを呼び出しても、この契約を実装しているため、Mailableはキューへ投入されます。

use Illuminate\Contracts\Queue\ShouldQueue;

class OrderShipped extends Mailable implements ShouldQueue
{
    //
}

Mailableのキュー投入とデータベーストランザクション

キュー投入されたMailableがデータベーストランザクション内でディスパッチされると、データベーストランザクションがコミットされる前にキューによって処理される場合があります。これが発生した場合、データベーストランザクション中にモデルまたはデータベースレコードに加えた更新は、データベースにまだ反映されていない可能性があります。さらに、トランザクション内で作成したモデルまたはデータベースレコードは、データベースに存在しない可能性があります。Mailableがこれらのモデルに依存している場合、キューに入れられたMailableを送信するジョブが処理されるときに予期しないエラーが発生する可能性があります。

キュー接続のafter_commit設定オプションがfalseに設定されている場合でも、メールメッセージ送信時にafterCommitメソッドを呼び出せば、キュー投入する特定のMailableが、オープンしているすべてのデータベーストランザクションのコミット後に、ディスパッチすると示せます。

Mail::to($request->user())->send(
    (new OrderShipped($order))->afterCommit()
);

あるいは、Mailableのコンストラクタで、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;

    /**
     * 新しいメッセージインスタンスの生成
     *
     * @return void
     */
    public function __construct()
    {
        $this->afterCommit();
    }
}

Tip!! これらの問題の回避方法の詳細は、キュー投入したジョブとデータベーストランザクションに関するドキュメントを確認してください。

Mailableのレンダ

MailableのHTMLコンテンツを送信せずにキャプチャしたい場合があります。これを行うには、Mailableのrenderメソッドを呼び出してください。このメソッドは、Mailableファイルの評価済みHTMLコンテンツを文字列として返します。

use App\Mail\InvoicePaid;
use App\Models\Invoice;

$invoice = Invoice::find(1);

return (new InvoicePaid($invoice))->render();

ブラウザによるMailableのプレビュー

Mailableのテンプレートを設計するときは、通常のBladeテンプレートのように、レンダ済みMailableをブラウザですばやくプレビューできると便利です。このためLaravelでは、ルートクロージャまたはコントローラから直接Mailableを返せます。Mailableが返されると、ブラウザでレンダされ表示されるため、実際の電子メールアドレスへ送信しなくても、デザインをすばやくプレビューできます。

Route::get('/mailable', function () {
    $invoice = App\Models\Invoice::find(1);

    return new App\Mail\InvoicePaid($invoice);
});

Note: インライン添付ファイルは、Mailableファイルがブラウザでプレビューされたときにレンダリングされません。これらのメーラブルをプレビューするには、MailHogHELOなどのメールテストアプリケーションに送信する必要があります。

Mailableの多言語化

Laravelを使用すると、リクエストの現在のロケール以外のロケールでMailableファイルを送信でき、メールがキュー投入される場合でもこのロケールを記憶しています。

これを実現するために、Mailファサードは目的の言語を設定するためのlocaleメソッドを提供します。Mailableのテンプレートが評価されると、アプリケーションはこのロケールに変更され、評価が完了すると前のロケールに戻ります。

Mail::to($request->user())->locale('es')->send(
    new OrderShipped($order)
);

ユーザー優先ロケール

場合によっては、アプリケーションは各ユーザーの優先ロケールを保存しています。1つ以上のモデルにHasLocalePreferenceコントラクトを実装することで、メールを送信するときにこの保存されたロケールを使用するようにLaravelに指示できます。

use Illuminate\Contracts\Translation\HasLocalePreference;

class User extends Model implements HasLocalePreference
{
    /**
     * ユーザーの希望するロケールを取得
     *
     * @return string
     */
    public function preferredLocale()
    {
        return $this->locale;
    }
}

このインターフェイスを実装すると、LaravelはMailableと通知をモデルへ送信するとき、自動的に優先ロケールを使用します。したがって、このインターフェイスを使用する場合、localeメソッドを呼び出す必要はありません。

Mail::to($request->user())->send(new OrderShipped($order));

Mailableのテスト

Laravelでは、Mailableに期待した内容が含まれているかをテストするため、便利なメソッドを提供しています。こうしたメソッドに次のものがあります。assertSeeInHtmlassertDontSeeInHtmlassertSeeInOrderInHtmlassertSeeInTextassertDontSeeInTextassertSeeInOrderInText

ご想像のとおり、"HTML"アサートは、MailableのHTMLバージョンに特定の文字列が含まれていることを宣言し、"text"アサートは、Mailableの平文テキストバージョンに特定の文字列が含まれていることを宣言します。

use App\Mail\InvoicePaid;
use App\Models\User;

public function test_mailable_content()
{
    $user = User::factory()->create();

    $mailable = new InvoicePaid($user);

    $mailable->assertSeeInHtml($user->email);
    $mailable->assertSeeInHtml('Invoice Paid');
    $mailable->assertSeeInOrderInHtml(['Invoice Paid', 'Thanks']);

    $mailable->assertSeeInText($user->email);
    $mailable->assertSeeInOrderInText(['Invoice Paid', 'Thanks']);
}

Mailableの送信テスト

指定のMailableが特定のユーザーへ「送信」されたことをアサートするテストとは別に、Mailableのコンテンツをテストするのを推奨します。メールが送信されたことをテストする方法については、Mail fakeのドキュメントをご覧ください。

メールとローカル開発

電子メールを送信するアプリケーションを開発する場合、実際の電子メールアドレスに電子メールを送信したくない場合があります。Laravelは、ローカル開発中に実際の電子メールの送信を「無効にする」ためのいくつかの方法を提供します。

Logドライバ

メールを送信する代わりに、logメールドライバは検査のためにすべてのメールメッセージをログファイルに書き込みます。通常、このドライバはローカル開発中にのみ使用されます。環境ごとのアプリケーションの設定の詳細については、設定ドキュメントを確認してください。

HELO/Mailtrap/MailHog

もしくは、HELOMailtrapなどのサービスとsmtpドライバを使用して、メールメッセージを「ダミー」メールボックスに送信可能です。本当の電子メールクライアントでそれらを表示できます。このアプローチには、Mailtrapのメッセージビューアで最終的な電子メールを実際に調べられるという利点があります。

Laravel Sailを使用している場合は、MailHogを使用してメッセージをプレビューできます。Sailの実行中は、http://localhost:8025でMailHogインターフェイスにアクセスできます。

グローバルなtoアドレスの使用

最後に、Mailファサードが提供するalwaysToメソッドを呼び出し、グローバルな「宛先」アドレスを指定する方法です。通常、このメソッドは、アプリケーションのサービスプロバイダのbootメソッドから呼び出すべきでしょう。

use Illuminate\Support\Facades\Mail;

/**
 * アプリケーションの全サービスの初期起動処理
 *
 * @return void
 */
public function boot()
{
    if ($this->app->environment('local')) {
        Mail::alwaysTo('taylor@example.com');
    }
}

イベント

Laravelは、メールメッセージの送信プロセス中に2つのイベントを発行します。MessageSendingイベントはメッセージが送信される前に発生し、MessageSentイベントはメッセージが送信された後に発生します。これらのイベントは、メールをキューへ投入したときではなく、メールが送信されているときに発生することを忘れないでください。このイベントのイベントリスナは、App\Providers\EventServiceProviderサービスプロバイダで登録できます。

/**
 * アプリケーションのイベントリスナマッピング
 *
 * @var array
 */
protected $listen = [
    'Illuminate\Mail\Events\MessageSending' => [
        'App\Listeners\LogSendingMessage',
    ],
    'Illuminate\Mail\Events\MessageSent' => [
        'App\Listeners\LogSentMessage',
    ],
];

カスタムトランスポート

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\MessageConverter;

class MailchimpTransport extends AbstractTransport
{
    /**
     * Mailchimp APIクライアント
     *
     * @var \MailchimpTransactional\ApiClient
     */
    protected $client;

    /**
     * 新しいMailchimpトランスポートインスタンスの生成
     *
     * @param  \MailchimpTransactional\ApiClient  $client
     * @return void
     */
    public function __construct(ApiClient $client)
    {
        $this->client = $client;
    }

    /**
     * {@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 ($email) {
                return ['email' => $email->getAddress(), 'type' => 'to'];
            })->all(),
            'subject' => $email->getSubject(),
            'text' => $email->getTextBody(),
        ]]);
    }

    /**
     * トランスポートの文字列表現の取得
     *
     * @return string
     */
    public function __toString(): string
    {
        return 'mailchimp';
    }
}

カスタムトランスポートを定義したら、Mailファサードが提供するextendメソッドで登録します。一般的には、アプリケーションのAppServiceProviderサービスプロバイダのbootメソッド内で行います。extendメソッドへ渡されるクロージャへ、$config引数が渡されます。この引数には、アプリケーションのconfig/mail.php設定ファイルで定義してあるメーラーの設定配列が含まれています。

use App\Mail\MailchimpTransport;
use Illuminate\Support\Facades\Mail;

/**
 * アプリケーションの全サービスの初期起動処理
 *
 * @return void
 */
public function boot()
{
    Mail::extend('mailchimp', function (array $config = []) {
        return new MailchimpTransport(/* ... */);
    })
}

カスタムトランスポートを定義し、登録すると、アプリケーションのconfig/mail.php設定ファイル内に、新しいトランスポートを利用するメーラー定義を作成できます。

'mailchimp' => [
    'transport' => 'mailchimp',
    // ...
],

Symfonyトランスポートの追加

Laravelは、MailgunやPostmarkのように、Symfonyがメンテナンスしている既存のメールトランスポートをサポートしています。しかし、Laravelを拡張して、Symfonyが保守する追加のトランスポートを追加サポートしたい場合があるでしょう。Composerを使い、必要なSymfonyメーラーをインストールし、Laravelでそのトランスポートを登録することで、これが実現できます。例として、"Sendinblue" Symfonyメーラーをインストールし、登録してみましょう。

composer require symfony/sendinblue-mailer

Sendinblueメーラーパッケージをインストールしたら、アプリケーションのservices設定ファイルへ、Sendinblue API認証情報のエントリを追加します。

'sendinblue' => [
    'key' => 'your-api-key',
],

最後に、Mailファサードのextendメソッドを使用して、Laravelへこのトランスポートを登録します。一般的に、これはサービスプロバイダのbootメソッド内で行う必要があります。

use Illuminate\Support\Facades\Mail;
use Symfony\Component\Mailer\Bridge\Sendinblue\Transport\SendinblueTransportFactory;
use Symfony\Component\Mailer\Transport\Dsn;

/**
 * アプリケーションの全サービスの初期起動処理
 *
 * @return void
 */
public function boot()
{
    Mail::extend('sendinblue', function () {
        return (new SendinblueTransportFactory)->create(
            new Dsn(
                'sendinblue+api',
                'default',
                config('services.sendinblue.key')
            )
        );
    });
}

ドキュメント章別ページ

ヘッダー項目移動

注目:アイコン:ページ内リンク設置(リンクがないヘッダーへの移動では、リンクがある以前のヘッダーのハッシュをURLへ付加します。

移動

クリックで即時移動します。

設定

適用ボタンクリック後に、全項目まとめて適用されます。

カラーテーマ
和文指定 Pagination
和文指定 Scaffold
Largeスクリーン表示幅
インデント
本文フォント
コードフォント
フォント適用確認

フォントの指定フィールドから、フォーカスが外れると、当ブロックの内容に反映されます。EnglishのDisplayもPreviewしてください。

フォント設定時、表示に不具合が出た場合、当サイトのクッキーを削除してください。

バックスラッシュを含むインライン\Code\Blockの例です。

以下はコードブロックの例です。

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * ユーザに関連する電話レコードを取得
     */
    public function phone()
    {
        return $this->hasOne('App\Phone');
    }
}

設定を保存する前に、表示が乱れないか必ず確認してください。CSSによるフォントファミリー指定の知識がない場合は、フォントを変更しないほうが良いでしょう。

キーボード・ショートカット

オープン操作

PDC

ページ(章)移動の左オフキャンバスオープン

HA

ヘッダー移動モーダルオープン

MS

移動/設定の右オフキャンバスオープン

ヘッダー移動

T

最初のヘッダーへ移動

E

最後のヘッダーへ移動

NJ

次ヘッダー(H2〜H4)へ移動

BK

前ヘッダー(H2〜H4)へ移動

その他

?

このヘルプページ表示
閉じる