本屋で立ち読みしてたら、Linux Journalって雑誌に "Validate an E-Mail Address with PHP, the Right Way" って記事が載っているのを発見したので、簡単に要約を。

まず、以下のメールアドレスは「正しい」アドレスである、と紹介。

これは、RFC3696からの引用。

RFC3696は、Application Techniques for Checking and Transformation of Names

(名前の検査と変換のアプリケーション技法) ってやつで、そのなかに、 "Restrictions on email addresses" って章があるみたい。

続いて、例として

http://www.devshed.com/c/a/PHP/Email-Address-Verification-with-PHP/2/

を挙げ、

function checkEmail($email) { if(preg_match("/^( [a-zA-Z0-9] )+( [a-zA-Z0-9\._-] )*@長いんでここで改行入れますね ( [a-zA-Z0-9_-] )+( [a-zA-Z0-9\._-] +)+$/" , $email)){ list($username,$domain)=split('@',$email); if(!checkdnsrr($domain,'MX')) { return false; } return true; } return false; }

この関数の間違ってるところを指摘。

正規表現が足りないのはすぐわかるからいいんだけど、DNSのチェックもおかしい、MXレコードが必ずあるとは限らないから、とも書いてある。(symfonyのは、ちゃんと調べてるみたいだ)

さらに

http://www.ilovejackdaniels.com/php/email-address-validation/

のスクリプトも紹介。

このスクリプトの著者Dave氏は、RFC2822をきちんと読んでvalidなメールアドレスの "local-part" が、1文字から64文字であることを理解している、と紹介。

このスクリプトの"the only major flaw" は、ユーザー名中に、 \@ が含まれるときうまく処理できないことらしい。

で、このあとが面白くて、「正しいメールアドレスの条件」10か条が、RFCの参照付きで紹介されている。

メールアドレスは local part と domain が @ で区切られて構成されている。(RFC2822) local partは、アルファベット、数字、以下の記号 ! # $ % & ' * + - / = ? ^ _ ` { | } ~ で、ドット「 . 」で区切られている場合がある。ただし、最初、最後、他のドットの隣にあってはいけない。(つまり連続しないことということか) (RFC2822 3.2.4) local partは、 クオーテーションマーク「 " 」のなかにスペースを含むいろんな文字が入った quoted string を含むことがある (RFC2822 3.2.5) \@ などの "quoted pair" をlocal partに含むものも「正しい」が "obsolete" (RFC822、RFC2822 4.4) (RFC2822はRFC822をsupersedeしてobsoleteにした、とある) local partの最大長は 64文字 (RFC2821 4.5.3.1) domainは、labelがドットで区切られたものである (RFC1035 2.3.1) domainは、アルファベットで始まり、その後に、0文字以上のアルファベット、数字、ハイフン「 - 」が続き、最後の一字はアルファベットか数字。(RFC1035 2.3.1) labelの最大長は 63字 (RFC1035 2.3.1) domainの最大長は 255字 (RFC2821 4.5.3.1) domainは、fully qualifiedで、DNSのtype AもしくはMXレコードでresolvableでなければならない (RFC2821 3.6)

んで、このあと3ページにわたって、色々解説しながら、PHPによるメールアドレス検証関数を実際に作っている。(それをここに写すのは、面倒なのとちょっと悪いような気がするので省略しますが、ご希望があるようなら考えます)

また、記事の最後に面白いことが書いてあるんだけど、 世間のメールアドレス検証は結構いい加減だ、てことは、 spamボットよけに、 {^c\@**Dog^}@example.com といったメールアドレスを使えるんじゃないか、という提案。

よく、webページに画像でメールアドレスを載せたりするけど、(アンカータグはらずに)このようなメールアドレスを文字で載せておけば、人間はコピペできて楽だし、ボットは正しく認識しない可能性が高いので安全じゃないか? みたいな。

……微妙かな。

今回、

正規表現：メールアドレスかどうか調べる - phpspot

↓

PHPでメールアドレスかどうか調べる方法

↓

re: PHPでメールアドレスかどうか調べる方法 (ハズレ日記)

と話題が進んできて(紹介漏れがあったらごめんなさい) ちょっと思ったんだけど、 メールアドレスに一致する正規表現に、「メールアドレスに一致する正規表現は「ありません」」って書いてあるけど、よくよむと、「クオートすればなんでも入るから」って話ですよね。

(このクソ長い正規表現て、確か、Oreillyの "Perl in a Nutshell" かなにかに載っていたような気がするんだけど、昔それ読んで、へー、メールアドレスの検証って大変なんだなーと思ったんだけど)

でも今回の記事読んで、ある程度現実的な線でちゃんとした検証する方法もあるんだなーと。思いました。(DNSはひかんでもいいような気がするけど)

あと、ちょっと文句みたいになるけど、「メールアドレスはこうやって検証すればいい」ってサンプルを紹介するときは、RFCなどの根拠を出さないとあまり意味がないような気がした。(この記事読んでそう思ったんだけど)

あ、あと今回読んだ記事は、Linux Journal の#158, June 2007号 に掲載されていたものでした。

http://www.linuxjournal.com/issue/158