Laravel Email 验证规则仅线上服务器失效的可能原因问询
Laravel订单表单邮箱验证线上失败问题修复
我通过Laravel内置的FormRequest表单验证实现客户订单输入校验,对应验证类代码如下:
<?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; class CreateOrderWebstoreRequest extends FormRequest { /** * Determine if the user is authorized to make this request. * * @return bool */ public function authorize() { return true; } /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { // Use additional Address valudation rules if Order is not picked up // dd('debugging halt',request()); $address_rules = []; if (! request()->is_pickup) { $address_rules = [ 'street' => 'required|min:3|max:100', 'house_number' => 'required|numeric|max:100000', 'house_number_suffix' => 'nullable|max:10', 'postal_code' => 'required|max:10', 'town' => 'required|min:3|max:50', 'country' => 'required|min:2|max:2', 'region' => 'nullable|min:3|max:50', 'owner' => 'nullable|min:3|max:25', ]; } return array_merge([ 'first_name' => 'required|min:3|max:50', 'middle_name' => 'nullable|min:1|max:15', 'last_name' => 'required|min:3|max:50', 'company_name' => 'nullable|min:3|max:50', 'email_address' => 'required|email:rfc,dns|max:50', 'telephone_number' => 'nullable|min:10|max:25', 'description' => 'nullable|min:5|max:250', ], $address_rules); } public function messages() { return [ ]; } }
问题现象
- 该套校验规则已稳定运行数月无异常,最近一周突然有多名客户反馈邮箱验证失败,触发validation.php中
email规则对应的默认错误提示 - 问题仅在线上生产环境出现,本地开发环境完全无法复现
环境信息
线上环境:运行于Laravel专用共享主机,Laravel版本6.18.15,PHP版本7.4.16
本地开发环境:Laravel版本6.18.10,PHP版本7.4.2
此前曾出现过主机方未正常更新PHP版本的问题,本次暂未排查到同类配置问题
已尝试操作的问题
尝试将邮箱验证规则修改为'email' => 'required|regex:/(.+)@(.+)\.(.+)/i'时,会抛出「IDN Conversion Failed」错误。
根因分析
该问题由两方面共同触发:
- 共享主机近期更新了PHP intl扩展或DNS服务器配置,Laravel原生
email:rfc,dns规则中的DNS校验、国际化域名(IDN)转换逻辑受环境影响出现异常,部分带特殊字符、新顶级域名的邮箱会被误判为非法 - Laravel 6.x版本的邮箱验证对intl扩展的兼容性存在已知小问题,PHP小版本更新后容易出现IDN转换失败的报错
修复方案
方案1:降低验证严格度(优先推荐)
去掉DNS校验项,仅保留RFC标准格式校验,修改email_address的验证规则为:
'email_address' => 'required|email:rfc|max:50',
RFC标准校验已经可以过滤绝大多数格式非法的邮箱,DNS校验本身受网络波动影响误判率较高,去掉后几乎不会增加垃圾订单量,可解决90%以上的偶发验证失败问题。
方案2:关闭IDN转换
如果修改规则后仍然存在IDN转换报错,可在app/Providers/AppServiceProvider.php的boot方法中添加配置,全局关闭邮箱验证的IDN转换逻辑:
use Illuminate\Validation\Concerns\ValidatesAttributes; public function boot() { ValidatesAttributes::$validateIdn = false; }
该配置仅对Laravel 6.18及以上版本生效,关闭后不会影响普通域名邮箱的验证,同时可以彻底解决IDN转换失败的报错。
方案3:自定义验证规则(兜底方案)
如果业务确实需要保留邮箱域名的MX校验,可以自定义验证规则绕开原生逻辑的依赖问题:
- 先在
AppServiceProvider的boot方法中注册自定义验证规则:
use Validator; public function boot() { Validator::extend('custom_email', function ($attribute, $value, $parameters, $validator) { // 基础格式校验 if (!filter_var($value, FILTER_VALIDATE_EMAIL)) { return false; } // 可选:MX记录校验 $domain = substr(strrchr($value, "@"), 1); return checkdnsrr(idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46), "MX"); }); }
- 修改验证规则调用自定义规则:
'email_address' => 'required|custom_email|max:50',
内容的提问来源于stack exchange,提问作者Stroomschok
相关产品推荐
相关产品推荐

