SendGridをLaravelから使ってメール送信を実装する

概要

Webアプリケーションでは、会員登録の確認メール・パスワードリセット・各種通知など、メール送信が必ずと言っていいほど必要になります。自前でメールサーバを運用するのは到達率(deliverability)・SPF/DKIM・バウンス処理などの観点で負担が大きいため、実務ではメール配信サービスを使うのが一般的です。

本記事では、メール配信サービスの SendGrid を Laravel から使ってメール送信を実装する手順を、ハンズオン形式でまとめます。接続方法には SMTPリレー と Web API の2通りがあり、両方を扱います。あわせてキュー送信・Webhookによるイベント受信・送信元ドメイン認証といった実運用の観点にも触れます。

環境

  • PHP 8.3 以上
  • Laravel 12 / 13
  • SendGrid アカウント(無料プランでも検証可能)
  • Composer

SendGridの2つの接続方式

方式 概要 向いているケース
SMTPリレー smtp.sendgrid.net にSMTP接続 既存のLaravel標準メール機構をそのまま使いたい
Web API (v3) HTTPSのREST APIで送信 SMTPポートが塞がれている・スループット重視

Laravelの標準メール機能は symfony/mailer をベースにしているため、SMTP方式はパッケージ追加なしで動きます。API方式はトランスポートドライバを追加すると、同じ Mail ファサードのまま裏側だけ切り替えられます。

事前準備:APIキー発行と送信元認証

APIキーの発行

管理画面 Settings > API Keys からAPIキーを発行します。最小権限の原則に従い、送信だけなら Restricted Access で Mail Send のみを許可します。

発行したAPIキーは発行時にしか全体表示されません。安全に控え、Gitには絶対にコミットせず .env で管理してください。

送信元ドメイン認証

到達率を上げるため、Settings > Sender Authentication で Domain Authentication を設定し、表示されたCNAMEをDNSに登録します。これでSPF/DKIMが有効になり、迷惑メール判定されにくくなります。検証段階ではSingle Sender Verificationでも送信可能ですが、本番ではドメイン認証を推奨します。

方式1:SMTPリレーで送る

パッケージ追加不要の方式です。.env を次のように設定します。

MAIL_MAILER=smtp
MAIL_HOST=smtp.sendgrid.net
MAIL_PORT=587
MAIL_USERNAME=apikey
MAIL_PASSWORD=${SENDGRID_API_KEY}
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="no-reply@example.com"
MAIL_FROM_NAME="${APP_NAME}"

重要なのは MAIL_USERNAME をリテラルで apikey という文字列 にする点です。SendGridのSMTP認証ではユーザー名が固定(apikey)、パスワードに実際のAPIキーを入れる独自仕様です。知らないとハマりやすいポイントです。

設定を変えたらキャッシュをクリアします。

php artisan config:clear

方式2:Web APIで送る

SMTPポートが使えない環境や高スループットが欲しい場合はAPI方式です。ドライバパッケージを導入します。

composer require s-ichikawa/laravel-sendgrid-driver

composer require で入る 4.x 系は Laravel 11 / 12 に対応しており(公式リポジトリの対応表には Laravel 13 も追加されています)、sendgrid トランスポートの追加方法は現行でも有効です。

MAIL_MAILER=sendgrid
SENDGRID_API_KEY=your_api_key_here
MAIL_FROM_ADDRESS="no-reply@example.com"
MAIL_FROM_NAME="${APP_NAME}"

config/mail.php にトランスポートを追加します。

'mailers' => [
    // ... 既存の smtp 等 ...

    'sendgrid' => [
        'transport' => 'sendgrid',
    ],
],

これで Mail ファサードの使い方を変えずに送信経路だけAPIに差し替わります。

実装例

Mailableクラス

php artisan make:mail WelcomeMail --markdown=emails.welcome
<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class WelcomeMail extends Mailable
{
    use Queueable, SerializesModels;

    public function __construct(public string $userName) {}

    public function envelope(): Envelope
    {
        return new Envelope(subject: 'ご登録ありがとうございます');
    }

    public function content(): Content
    {
        return new Content(
            markdown: 'emails.welcome',
            with: ['userName' => $this->userName],
        );
    }
}

Markdownテンプレート

resources/views/emails/welcome.blade.php:

<x-mail::message>
# {{ $userName }} 様

このたびはご登録いただきありがとうございます。

<x-mail::button :url="config('app.url')">
サービスを開く
</x-mail::button>

今後ともよろしくお願いいたします。
</x-mail::message>

送信

use App\Mail\WelcomeMail;
use Illuminate\Support\Facades\Mail;

Mail::to($user->email)->send(new WelcomeMail($user->name));

SMTP方式でもAPI方式でも、このコードは共通です。

キュー送信(推奨)

メール送信はネットワークI/Oを伴うため、HTTPリクエスト処理中に同期送信するとレスポンスが遅くなります。queue() で非同期化します。

Mail::to($user->email)->queue(new WelcomeMail($user->name));
php artisan queue:work

QUEUE_CONNECTION は sync 以外(database/redis)にします。送信失敗時のリトライも効くようになります。

確認方法

Tinkerで疎通確認

Mail::to('test@example.com')->send(new App\Mail\WelcomeMail('テスト太郎'));

例外なく完了し、管理画面 Activity にログが載れば成功です。

ログドライバで中身確認

一時的に MAIL_MAILER=log にすると storage/logs/laravel.log に本文が書き出され、テンプレートの崩れを確認できます。

Webhookでイベント受信

バウンス・開封などのイベントは Settings > Mail Settings > Event Webhook にエンドポイントを登録して受け取ります。

Route::post('/webhooks/sendgrid', function (Request $request) {
    foreach ($request->json()->all() as $event) {
        Log::info('sendgrid event', [
            'event' => $event['event'] ?? null,
            'email' => $event['email'] ?? null,
        ]);
        // bounce/dropped はここで配信停止リストに反映
    }
    return response()->noContent();
});

Signed Event Webhookで署名検証すると安全です。

注意点

  • APIキーはコミットしない(.env+シークレット管理で注入)
  • SMTP認証のユーザー名は固定で apikey
  • Fromは認証済みドメインにする(到達率に直結)
  • バウンス・スパム報告はWebhookで検知して配信停止に反映
  • 本番の送信はキュー化を徹底
  • プランごとのレート制限に注意

まとめ

LaravelからSendGridを使うには、SMTPリレー方式ならパッケージ不要で .env 設定だけ(ユーザー名は apikey 固定)、API方式ならドライバを追加して MAIL_MAILER=sendgrid にするだけで、アプリコードはそのまま。どちらも Mail ファサードの使い方は共通です。送信元ドメイン認証・キュー送信・Webhookによるバウンス処理までセットで考えると、到達率と信頼性の高いメール基盤になります。

\ 最新情報をチェック /

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。