結論
Laravelのemail:dns バリデーションは、DNSが設定されている環境、されていない環境で結果が変わることがある。本調査では、example.com(NullNXレコードが設定されている)ドメインについてバリデーション結果が変わることを確認した。
# Before:DNSが設定されていない環境での実行結果
root@608e26d6b651:/var/www/html# php artisan tinker
Psy Shell v0.11.18 (PHP 8.2.9 ― cli) by Justin Hileman
> $v = validator(['email' => 'test@example.com'], ['email' => 'required|email:dns'])->passes();
= true
# After:DNSが設定されている環境での実行結果
root@608e26d6b651:/var/www/html# php artisan tinker
Psy Shell v0.11.18 (PHP 8.2.9 ― cli) by Justin Hileman
> $v = validator(['email' => 'test@example.com'], ['email' => 'required|email:dns'])->passes();
= false
関連
発生現象
- Laravelアプリケーションのテストを書いてPRを出したところ、自分のローカル開発環境で成功するテストが、GithubAction上の仮想環境では失敗する、という現象が発生した。
調査過程のメモ
-
ローカルでは成功しているのにGithubActionsでは失敗するテストは、いずれもEmailのバリデーションに関連するテストケースである。
-
各テストケースの入力値として「example.com」を使用しており、このドメイン名の名前解決が上手く行っていないのか?という仮説を立てて調査開始。
-
同僚に検証を依頼したところGithubActionで失敗するテストがローカル開発環境でも失敗するという報告をいただき、どうやら自分の環境がおかしい、ということになる。
dns_get_record() の実行結果検証
- Laravel のバリデーション email:dns はegulias/email-validatorを使用している
- この中で、dns_get_record() を使っているので、artisan tinker 経由で結果を見てみることにする。
自分の環境では、結果が空配列になっている。
# 自分の環境
root@608e26d6b651:/var/www/html# php artisan tinker
Psy Shell v0.11.18 (PHP 8.2.9 ― cli) by Justin Hileman
> dns_get_record("example.com", DNS_MX);
= []
同じ検証を同僚の端末で行ったところ、MXレコードはない(target が空文字列となっている)が、結果自体は返ってきている。
# 同僚の環境
> dns_get_record("example.com", DNS_MX);
= [
[
"host" => "example.com",
"class" => "IN",
"ttl" => 4667,
"type" => "MX",
"pri" => 0,
"target" => "",
],
]
DNS設定
こちらを見ながら、8.8.8.8と4.4.4.4を指定して、差分が解消した。
補足
- 結局、バリデーションを通過するテストケースはmxレコードが存在するemailを使用しなければならんのか?という問題が残る。テストケースに使うドメインは example.com
- こっちのバリデーション https://readouble.com/laravel/10.x/ja/validation.html#rule-active-url も、DNS設定できない環境だと動作がかわる(かも?) ただ、example.comはAレコードは引けるので、関係ないかも。細かくは調査してない