【Laravel】Mailableを使ってメール送信機能を実装する

##作成物
mailableクラスを使って、フォームを送信した際に、通知メールを送信する機能を実装します。
 
![スクリーンショット 2021-09-19 7.08.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208065/12e5f4dd-3cdc-7194-aad6-814605abf384.png)


#手順
1. ルーティングの設定
2. コントローラーの作成
3. ビューの作成
4. Mailableクラスの作成
5. メール文面の作成
6. メール送信設定　~ログへの書き出し~
7. メール送信設定 ~Mailtrapを使ってみる~   

##ルーティングの設定
まずはフォーム画面の表示と、入力内容を送信する際のルーティングを設定しておきます。

```web.php
//Laravel8
Route::get('/mail', [MailController::class,'index']);
Route::post('/mail', [MailController::class,'send']);

//Laravel7以前
Route::get('/mail', 'MailController@index');
Route::post('/mail', 'MailController@send');
```

##コントローラーの作成
indexメソッドとsendメソッドを持つコントローラーを作成します。

```
$ php artisan make:controller MailController
```
コントローラーを以下のように編集します。

```MailController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use App\Mail\TestMail;      //Mailableクラス
use Mail;

class MailController extends Controller
{
    public function index()
    {
        return view('mail.index');
    }

    public function send(Request $request)
    {
        $rules = [
            'name' => 'required|',
            'message' => 'required'
        ];

        $messages = [
            'name.required' => '名前を入力してください。',
            'message.required' => 'メッセージを入力してください。'
        ];

        $validator = Validator::make($request->all(), $rules, $messages);

        if($validator->fails()) {
            return redirect('/mail')
                ->withErrors($validator)
                ->withInput();
        }

        $data = $validator->validate();

        Mail::to('admin@hoge.co.jp')->send(new TestMail($data));

        session()->flash('success', '送信しました！');
        return back();
    }
}
```

###解説
* フォームのエラーチェックに使うバリデーター、後ほど作成するMailableクラス、Mailファサードを使うのでMailをuseしておきます。
* バリデーションについては説明は省略します。
* Mailファザードを利用してメールを送信します。toメソッドには宛先、sendメソッドにはmailableクラス（後述）のインスタンスを設定します。
* フォーム送信後はフォーム画面に戻ってフラッシュメッセージを表示するため、ここではフラッシュデータを保存しています。

##ビューの作成
フォーム画面を作成します。
resources/views/mail/index.blade.php

```php:index.blade.php
<form action="{{ url('mail') }}" method='POST'>
    @csrf
    <div class="form-group">

        <p>名前</p>
        <input type="text" name="name" value="{{ old('name') }}" class="form-control">
        @if ($errors->has('name'))
        <p class="bg-danger">{{ $errors->first('name') }}</p>
        @endif

        <p>メッセージ</p>
        <input type="text" name="message" value="{{ old('message') }}" class="form-control">
        @if ($errors->has('message'))
        <p class="bg-danger">{{ $errors->first('message') }}</p>
        @endif

        <p><input type="submit" value="送信" class="btn"></p>

    </div>
</form>


@if (Session::has('succsss'))
<div>
    <p class="bg-warning text-center">{{ Session::get('success')}}</p>
</div>
@endif
```

###解説
* inputタグのvalueにold関数を使い、バリデーションに引っかかった際は入力した内容が引き継がれるようにしています。
* Laravelのバリデーションを使って、エラーがある際はエラーメッセージを表示します。
* ページ下部にセッションを使ったフラッシュメッセージを配置しています。送信が完了した際はメッセージが表示されます。
* bootstrapを使って少し装飾を加えています。

##Mailableクラスの作成
メールの送信を担うMaildableクラスを作成します。
Laravelでは、Mailableクラスを作成するコマンドが用意されています。

```
$ php artisan make:mail SendTestMail
```
app/Mail/SendTestMailの位置に、ファイルが作成されます。

```SendTestMail.php
<?php

namespace App\Mail;

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

class SendTestMail extends Mailable
{
    use Queueable, SerializesModels;
    public $data;      //追加

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct($data)      //引数を追加
    {
        $this->data = $data;      //追加
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        //以下を追加
        return $this->view('mail.contact')
            ->subject('メッセージを受け付けました')
            ->from('sample@sample.com', 'テストメール事務局')
            ->subject('テストメールです。')
            ->with('data', $this->data);
    }
}

```
buildメソッドに、メールの中身となるviewテンプレート、メールの件名や送信者、引き継ぐデータを指定します。

##メール文面の作成
送信するメールの中身を記述します。
resources/views/mail/contact.blade.php

```php:contact.blade.php
<p>名前：{{ $data['name'] }}さん</p>
<p>メッセージ：{!! nl2br( $data['message'] ) !!}</p>

<p>メッセージが送信されました。</p>
```

##メール送信設定　~ログへの書き出し~
実際にサーバーを使用する前に、まずはLaravelのログにメール内容を表示してみます。
送信設定は`.env`ファイルで行います。

ログに書き出す場合は、以下のようにします。

```env:.env
MAIL_MAILER =log
```

では試してみたいと思います。
まずはローカルサーバーを立ち上げ、`localhost:8000/mail`にアクセスします。

```
$ php artisan serve
```
フォームに入力して、送信ボタンを押します。
![スクリーンショット 2021-09-20 11.00.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208065/4b51a6b3-a9cf-bb8a-98bb-21f16076f358.png)

送信するとフォーム画面に戻り、セッションによるフラッシュメッセージが出ています。
![スクリーンショット 2021-09-20 11.04.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208065/bca9ceb0-b721-55e5-4dae-63fc74ac0019.png)

ここではメールの内容をログに書き出すよう設定したので、`storage/logs/laravel.log`を確認すると、きちんとログ出力されています。

```laravel.log
[2021-09-20 11:00:51] local.DEBUG: Message-ID: <84089b12131c676930c9d57aeb8e60ad@127.0.0.1>
Date: Mon, 20 Sep 2021 11:00:51 +0900
Subject: =?utf-8?Q?=E3=83=86=E3=82=B9=E3=83=88=E3=83=A1?=
 =?utf-8?Q?=E3=83=BC=E3=83=AB=E3=81=A7=E3=81=99=E3=80=82?=
From: =?utf-8?Q?=E3=83=86=E3=82=B9=E3=83=88=E3=83=A1?=
 =?utf-8?Q?=E3=83=BC=E3=83=AB=E4=BA=8B=E5=8B=99=E5=B1=80?=
 <sample@sample.com>
To: admin@hoge.co.jp
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: quoted-printable

<p>名前：なまえさん</p>
<p>メッセージ：ログに書き出します。</p>

<p>メッセージが送信されました。</p>
```

##メール送信設定 ~Mailtrapを使ってみる~
ログへのメール内容の書き出しが正常に行われることが確認できたので、実際にメールを送信します。
送信するメールサーバ、ユーザアカウント、パスワードの情報が必要になるので、ここではMailtrapというサービスを使用してみます。

※Mailtrapとは、フェイクのSMTPテストサーバを提供するサービスです。

https://mailtrap.io

まずはMailtrapでアカウント登録を済ませます。
登録を完了したら「My inbox」画面に移動します。
Laravelを選択し、表示されたUsernameとPasswordの値をコピーし、.envファイルにそれぞれ設定します。

```env:.env
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=********    //Mailtrapよりコピぺ
MAIL_PASSWORD=********    //Mailtrapよりコピぺ
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
```
ではまた、ローカルサーバーを立ち上げ、`localhost:8000/mail`にアクセスします。
フォーム内容を入力して送信します。
![スクリーンショット 2021-09-20 13.28.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208065/ec075951-8925-617b-b7e2-f0fd347bac4f.png)

Mailtrapを開くと、メールが届いています。
コントローラーで設定した宛先、Mailableクラスで設定した送信者や件名、ビューで記述したメール文面もきちんと確認できます。
![スクリーンショット 2021-09-20 13.29.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208065/f57872e5-0658-4f1a-86a2-27cad8430eaf.png)


<br><br>
##参考記事

https://reffect.co.jp/laravel/laravel-send-email#Mail

https://reffect.co.jp/laravel/mailtrap-dummy-smtp-server

https://noumenon-th.net/programming/2020/05/16/mailable/