初心者目線でLaravelの基本的なメール送信を解説!具体的な設定例あり

Featured image of the post

概要

Laravelでメールを送信する方法を学習した🔰

同じ初学者でも理解できるように記録に残す。

メールは以下のような場面で使うことが多い。
  • ユーザー登録でメール認証をする
  • ユーザー登録が完了したことをお知らせする
  • ユーザー登録後にでパスワードをリセットする

💡
実装方法は色々あるがメジャーな方法を解説する

準備

メールを送信するために最初に設定が必要✅

送信元アドレスを設定

メール送信機能で使用するアドレスを設定する。

.env

MAIL_MAILER=smtp                     // メールドライバー(smtp,sendmailなど)
MAIL_HOST=mailhog                    // SMTPサーバーのホスト名
MAIL_PORT=1025                       // SMTPサーバーのポート番号
MAIL_USERNAME=null                   // SMTPサーバーにログインするために使用するユーザー名
MAIL_PASSWORD=null                   // SMTPサーバーにログインするために使用するパスワード
MAIL_ENCRYPTION=null                 // SMTPサーバーとの通信の暗号化
MAIL_FROM_ADDRESS=test@example.com // 送信元アドレス(表示用)
MAIL_FROM_NAME="${APP_NAME}"         // 送信者名(非表示用)

【補足】config/mail.php
  • 実際に設定しているところはconfig/mail.php✅
  • env(…)を使っているため.envファイルの設定が読み込まれている✅
'mailers' => [
        'smtp' => [
            'transport' => 'smtp',
            'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
            'port' => env('MAIL_PORT', 587),
            'encryption' => env('MAIL_ENCRYPTION', 'tls'),
            'username' => env('MAIL_USERNAME'),
            'password' => env('MAIL_PASSWORD'),
            'timeout' => null,
            'auth_mode' => null,
        ],
				...
],

'from' => [
    'address' => env('MAIL_FROM_ADDRESS', '[email protected]'),
    'name' => env('MAIL_FROM_NAME', 'Example'),
],

【補足】MAIL_USERNAMEとMAIL_FROM_ADDRESSの違い

どちらも同じものを指定することがあるが全く別物⚠️

  • MAIL_USERNAMEは、メールサーバーのログインに使うユーザー名。
  • MAIL_FROM_ADDRESSは、メールの「送信者」の欄に表示される送信元アドレス。

    実際のメールアドレスと異なっていてもOKなので送信者を偽ることも…💭

💡
ただし、GmailのときはMAIL_FROM_ADDRESSは不要!

自動的にMAIL_USERNAMEで上書きされる!

【備忘録】ローカル環境でGmailを送信成功したときの設定内容

自分がローカル実際で送信成功したときの設定✅

  • まず前提として、こちらのサイトを参考にアプリパスワードを発行する。
  • その後以下のように設定する。

.env

MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=xxxx@gmail.com
MAIL_PASSWORD=さっき発行したアプリパスワード
MAIL_ENCRYPTION=tls
# MAIL_FROM_ADDRESS=xxxx@gmail.com  👈Gmailのときは不要
MAIL_FROM_NAME="${APP_NAME}"

config/mail.php(SSLエラーの対処。詳細は後述。

'mailers' => [
    'smtp' => [
        'transport' => 'smtp',
        'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
        'port' => env('MAIL_PORT', 587),
        'encryption' => env('MAIL_ENCRYPTION', 'tls'),
        'username' => env('MAIL_USERNAME'),
        'password' => env('MAIL_PASSWORD'),
        'timeout' => null,
        'auth_mode' => null,

        // 以下追記
        'stream' => [
            'ssl' => [
                'allow_self_signed' => true,
                'verify_peer' => false,
                'verify_peer_name' => false,
            ],
        ],
    ],

【応用設定】特定の機能だけ別のアドレスで送信する場合

Mailableクラスでメール送信

Mailableクラスとは
  • 簡単にメール送信するためのクラス🔰
  • メールの送信先、件名、本文、添付ファイルなどを設定するためのメソッドが用意されている✅

【ステップ1】Mailableを生成する

コマンド1つでMailableを生成できる✅

php artisan make:mail php artisan make:mail クラス名

ポイント
  • メール機能1つにつき、Mailableを1つ生成する。
  • クラス名は機能が分かる名前がおすすめ。

    例:

    • WelcomeEmail:新規登録時のメール
    • PasswordResetEmail:パスワードリセットのためのメール
    • OrderConfirmationEmail:注文確認メール
    • ContactFormEmail:お問い合わせ完了メール

実演

WelcomeEmailクラスを生成する。

php artisan make:mail WelcomeEmail

以下のようなapp/Mail/WelcomeEmail.phpが生成されているはず。

(コメントを付け足している)

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class WelcomeEmail extends Mailable
{
		// コンストラクタ
    public function __construct()
    {
				// メールで使う情報があれば主にコンストラクタの引数で受け取る
    }

		// メールを送るメソッド
    public function build()
    {
				// メールを送る
        return $this->view('view.name');
    }
}

💡
これだけでMailableの生成はOK!

【ステップ2】最低限の設定

以下の設定をすればメール送信ができるようになる!

完成形

最初に完成形を紹介する。

とりあえず以下をコピペすれば動く✅

app/Mail/WelcomeEmail.php

class WelcomeEmail extends Mailable
{
    public function build()
    {
				return $this->to('[email protected]')             // 宛先
                    ->cc('[email protected]')             // CC
                    ->bcc('[email protected]')            // BCC
                    ->subject('会員登録が完了しました')     // 件名
                    ->view('mail.WelcomeEmail')         // 本文(HTMLメール)
                    ->text('mail.WelcomeEmail_text');   // 本文(プレーンテキストメール)
    }
}

resources/views/mail/WelcomeEmail.blade.php(手動でファイルを作成)

<h1>メールテスト</h1>
<p>会員登録ありがとうございます。</p>
<p>無事に登録完了しました。</p>

resources/views/mail/WelcomeEmail_text.blade.php(手動でファイルを作成)

メールテスト
会員登録ありがとうございます。
無事に登録完了しました。

それぞれの設定を詳しく解説していく。

宛先の設定

2つの設定方法がある✅

【方法1】Mailableクラス内で設定する
  • 常に宛先が同じ場合はこの方法で設定した方が楽。

  • to(’メールアドレス’)Toを設定できる。
  • cc(’メールアドレス’)CCを設定できる。
  • bcc(’メールアドレス’)BCCを設定できる。

app/Mail/WelcomeEmail.php

class WelcomeEmail extends Mailable
{
    public function build()
    {
        // メールの宛先
				// メソッドチェーンで複数指定できる
        return $this->to('[email protected]')   // To
										->cc('[email protected]')   // CC
										->bcc('[email protected]'); // BCC
    }
}

💡
送信先アドレスをMailableクラスにわたさないといけない

【方法2】Mailableクラス外で設定する
  • 宛先が動的に変わる場合はこの方法で設定した方が楽。
  • 後に【ステップ4】で解説する。

💡
送信先アドレスをMailableクラスにわたす必要がない

件名の設定
  • subject(’件名’)で設定できる。

app/Mail/WelcomeEmail.php

class WelcomeEmail extends Mailable
{
    public function build()
    {
        // メール件名
        return $this->subject('会員登録が完了しました');
    }
}

本文の設定

前提として、本文専用のbladeファイルを別途作成する必要がある⚠️

2つの設定方法があるが、両方設定しておくといい。✅

【方法1】HTML形式
  • HTML形式のメール本文を設定する。
  • view(’bladeファイル名’)で設定できる。

app/Mail/WelcomeEmail.php

class WelcomeEmail extends Mailable
{
    public function build()
    {
        // メール本文:ビューで別途定義
        return $this->view('mail.WelcomeEmail');
    }
}

resources/views/mail/WelcomeEmail.blade.php

※空のファイルを新規作成する。

※mailフォルダを作っておくと管理しやすい。

<h1>メール送信テスト</h1>
<p>これはHTMLメールです。</p>

【方法2】プレーンテキスト
  • 相手がHTMLメールをサポートしていないときに使われるメール本文を設定する。
  • text(’bladeファイル名’)で設定できる。

app/Mail/WelcomeEmail.php

class WelcomeEmail extends Mailable
{
    public function build()
    {
        // メール本文:ビューで別途定義
        return $this->view('mail.WelcomeEmail')       // HTMLメール
										->text('mail.WelcomeEmail_text'); // プレーンテキストメール
    }
}

resources/views/mail/WelcomeEmail_text.blade.php

メール送信テスト。
これはプレーンテキストメールです。

※空のファイルを新規作成する。

※ファイル名は「HTML用のファイル名_text」とすると管理しやすい。

※mailフォルダを作っておくと管理しやすい。

【補足】本文に値を渡す

2つの方法がある✅

【方法1】publicなプロパティ(よく使う)
  • コンストラクタでデータを受け取る場合によく使う。
  • Mailableクラスのpublicなプロパティは、何もせずにビューで使える。

app/Mail/WelcomeEmail.php

class WelcomeEmail extends Mailable
{
		// ①publicプロパティを宣言
		public $user;

		public function __construct( User $user )
    {
				// ②publicプロパティに値を設定(ユーザーデータを受け取る)
        $this->user = $user;
    }

    public function build()
    {
				// ビューの中で$userが使える!
        return $this->view('mail.WelcomeEmail')
										->text('mail.WelcomeEmail_text');
    }
}

💡
コントローラーなどからデータを受け取る場合はコンストラクタでもらう

【方法2】withメソッド(あまり使わない?)
  • publicプロパティが適さない以下のような場合に使う。

例1:コンスタントでもらったデータの一部だけビューに渡したい。

app/Mail/WelcomeEmail.php

class WelcomeEmail extends Mailable
{
    // ②ただのプライベートプロパティ
		// publicにするとビューで使えてしまうの、あえてプライベートにしている
    private $user_priv;

    public function __construct( User $user )
    {
        // ①ユーザーデータを保持するため一旦プロパティに入れる
        $this->user_priv = $user;
    }

    public function build()
    {
				// ③ユーザーデータの一部だけ渡す
        return $this->view('mail.WelcomeEmail')                 // HTMLメールの本文
                    ->text('mail.WelcomeEmail_text')            // プレーンテキストメールの本文
                    ->with([                                    // ビューで使う変数
                        'user_id', $this->user_priv->id,
                        'user_name' => $this->user_priv->name,
                    ]);
    }
}
💡
プログラムの設計上、不要なデータは渡さないほうがいい!

例2:一時的なデータでpublicプロパティに受け取る必要がない。

app/Mail/WelcomeEmail.php

class WelcomeEmail extends Mailable
{
    public function build()
    {
				// ①この関数だけで使う変数
				// わざわざプロパティにする必要がない
				$user = User::find(1);

				// ②ユーザーデータを渡す
        return $this->view('mail.WelcomeEmail')                 // HTMLメールの本文
                    ->text('mail.WelcomeEmail_text')            // プレーンテキストメールの本文
                    ->with([                                    // ビューで使う変数
                        'user', $user,
                    ]);
    }
}
💡
こんな場面はほとんどない…?

【ステップ3】その他の設定
添付
  • attach('ファイルのパス')で設定できる。

app/Mail/WelcomeEmail.php

class WelcomeEmail extends Mailable
{
    public function build()
    {
        return $this->view('mail.WelcomeEmail')       // HTMLメール
										->text('mail.WelcomeEmail_text')  // プレーンテキストメール
										->attach('/path/to/file');
    }
}

💡
ファイル名の指定などもできる。

詳細は以下を参照。

【ステップ4】Mailableを使ってメール送信
  • ここまで設定すればメールを送る準備はOK✅
  • あとはコントローラーなどでメールを送るだけ。

app/Http/Controllers/TestController.php

// ①追記
use Illuminate\Support\Facades\Mail;
use App\Mail\WelcomeEmail;

class TestController extends Controller
{
		public function hoge(){
        // ②メール送信に使うインスタンスを生成
        $welcomeMail = new WelcomeEmail();
				// ③メール送信
        Mail::send( $welcomeMail );

				// ④補足:ここで宛先を追加することもできる
				// Mail::to($request->test1)
				//     ->cc($request->test2)
				//     ->bcc($request->test3)
				//     ->send($welcomeMail);

				// ⑤送信成功か確認
				if (count(Mail::failures()) > 0) {
            $message = 'メール送信に失敗しました';

						// 元の画面に戻る
						return back()->withErrors($messages);
        }
        else{
            $messages = 'メールを送信しました';

						// 別のページに遷移する
						return redirect()->route('hoge')->with(compact('messages'));
        }				
    }
}

解説
  1. useを使いMailableを使うために必要なものを準備する。
  2. new WelcomeEmail()Mailableインスタンスを生成する。
  3. Mail::send(…)メールを送信する。
  4. to(…), cc(…), bcc(…)宛先を追加できる。
  5. if (count(Mail::failures()) > 0)エラーがあるか確認する。

💡
宛先の設定について。
Mailableクラスの中で設定することもできるが、動的に宛先が変わる場合はここで設定してもよい!

エラー対処

SSLエラー

以下のようなエラーが出た場合

ErrorException
stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed

原因
  • SSL証明書の検証に失敗している。

対処方法
  • ローカル環境ならSSL証明書の検証を無視すればOK。

config/mail.php

'mailers' => [
    'smtp' => [
        'transport' => 'smtp',
        'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
        'port' => env('MAIL_PORT', 587),
        'encryption' => env('MAIL_ENCRYPTION', 'tls'),
        'username' => env('MAIL_USERNAME'),
        'password' => env('MAIL_PASSWORD'),
        'timeout' => null,
        'auth_mode' => null,

        // 以下追記
        'stream' => [
            'ssl' => [
                'allow_self_signed' => true,
                'verify_peer' => false,
                'verify_peer_name' => false,
            ],
        ],

    ],

参考サイト

基本部分の導入が理解できた

仕組みが分かりやすかった

gmailを使う場合、内容が具体的でめちゃくちゃ参考になった

メール送信失敗の判定方法

公式ドキュメント