40
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Laravel RFC違反のメールアドレスにメール送信できるようにする

Last updated at Posted at 2019-09-12

ストーリー

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

電子メールに関するきまりが書かれたRFCRFC 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が返ってきます。

参考

40
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?