【Laravel】Mailable jsonを受け取りメールを送信するAPIを作る

Mailableを使ったメール送信方法を試してみました。
今回は外部から以下に記述するJSONをPOSTで受け取り、JSONに記述されているメールアドレス(email)宛に内容(name, body)をメール本文に記述して送信するというAPIを作成します。GmailのSMTPサーバーを使用します。

#### 受け取るJSONファイル
```json:json
{
  "name":"example name",
  "email":"target@xxxxxx.com", //送り先のアドレス
  "body":"test body"
}
```

## .env の編集
.envファイルにGmailのSMTPサーバーを使う設定を行います。
事前にGmailのアプリパスワードを生成する必要があります。
参考: https://pc-karuma.net/google-account-generate-app-password/

```
MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME=xxxxx@gmail.com
MAIL_PASSWORD=****************
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS==null //Gmailの場合null
MAIL_FROM_NAME="${APP_NAME}"
```

## Controller 作成
```
php artisan make:Controller Api/MailController
```

## ルーティング作成
今回はAPIなので `routes/api.php` に記述します。
```php:routes/api.php
Route::post('/send', 'App\Http\Controllers\MailController@send');
```

## Mailableクラス作成
artisanコマンドでファイルを作成できます。
```
php artisan make:Mail MailSend
```

ファイルができたら中身を記述していきます。
まず、コンストラクトで`name`, `body`を受け取ります。
そして、`build()`関数では後ほど作成するメール本文のビューファイル`views/emails/body.blade.php`を呼び出し、
送り元アドレス(from)、タイトル(subject)、ビューに渡す値(with)を記述します。


```php:Mail/MailSend.php
<?php

namespace App\Mail;

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

class MailSend extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct(string $name, string $body)
    {
        $this->name = $name;
        $this->body = $body;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.body')
        ->from('xxxxx@xxxxxx.com') //送り元アドレス
        ->subject('テストメールです')
        ->with([
          'name' => $this->name,
          'body' => $this->body
        ]);
    }
}
```

## メール本文のビューファイル作成

```:views/emails/body.blade.php
<p>こんにちは、{{ $name }}さん</p>
<p>下記内容を受け取りました。</p>
<br>
<p>{{ $body }}</p>
```

## JSONを受け取る
POSTされたJSONデータを受け取ります。
```php:MailController.php
$raw = file_get_contents('php://input');
```

次に受け取ったJSONをphp変数に`json_decode()`で 変換します。
また、エラーを受け取りメッセージを返す処理を記述しておきます。
```php:MailController.php
$data = json_decode($raw, true); // json形式をphp変数に変換
$decode_err = json_last_error_msg();

if (!function_exists('json_last_error_msg')) {
  function json_last_error_msg() {
  static $ERRORS = array(
    JSON_ERROR_NONE => 'No error',
    JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
    JSON_ERROR_STATE_MISMATCH => 'State mismatch (invalid or malformed JSON)',
    JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
    JSON_ERROR_SYNTAX => 'Syntax error',
    JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded'
  );
  $error = json_last_error();
  return isset($ERRORS[$error]) ? $ERRORS[$error] : 'Unknown error'
}
```

## メール送信
メール送信は以下のように記述します。

```php:MailController.php
Mail::to($data['email'])->send(new MailSend($data['name'], $data['body']));
```

`to()`メソッドで送り先のアドレスを指定します。
`send()`内でMailSendインスタンスを作成し、引数として`name`, `body`を渡します。
これでAPIを外部で呼ぶとメールが送信されます。
Mailableを使うと簡単にメール送信を実装でき、いくらでも応用ができそうです。