Laravel5.7: 日本語のパスワードリセット用のメールを送信する

# 親記事
[Laravel 5.7で基本的なCRUDを作る - Qiita](https://qiita.com/sutara79/items/ef30fcdfb7afcb2188ea)


# メールを送信できるようにする
まずは、Laravelでメールを送信できるようにします。

## メール送信の設定
Yahoo!メールまたはGmailのSMTPを利用して、ローカル環境と本番環境の両方でメールを送信します。

### Yahoo!メールの場合
:link: [Yahoo!メールのSMTP設定](https://www.yahoo-help.jp/app/answers/detail/p/565/a_id/47789/~/smtp-auth%E3%81%A8%E3%81%AF%EF%BC%88%E3%83%A1%E3%83%BC%E3%83%AB%E3%82%BD%E3%83%95%E3%83%88%E3%81%AE%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E8%AA%8D%E8%A8%BC%E8%A8%AD%E5%AE%9A%EF%BC%89)

```text:.env
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mail.yahoo.co.jp
MAIL_PORT=587
MAIL_USERNAME=<Yahooのユーザー名>
MAIL_PASSWORD=<Yahooのパスワード>
MAIL_ENCRYPTION=
MAIL_FROM_ADDRESS=<Yahooのユーザー名>@yahoo.co.jp
MAIL_FROM_NAME=demo-laravel-crud
```

※平文で送らないとエラーになるので、`MAIL_ENCRYPTION`は空欄にします。

### Gmailの場合
:link: [GmailのSMTP設定](https://support.google.com/a/answer/176600?hl=ja)

「安全性の低いアプリの許可」を有効にしなければなりません。
メール送信に使いたいGoogleアカウントでログインした上で、下記のページを開いてください。
:link: https://myaccount.google.com/lesssecureapps
![001.png](https://qiita-image-store.s3.amazonaws.com/0/27816/27a82547-b71d-b3d3-9841-d366f22158ae.png)

```text:.env
MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=<Gmailアドレス>
MAIL_PASSWORD=<Googleのパスワード>
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=<Gmailアドレス>
MAIL_FROM_NAME=demo-laravel-crud
```

## 送信の確認
実際にパスワードリセットのリンクをクリックしてもいいのですが、tinkerなら手軽に確認できます。
YahooとGmail両方を試す場合、`.env`を変更したらtinkerを一旦`exit`で終了してください。

```text:PowerShell
# tinkerを起動
> php artisan tinker

# メールを送信。「null」と表示されれば成功。数分後には実際にメールが届く。
>>> Mail::raw('test mail', function($message) {$message->to('<送信先アドレス>')->subject('Test');});
=> null
```

:link: [Laravel5.1でgmail経由でメール送信 - Qiita](https://qiita.com/zaburo/items/37f28f0b621cbac74d15)

どうしても送信に失敗する場合は、問題を切り分けるためにLaravelが利用しているswiftmailer単体でテストすることをおすすめします。
私の場合は、Yahoo!では対応していないTLSで暗号化しようとして失敗し続けていました。
:link: [swiftmailerでメールを送る (Gmail, Yahoo!メール経由)](https://qiita.com/sutara79/items/a187b1d50a46b86caec4)


# 独自のテンプレートで日本語のメール文を作る
下記を参考に進めていきます。
:link: [Laravel5.4でパスワード再設定メールテンプレートをカスタマイズ 一言多いプログラマーの独り言](http://programmer-jobs.blogspot.jp/2017/02/laravel-5-4-customize-reset-email-template.html)

## 独自の通知クラスを作る
:link: readouble.com: [通知の作成](https://readouble.com/laravel/5.7/ja/notifications.html#creating-notifications)

下記を実行して`app/Notifications/CustomPasswordReset.php`を生成してください。

```text:PowerShell
> php artisan make:notification CustomPasswordReset
```

## Userモデルのメソッドを上書きする
:link: readouble.com: [リセットメールのカスタマイズ](https://readouble.com/laravel/5.7/ja/passwords.html#password-customization)

下記のように`sendPasswordResetNotification()`メソッドを追記することで、Userモデルの親の
[Illuminate\Foundation\Auth\User](https://github.com/laravel/framework/blob/5.7/src/Illuminate/Foundation/Auth/User.php)クラスが利用している
[Illuminate\Auth\Passwords\CanResetPassword](https://github.com/laravel/framework/blob/5.3/src/Illuminate/Auth/Passwords/CanResetPassword.php)トレイトで定義されている同名のメソッドを上書きします。

```php:app/User.php
// 忘れずにインポートすること
use App\Notifications\CustomPasswordReset;

class User extends Authenticatable
{
    (中略)

    /**
     * パスワードリセット通知の送信
     *
     * @param  string  $token
     * @return void
     */
    public function sendPasswordResetNotification($token)
    {
        $this->notify(new CustomPasswordReset($token));
    }
```

## 通知クラスを編集する
下記のように修正します。

```diff:app/Notifications/CustomPasswordReset.php
+use Illuminate\Auth\Notifications\ResetPassword;
 
 class CustomPasswordReset extends Notification
 {
+    /** @var string */
+    public $token;
+
     /**
      * Create a new notification instance.
      *
+     * @param  string  $token
      * @return void
      */
-    public function __construct()
+    public function __construct($token)
     {
+        $this->token = $token;
     }

     public function toMail($notifiable)
     {
         return (new MailMessage)
-                    ->line('The introduction to the notification.')
-                    ->action('Notification Action', url('/'))
-                    ->line('Thank you for using our application!');
+                    ->subject(__('Reset Password'))
+                    ->view('emails.reset')
+                    ->action(__('Reset Password'), url('password/reset', $this->token));
     }
```

## メール本文を作る
下記のデフォルトのテンプレートを参考にして、新しくビューファイルを作ります。
:link: [laravel/framework/src/Illuminate/Notifications/resources/views/email.blade.php](https://github.com/laravel/framework/blob/5.7/src/Illuminate/Notifications/resources/views/email.blade.php)

```html:resources/views/emails/reset.blade.php
<h3>
    <a href="{{ config('app.url') }}">{{ config('app.name') }}</a>
</h3>
<p>
    {{ __('Click link below and reset password.') }}<br>
    {{ __('If you did not request a password reset, no further action is required.') }}
</p>
<p>
    {{ $actionText }}: <a href="{{ $actionUrl }}">{{ $actionUrl }}</a>
</p>
```

## 動作確認
1. 本物のメールアドレスでユーザー登録し、一旦ログアウトします。
1. 使用言語を日本語に切り替えます。
1. ログイン画面右下の「パスワードをお忘れですか?」をクリックして、パスワード再設定用のリンクを送ります。
1. 下記のような日本語のメールが届けば成功です。  
  ![001.png](https://qiita-image-store.s3.amazonaws.com/0/27816/06594e10-95e5-baba-601a-7e790c181140.png)