LoginSignup
50
51

More than 5 years have passed since last update.

そろそろメールアドレスを正規表現だけでチェックするのは終わりにしませんか?

Last updated at Posted at 2015-08-10

メールアドレス + 正規表現 となるとまあ、当事者でなくても二の足を踏んでしまいますが…

<?php

function email_check($email)
{
    $pattern = '/^[^0-9][a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*@\[?([\d\w\.-]+)]?$/';
    return preg_match($pattern, $email, $matches) && checkdnsrr($matches[2], 'MX');
}

この程度で十分な気がするんですが、どうでしょうね…。
ドメインの存在チェックする方がよっぽど使えると思うのです。

checkdnsrr

同じページに checkdnsrr を利用したメールアドレスのバリデーション例がありますね。eregi を利用しているのはいただけませんが…10年前の投稿なのでやむなし。

ちなみに、@より前の部分については、もっとこうした方がいいのではなどありましたら「優しく」ご指摘ください。

コメントより、

MXレコードがなくても妥当なメールアドレスです。代わりにA (かAAAA) レコードを引きに行くので。

ご指摘を受けて。@mpyw さんのコードこちらは @[xxx.xxx.xxx.xxx] 形式のアドレスは弾きます。

<?php

function email_check($email)
{
    $pattern = '/@([\w.-]++)\z/';
    return filter_var($email, FILTER_VALIDATE_EMAIL) &&
        preg_match($pattern, $email, $matches) &&
        (checkdnsrr($matches[1], 'MX') || checkdnsrr($matches[1], 'A') || checkdnsrr($matches[1], 'AAAA'));
}

もう一つの案、一応、@[xxx.xxx.xxx.xxx] 形式のアドレスを受け付けます。

<?php

function email_check($email)
{
    $arr = explode("@", $email);
    $domain = str_replace(array('[', ']'), "", array_pop($arr));
    return filter_var($email, FILTER_VALIDATE_EMAIL) &&
        (checkdnsrr($domain, 'MX') || checkdnsrr($domain, 'A') || checkdnsrr($domain, 'AAAA'));
}

さらに…

@mpyw さんの記事
PHPで各種バリデーション

後になって気付いた副産物

この方法だと、送信前にチェックすることで、Return mail で送信不能になるメールアドレスをあらかじめ取り除くことが可能ですね。

メールの不達にはいろいろ理由はありますが、

  • Host unknown (ホストが存在しません)
  • User unknown (ユーザが存在しません)
  • その他

少なくとも「ホストが存在しない」場合の送信を未然に対処できますね。

50
51
7

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
50
51