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によるバウンス処理までセットで考えると、到達率と信頼性の高いメール基盤になります。
