PHP
正規表現
メールアドレス

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

More than 3 years have passed since last update.

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

<?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 (ユーザが存在しません)

  • その他

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