PHPでメールアドレスを確認する「正しい方法」(Linux Journal誌の記事より)
本屋で立ち読みしてたら、Linux Journalって雑誌に "Validate an E-Mail Address with PHP, the Right Way" って記事が載っているのを発見したので、簡単に要約を。
まず、以下のメールアドレスは「正しい」アドレスである、と紹介。
- Abc\@def@example.com
- customer/department=shipping@example.com
- !def!xyz%abc@example.com
これは、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ページに画像でメールアドレスを載せたりするけど、(アンカータグはらずに)このようなメールアドレスを文字で載せておけば、人間はコピペできて楽だし、ボットは正しく認識しない可能性が高いので安全じゃないか? みたいな。
……微妙かな。
今回、
↓
↓
re: PHPでメールアドレスかどうか調べる方法 (ハズレ日記)
と話題が進んできて(紹介漏れがあったらごめんなさい) ちょっと思ったんだけど、 メールアドレスに一致する正規表現に、「メールアドレスに一致する正規表現は「ありません」」って書いてあるけど、よくよむと、「クオートすればなんでも入るから」って話ですよね。
(このクソ長い正規表現て、確か、Oreillyの "Perl in a Nutshell" かなにかに載っていたような気がするんだけど、昔それ読んで、へー、メールアドレスの検証って大変なんだなーと思ったんだけど)
でも今回の記事読んで、ある程度現実的な線でちゃんとした検証する方法もあるんだなーと。思いました。(DNSはひかんでもいいような気がするけど)
あと、ちょっと文句みたいになるけど、「メールアドレスはこうやって検証すればいい」ってサンプルを紹介するときは、RFCなどの根拠を出さないとあまり意味がないような気がした。(この記事読んでそう思ったんだけど)
あ、あと今回読んだ記事は、Linux Journal の#158, June 2007号 に掲載されていたものでした。