ストーリー
Laravel RFC違反しているメールアドレスをサクッと探すtipsより。
RFC違反しているメールアドレスを見つけたところで、送信できるようにして欲しいという無茶苦茶な要望があります。
そんな無茶振りに対応する方法をご紹介します。
環境
- PHP 7.2
- Laravel 5.7
RFC違反のメールアドレスの例
-
example.-.@example.com
-
@
の前に.
を置いてはならない
-
-
.example@example.com
-
.
から開始してはならない
-
-
ex..ample@example.com
-
.
が連続してはいけない
-
エラー
$ php artisan tinker
このRFC違反メールアドレスにLaravelからメールを送信しようとするとSwift_RfcComplianceException
という例外が発生します。
Mail::raw('test mail',function($message){$message->to('example.-.@example.com')->subject('test');});
Swift_RfcComplianceException with message 'Address in mailbox given [test.@example.com] does not comply with RFC 2822, 3.6.2.'
RFC 2822
電子メールに関するきまりが書かれたRFC。RFC 822を破棄し、新標準となった。
対応策
Swiftmailer
のコンテナに独自のバリデータを読み込ませる事で対応します。
app/Validation/AllowNonRfcComplaintEmailValidator.php
<?php
namespace App\Validation;
use Egulias\EmailValidator\EmailValidator;
use Egulias\EmailValidator\Validation\EmailValidation;
class AllowNonRfcComplaintEmailValidator extends EmailValidator
{
/**
* 最低限、@が含まれていて、ドメインとアカウント名が含まれているメールアドレスは許可します
* @param string $email
* @param EmailValidation $emailValidation
* @return bool
*/
public function isValid($email, EmailValidation $emailValidation): bool
{
// warningsとerrorのプロパティを埋める
parent::isValid($email, $emailValidation);
if (substr_count($email, '@') !== 1) {
return false;
}
list($account, $domain) = explode('@', $email);
if (strlen($account) > 0 && strlen($domain) > 0) {
return true;
}
return false;
}
}
parent::isValid($email, $emailValidation)
戻り値は使用してないですが、
親関数ので実行している warnings
, errors
プロパティを埋める処理を呼び出してます。
app/Providers/AllowNonRfcComplaintEmailPatchServiceProvider.php
<?php
namespace App\Providers;
use App\Validation\AllowNonRfcComplaintEmailValidator;
use Illuminate\Support\ServiceProvider;
use Swift;
use Swift_DependencyContainer;
class AllowNonRfcComplaintEmailPatchServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot(): void
{
Swift::init(
function () {
Swift_DependencyContainer::getInstance()
->register('email.validator')
->asSharedInstanceOf(AllowNonRfcComplaintEmailValidator::class);
}
);
}
}
config/app.php
return [
'providers' => [
// ...
App\Providers\AllowNonRfcComplaintEmailPatchServiceProvider::class,
],
];
動作確認
$ php artisan tinker
Mail::raw('test mail',function($message){$message->to('example.-.@example.com')->subject('test');});
null
成功したらnull
が返ってきます。