Laravelでメール送信機能を実装

最近Laravelでメールに関するタスクに携わることが多いのでメール送信機能を自分でも作ってみました。

メール送信機能を作ります。

環境構築は割愛します。
Laravel9 MySQL　PHP8系

ルーティング作成

```php:
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\MailSendController;

Route::get('/', function () {
    return view('welcome');
});

Route::get('/mail', [MailSendController::class, 'send']);

```

これで/mailにアクセスするとメール送信が行われるルーティングを作成します。


Mailableクラスを作成

```php
php artisan make:mail SendTestMail
```

```php:app/Mail/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;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.test')
                ->to('XXXXX@XXXXX.jp','鈴木太郎')
                ->from('XXX@XXXX','佐藤一郎')
                ->subject('テストメールです。');
    }
}
```



コントローラーの作成

```php
php artisan make:controller MailSendController
```

```php:app/Http/Controllers/MailSendController.php
<?php

namespace App\Http\Controllers;

use App\Mail\SendTestMail;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;

class MailSendController extends Controller
{
    public function send(){
        Mail::send(new SendTestMail());
        }
}
```

Viewファイル作成

```php:resources/views/emails/test.blade.php
<p>テストメールが届きました。</p>
```

送信したメール内容を確認するためにMailtrapを使います。

ユーザー登録して、Inboxes→My Inbox のIntegrationの下のプルダウンをLaravel7+にすると接続情報が出てくるので、.envファイルに記載します。

```
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=xxxxxxxxxxx
MAIL_PASSWORD=xxxxxxxxxxx
MAIL_ENCRYPTION=tls
```

/mailにアクセスしてメールが届いていることを確認します。

## 応用編としてメールが送られた日付とその日のメール回数をタイトルに出力する機能を作成


日付と回数を保持するモデルとテーブルを作成

```
php artisan make:model MailCount --migration
```

モデルの内容を編集
```php:MailCount
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class MailCount extends Model
{
    use HasFactory;

    protected $fillable = ['daily_mail_counts','sending_date'];

    protected $dates = [
        'sending_date'
    ];
}

```

マイグレーションファイル編集

```php:2022_XX_XX_XXXXXX_create_mail_counts_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('mail_counts', function (Blueprint $table) {
            $table->id();
            $table->integer('daily_mail_counts');
            $table->timestamp('sending_date');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('mail_counts');
    }
};
```

マイグレーション実行

```
php artisan migrate
```

コントローラーに処理を追記

```php:app/Http/Controllers/MailSendController.php
<?php

namespace App\Http\Controllers;

use App\Mail\SendTestMail;
use App\Models\MailCount;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;

class MailSendController extends Controller
{
    public function send(){
        $todayMail=MailCount::whereDate('sending_date', Carbon::today())->first();

        if ($todayMail) {
            $todayMail->daily_mail_counts += 1;
            $todayMail->save();
        }else {
            $todayMail = MailCount::create(['daily_mail_counts' => 1 ,'sending_date' => Carbon::now()]);
        }

        Mail::send(new SendTestMail($todayMail));
        }
}

```

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;

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

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.test')
                ->to('XXXXX@XXXXX.jp','鈴木太郎')
                ->from('XXX@XXXX','佐藤一郎')
                ->subject("{$this->todayMail->sending_date->format('Y/m/d')}の{$this->todayMail->daily_mail_counts}回目のテストメールです。");
    }
}
```

これでメールを送信すると、日付とその日のメール回数がタイトルに出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1008745/57c04d33-4242-dd81-d9bb-3c211f68f1b4.png)

以上です。

参考記事

これでLaravelメール送信が完全にわかる
https://reffect.co.jp/laravel/laravel-send-email
MailTrapのダミーのSMTPサーバ使ってテストメール送信
https://reffect.co.jp/laravel/mailtrap-dummy-smtp-server
Laravel 特定の日付・時間のデータ取得にはCarbonとwhereDateを使おう
https://biz.addisteria.com/laravel_carbon/
MailtrapでLaravelの簡単メール送信テスト
https://qiita.com/ubonsa/items/5514fb9c5d5783bcc758
PHPでdate_formatを使う方法を現役エンジニアが解説
https://techacademy.jp/magazine/31197
【Laravel】Eloquentのcreate、saveの使い分け、違いについて説明してみる
https://maasaablog.com/development/laravel/897/
『Carbon』でよく使うパターンをまとめてみた【Laravel向け】
https://coinbaby8.com/carbon-laravel.html
Laravelで日時順でレコードを取得する方法
https://leben.mobi/blog/laravel_desc_asc_get_record/php/
【Laravel入門】CRUD実装〜編集
https://qiita.com/yukibe/items/da6b49ed05e04e21017f
Laravel Viewでの日付フォーマットの変更
https://qiita.com/Ioan/items/cfab05315ec9f9d66a02
Call to a member function format() on string エラーの対処法
https://error-search.com/error-post/detail/527/%25E3%2580%2590%25E8%25A7%25A3%25E6%25B1%25BA%25E6%25B8%2588%25E3%2581%25BF%25E3%2580%2591Call%2Bto%2Ba%2Bmember%2Bfunction%2Bformat%2528%2529%2Bon%2Bstring%2B%25E3%2582%25A8%25E3%2583%25A9%25E3%2583%25BC%25E3%2581%25AE%25E5%25AF%25BE%25E5%2587%25A6%25E6%25B3%2595