Laravel『Mail Not Sent』の原因と対処法
- 作成日 2026.01.15
- その他
Laravelで「Mail Not Sent(メールが送れない)」状態は、Mailファサードの呼び出し自体が失敗して例外が出るケースだけでなく、キューに積まれて実行されていない、SMTP接続はできたが送信先に拒否された、送信は成功したが迷惑メール側に落ちた、など複数の層で起きる。まず「同期送信かキュー送信か」「Laravelが例外を出しているか(ログ)」「SMTP/送信サービスの応答(接続・認証・レート制限)」「受信側の拒否(SPF/DKIM/DMARC、From不正)」を切り分けると復旧が速い。
- 1. 症状と発生条件(典型例)
- 2. 最初の切り分け:同期送信か、キュー送信か
- 3. 原因1:.env のメール設定不備(MAIL_MAILER / HOST / PORT / USERNAME / PASSWORD)
- 4. 原因2:SMTPへの接続不可(ネットワーク/ファイアウォール/ポート閉塞)
- 5. 原因3:認証失敗(ユーザー/パスワード、アプリパスワード、二要素認証)
- 6. 原因4:暗号化/TLSの不整合(tls/ssl、証明書検証)
- 7. 原因5:受信側に拒否されている(550/554、Fromドメイン制限、SPF/DKIM/DMARC)
- 8. 原因6:キュー送信のworkerが動いていない/失敗ジョブが溜まっている
- 9. 原因7:ローカル/開発環境で “送れたように見えるが届かない” 設定
- 10. サンプル:送信テスト用ルート(例外を握り潰さずログに残す)
- 11. チェックリスト(上から順に確認する)
症状と発生条件(典型例)
発生条件の典型:
・Mail::to(…)->send(…) を呼ぶと例外が出る(接続不可、認証失敗、TLS失敗など)
・処理は成功するがメールが届かない(キュー未稼働、迷惑メール、バウンス)
・キュー送信(ShouldQueue)にしたら送れなくなった(worker未起動、失敗ジョブ溜まり)
・本番だけ送れない(ファイアウォールで25/587閉塞、DNS/SPF問題、送信元ドメイン制限)
よくあるログ/例外キーワード:
Connection could not be established with host
Failed to authenticate on SMTP server
Connection timed out
SSL: certificate verify failed
Expected response code 250 but got code "550"
Too many login attempts / Rate limit exceeded最初の切り分け:同期送信か、キュー送信か
Laravelは Mailable が ShouldQueue を実装していたり、MAIL_MAILER の設定やコード側で queue() を呼ぶとキュー送信になる。
・同期:send()
・キュー:queue() / later() / ShouldQueue
キュー送信のまま worker が動いていないと「送信したつもり」になる。
// 同期
Mail::to($user->email)->send(new WelcomeMail($user));
// キュー
Mail::to($user->email)->queue(new WelcomeMail($user));
まずは一時的に send() にして送信できるかを確認すると、キュー要因を早期に排除できる。
原因1:.env のメール設定不備(MAIL_MAILER / HOST / PORT / USERNAME / PASSWORD)
最頻出。特に本番で .env が違う、設定キャッシュが古い、が混ざるとハマりやすい。
確認する代表項目(例:SMTPの場合)。
MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=your_user
MAIL_PASSWORD=your_pass
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@example.com
MAIL_FROM_NAME="Example"設定を変えたら config キャッシュが残っていないかも確認する。
php artisan config:clear
php artisan cache:clear原因2:SMTPへの接続不可(ネットワーク/ファイアウォール/ポート閉塞)
発生条件の典型:
・クラウド/レンタルサーバで outbound 25 が塞がれている
・587/465 もセキュリティグループで閉じている
・DNS解決できない
・社内ネットワークから外部SMTPへ出られない
対処:
・587(STARTTLS)を優先して試す
・送信サービス(SES/SendGrid/Mailgun等)を利用する場合は推奨ポートに合わせる
・疎通確認(サーバ側で実施)
# DNS
nslookup smtp.example.com
# TCP疎通(環境により nc/telnet が使える)
nc -vz smtp.example.com 587接続タイムアウトが出るなら、アプリ以前にネットワーク層の問題が濃厚。
原因3:認証失敗(ユーザー/パスワード、アプリパスワード、二要素認証)
発生条件の典型:
・SMTPの資格情報が違う
・Gmail等で「アプリパスワード」が必要(2FA有効)
・送信サービスがAPIキー/SMTPキーを要求しているのに通常パスを入れている
対処:
・メールサービス側の「SMTP認証情報」を再発行
・.env の余計な空白や引用符の崩れを排除
・同一資格情報で他のクライアントから送れるか確認(切り分け)
原因4:暗号化/TLSの不整合(tls/ssl、証明書検証)
発生条件の典型:
・587なのに ssl を指定している / 465なのに tls を指定している
・証明書検証エラー(ca-certificates不足、古いOS)
対処:
・587 → MAIL_ENCRYPTION=tls
・465 → MAIL_ENCRYPTION=ssl
# 587
MAIL_PORT=587
MAIL_ENCRYPTION=tls
# 465
MAIL_PORT=465
MAIL_ENCRYPTION=ssl証明書検証で落ちる場合、OSのCA更新が必要なことがある(アプリ側の回避より、基盤更新が安全)。
原因5:受信側に拒否されている(550/554、Fromドメイン制限、SPF/DKIM/DMARC)
SMTP的には送信処理中に「550」等で弾かれ、Laravel側では例外や送信失敗として現れることがある。
発生条件の典型:
・MAIL_FROM_ADDRESS のドメインが送信サービスで認証されていない
・SPF/DKIM未設定でDMARCが厳しく、受信側が拒否
・FromとReturn-Pathの整合が取れていない
対処:
・送信サービス側でドメイン認証(SPF/DKIM)
・Fromは“認証済みドメイン”に統一
・エラーメッセージの応答コード(550など)をログから抜き出して、その文言の通りに修正する
原因6:キュー送信のworkerが動いていない/失敗ジョブが溜まっている
キュー化した瞬間に「送れない」になるパターン。
発生条件:
・queue:work を動かしていない
・Supervisor/systemd設定がなく、プロセスが落ちている
・失敗ジョブ(failed_jobs)が増えている
対処:
・workerの稼働確認
php artisan queue:work・失敗ジョブ確認
php artisan queue:failed・ジョブ再実行
php artisan queue:retry all本番運用では常駐プロセス管理(Supervisor等)で worker を維持する前提になる。
原因7:ローカル/開発環境で “送れたように見えるが届かない” 設定
開発環境で mailpit/mailhog/log ドライバを使っていると外部には届かない。
発生条件の典型:
・MAIL_MAILER=log(ログに出るだけ)
・MAIL_MAILER=array(メモリ内で破棄)
対処:
・本当に外部送信する環境では smtp などにする
MAIL_MAILER=smtp開発は mailpit、ステージング/本番は smtp のように環境で切り替える。
サンプル:送信テスト用ルート(例外を握り潰さずログに残す)
切り分け用に最小の送信を作ると原因が浮き出やすい。
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Log;
Route::get('/mail-test', function () {
try {
Mail::raw('mail test', function ($message) {
$message->to('you@example.com')
->subject('Mail Test');
});
return response('OK', 200);
} catch (\Throwable $e) {
Log::error('mail failed', ['error' => $e->getMessage()]);
return response('NG: '.$e->getMessage(), 500);
}
});キュー要因を避けるため、最初は raw + 同期送信で確認する。
チェックリスト(上から順に確認する)
1) 同期(send)かキュー(queue/ShouldQueue)かを切り分けたか
2) storage/logs/laravel.log にSMTP応答や例外メッセージ(550/timeout/auth)が残っているか
3) .env の MAIL_MAILER/HOST/PORT/USERNAME/PASSWORD/ENCRYPTION/FROM が正しいか
4) 設定変更後に config:clear を実施し、古い設定キャッシュを排除したか
5) サーバからSMTP先へ疎通できるか(DNS/ポート587/465、ファイアウォール)
6) 認証方式(アプリパスワード/SMTPキー)に合った資格情報を使っているか
7) 受信側拒否(550/DMARC等)の場合、Fromドメイン認証(SPF/DKIM)が整っているか
8) キュー送信なら worker が常時稼働し、failed_jobs が溜まっていないか
-
前の記事
Laravel『View [name] Not Found』の原因と対処法 2026.01.09
-
次の記事
Laravel『Invalid Session Driver』の原因と対処法 2026.01.16
コメントを書く