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クラスを生成したら、その中身を調べるために開いてみましょう。Mailableクラスの設定は、envelopecontentattachmentsなどのメソッドで行います。

envelopeメソッドは、メッセージのサブジェクトと、時折り受信者を定義する、Illuminate\Mail\Mailables\Envelopeオブジェクトを返します。contentメソッドは、メッセージの内容を生成するために使用するBladeテンプレートを定義する、Illuminate\Mail\Mailables\Contentオブジェクトを返します。

Senderの設定

Envelopeの使用

まず、メール送信者の設定を調べてみましょう。つまり、「誰から送られた」メールかということです。送信者の設定は、2つの方法があります。まず、メッセージのEnvelope(封筒)に"from"アドレスを指定する方法です。

use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Envelope;

/**
 * メッセージEnvelopeを取得
 *
 * @return \Illuminate\Mail\Mailables\Envelope
 */
public function 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メソッドを呼び出すのは面倒です。代わりに、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クラスのcontentメソッド内でview、つまりメールのコンテンツをレンダリングするときどのテンプレートを使用するかを定義します。各メールは通常、Bladeテンプレートを使用してコンテンツをレンダするので、メールのHTML構築にBladeテンプレート・エンジンのパワーと利便性をフル活用できます。

/**
 * メッセージ内容の定義を取得
 *
 * @return \Illuminate\Mail\Mailables\Content
 */
public function content()
{
    return new Content(
        view: 'emails.orders.shipped',
    );
}

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

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

平文テキスト版のメールを定義したい場合は、メッセージのContent定義を作成するときに、平文テキストのテンプレートを指定してください。viewパラメータと同様、textパラメータにはメールの内容をレンダするために使用するテンプレートの名前を指定します。HTMLバージョンと平文テキストバージョンの両方を自由に定義できます。

/**
 * メッセージ内容の定義を取得
 *
 * @return \Illuminate\Mail\Mailables\Content
 */
public function content()
{
    return new Content(
        view: 'emails.orders.shipped',
        text: 'emails.orders.shipped-text'
    );
}

明確にするために、htmlパラメータをviewパラメータの別名として使用できます。

return new Content(
    html: 'emails.orders.shipped',
    text: 'emails.orders.shipped-text'
);

ビューデータ

Publicなプロパティ経由

通常、電子メールのHTMLをレンダするときに使用するデータをビューへ渡す必要があります。ビューでデータを利用できるようにする方法は2つあります。まず、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;

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

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

    /**
     * メッセージ内容の定義を取得
     *
     * @return \Illuminate\Mail\Mailables\Content
     */
    public function content()
    {
        return new Content(
            view: 'emails.orders.shipped',
        );
    }
}

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

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

withパラメータ経由

もし、テンプレートへ送る前にメールのデータフォーマットをカスタマイズしたい場合は、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;

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

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

    /**
     * メッセージ内容の定義を取得
     *
     * @return \Illuminate\Mail\Mailables\Content
     */
    public function content()
    {
        return new Content(
            view: 'emails.orders.shipped',
            with: [
                'orderName' => $this->order->name,
                'orderPrice' => $this->order->price,
            ],
        );
    }
}

データがwithメソッドに渡されると、ビューで自動的に利用できるようになるため、Bladeテンプレートの他のデータにアクセスするのと同じようにアクセスできます。

<div>
    Price: {{ $orderPrice }}
</div>

添付

メールに添付ファイルを追加するには、メッセージのattachmentsメソッドから返す配列に添付ファイルを追加します。最初に、Attachmentクラスが提供する、fromPathメソッドでファイルパスを指定して、添付ファイルを追加します。

use Illuminate\Mail\Mailables\Attachment;

/**
 * メッセージの添付を取得
 *
 * @return \Illuminate\Mail\Mailables\Attachment[]
 */
public function attachments()
{
    return [
        Attachment::fromPath('/path/to/file'),
    ];
}

メッセージへファイルを添付するときに、aswithMimeメソッドを使い、添付ファイルの表示名とMIMEタイプを指定することもできます。

/**
 * メッセージの添付を取得
 *
 * @return \Illuminate\Mail\Mailables\Attachment[]
 */
public function attachments()
{
    return [
        Attachment::fromPath('/path/to/file')
                ->as('name.pdf')
                ->withMime('application/pdf'),
    ];
}

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

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

/**
 * メッセージの添付を取得
 *
 * @return \Illuminate\Mail\Mailables\Attachment[]
 */
public function attachments()
{
    return [
        Attachment::fromStorage('/path/to/file'),
    ];
}

もちろん、添付ファイル名とMIMEタイプも指定できます。

/**
 * メッセージの添付を取得
 *
 * @return \Illuminate\Mail\Mailables\Attachment[]
 */
public function attachments()
{
    return [
        Attachment::fromStorage('/path/to/file')
                ->as('name.pdf')
                ->withMime('application/pdf'),
    ];
}

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

/**
 * メッセージの添付を取得
 *
 * @return \Illuminate\Mail\Mailables\Attachment[]
 */
public function attachments()
{
    return [
        Attachment::fromStorageDisk('s3', '/path/to/file')
                ->as('name.pdf')
                ->withMime('application/pdf'),
    ];
}

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

fromData添付メソッドを使用すると、生のバイト列を添付ファイルにできます。例えば、メモリ上でPDFを生成し、それをディスクへ一旦書き込まずにメールへ添付したい場合は、このメソッドを使用します。fromDataメソッドは、添付ファイルに割り当てるべき名前と同時に、生のデータバイトを解決するクロージャを受け取ります。

/**
 * メッセージの添付を取得
 *
 * @return \Illuminate\Mail\Mailables\Attachment[]
 */
public function attachments()
{
    return [
        Attachment::fromData(fn () => $this->pdf, 'Report.pdf')
                ->withMime('application/pdf'),
    ];
}

インライン添付

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

<body>
    Here is an image:

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

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

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

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

<body>
    Here is an image from raw data:

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

Attachableオブジェクト

単純な文字列のパスを介してメッセージへファイルを添付すれば十分なことがある一方で、多くの場合、アプリケーション内の添付可能(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
{
    /**
     * モデルの添付可能な形式を取得
     *
     * @return \Illuminate\Mail\Attachment
     */
    public function toMailAttachment()
    {
        return Attachment::fromPath('/path/to/file');
    }
}

添付可能なオブジェクトを定義したら、メールメッセージを作成する際にattachmentsメソッドにより、そのオブジェクトのインスタンスを返してください。

/**
 * メッセージの添付の取得
 *
 * @return array
 */
public function attachments()
{
    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は、添付ファイルをカスタマイズするために使用できる追加メソッドも提供しています。例えば、aswithMimeメソッドを使用して、ファイル名やMIMEタイプをカスタマイズできます。

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

ヘッダ

時には、送信するメッセージへ追加のヘッダを付ける必要が起きるかもしれません。例えば、カスタムMessage-Idや、その他の任意のテキストヘッダを設定する必要があるかもしれません。

これを行うには、Mailableでheadersメソッドを定義します。headersメソッドは、Illuminate\Mail\Mailables\Headersインスタンスを返す必要があります。このクラスは messageIdreferencestextを引数に取ります。もちろん、特定のメッセージに必要なパラメータだけを渡すこともできます。

use Illuminate\Mail\Mailables\Headers;

/**
 * メッセージヘッダの取得
 *
 * @return \Illuminate\Mail\Mailables\Headers
 */
public function 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()
{
    return new Envelope(
        subject: 'Order Shipped',
        tags: ['shipment'],
        metadata: [
            'order_id' => $this->order->id,
        ],
    );
}

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

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

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

Laravelのメール機能は、Symfony Mailerによって提供されています。Laravelでは、メッセージを送信する前に、Symfonyのメッセージインスタンスで呼び出されるカスタムコールバックを登録できます。これにより、メッセージ送信前に、そのメッセージを深くカスタマイズするチャンスが得られます。これを利用するには、Envelope定義でusingパラメータを定義します。

use Illuminate\Mail\Mailables\Envelope;
use Symfony\Component\Mime\Email;

/**
 * メッセージEnvelopeの取得
 *
 * @return \Illuminate\Mail\Mailables\Envelope
 */
public function envelope()
{
    return new Envelope(
        subject: 'Order Shipped',
        using: [
            function (Email $message) {
                // ...
            },
        ]
    );
}

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のContent定義をそのcontentメソッド内で設定するときに、viewパラメータの代わりに、markdownパラメータを使用します。

use Illuminate\Mail\Mailables\Content;

/**
 * メッセージ内容の定義を取得
 *
 * @return \Illuminate\Mail\Mailables\Content
 */
public function content()
{
    return new Content(
        markdown: 'emails.orders.shipped',
        with: [
            'url' => $this->orderUrl,
        ],
    );
}

Markdownメッセージの記述

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

<x-mail::message>
# 発送

注文を発送しました。

<x-mail::button :url="$url">
注文の確認
</x-mail::button>

Thanks,<br>
{{ config('app.name') }}
</x-mail::message>

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

ボタンコンポーネント

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

<x-mail::button :url="$url" color="success">
注文の確認
</x-mail::button>

パネルコンポーネント

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

<x-mail::panel>
ここはパネルの本文。
</x-mail::panel>

テーブルコンポーネント

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

<x-mail::table>
| Laravel       | テーブル         | 例  |
| ------------- |:-------------:| --------:|
| Col 2 is      | Centered      | $10      |
| Col 3 is      | Right-Aligned | $20      |
</x-mail::table>

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

カスタマイズするために、すべての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();
    }
}

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

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

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

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の構造を調べる数多くのメソッドを提供しています。さらに、期待するコンテンツがMailableに含まれているかをテストするために便利なメソッドをいくらか用意しています。これらのメソッドは以下の通りです。assertSeeInHtmlassertDontSeeInHtmlassertSeeInOrderInHtmlassertSeeInTextassertDontSeeInTextassertSeeInOrderInTextassertHasAttachmentassertHasAttachedDataassertHasAttachmentFromStorageassertHasAttachmentFromStorageDisk

ご想像のとおり、"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->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->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']);
}

Mailableの送信テスト

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

メールとローカル開発

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

Logドライバ

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

HELO/Mailtrap/Mailpit

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

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

グローバルな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サービスプロバイダで登録できます。

use App\Listeners\LogSendingMessage;
use App\Listeners\LogSentMessage;
use Illuminate\Mail\Events\MessageSending;
use Illuminate\Mail\Events\MessageSent;

/**
 * アプリケーションのイベントリスナマッピング
 *
 * @var array
 */
protected $listen = [
    MessageSending::class => [
        LogSendingMessage::class,
    ],

    MessageSent::class => [
        LogSentMessage::class,
    ],
];

カスタムトランスポート

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)
    {
        parent::__construct();

        $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 symfony/http-client

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')
            )
        );
    });
}

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

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

ドキュメント章別ページ

ヘッダー項目移動

注目:アイコン:ページ内リンク設置(リンクがないヘッダーへの移動では、リンクがある以前のヘッダーのハッシュを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)へ移動

その他

?

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