2013-10-22 2 views
20

データベースレイヤーに送信する前に、すべての入力を検証するクラスがあります。私の問題はエスケープや何かに関する問題ではないことに注意してください。私のデータベース層はSQLインジェクションの問題を処理します。私がしたいのは、その電子メールが有効であるかどうかを検証することです。なぜなら、その電子メールが「送信先」として使用される可能性があるからです。たとえば、ユーザーは電子メールに送信されたリンクを介して自分のアカウントへのアクセスを回復します。私はfilter_varについてたくさんのことを読んでいて、それに反対している人がたくさんいて、他の人が好きです。 「私は電子メールを検証し、データベースやHTMLやXSSなどのためにフィルタリングしない」ということに重点を置いて、filter_varを使用する際に問題がありますか?emailを検証するのにfilter_varを使うべきですか?

+5

電子メールが正しくフォーマットされていることを確認したい場合は、その目的のために問題ありません。本当のメールアドレスかどうかを知りたければ、メール検証サービスの料金を支払う必要があります。 –

+4

妥当性検査サービスに料金を支払う必要はありません。確認リンク付きのメールを送信してください。 – ComFreek

+0

はい、有効な電子メールアドレスであるかどうかを確認するには 'filter_var'を必ず使用してください。 – feeela

答えて

23

標準ライブラリの検証を使用する代わりに、自家製の一つは、複数の利点があります:既にあなたも、うまくいけば、電子メールの検証の経験で、使用されるコード(だけでなく、少なくとも2)を見

  1. 多くの眼球をそれがリリースに統合される前に。
  2. です。unit testedです。
  3. 他の人は同じチェックとreport bugsを使用し、これらの修正をPHPアップデートで無料で入手できます。

電子メールアドレスの形式を確認することは、本当のことを本当に知りたい場合は、最初の防衛線に過ぎません。メッセージを送信する必要があります。

+2

残念ながら、これは誰かが実際にそのようなバリデーションライブラリを維持し&さらに改善した場合にのみ真です。この場合、 'filter_var'を使うのはいくつかの危険があります:これはかなり長い間有効でしたが、ローカルパートではUTF8をサポートしていません。実際には' idn_to_ascii'でドメイン名を変換して、これは明らかではない。 'filter_var'を使用すると実際に有効な多くの失敗した電子メールアドレスを準備してください。これは、電子メールアドレスでユニコードが広く使用されている場合にのみより悪化します。 – iquito

8

はい、あなたが使用する必要がありfilter_varが、これは、あなたがそれを組み込むことができる方法である:はい、あなたがすべき

if(filter_var($email ,FILTER_VALIDATE_EMAIL)) 
{ 
    /* 
    * Rest of your code 
    */ 
} 
+0

PHPの全バージョンでは動作しません – denis

7

はい。しかし、checkdnsrr()もここで言及する価値があるかもしれません。

filter_var()は、ローカルコンテキスト(例:someone @ localhost)で有効な可能性があるため、不完全なドメインを承認します。これは、人々がTLDやドメイン名のドット(例えば[email protected])を見逃してしまう偽陽性につながる可能性があります。

ドメインでcheckdnsrr()ルックアップを実行してこれらをキャッチ - MXレコードが見つかった場合ドメインとアドレスが有効な場合、あなたはほとんどあなたのベストを尽くしました。

例コード:

if(filter_var($email, FILTER_VALIDATE_EMAIL)) 
{ 
    list($userName, $mailDomain) = explode("@", $email); 
    if (!checkdnsrr($mailDomain, "MX")) 
    { 
     // Email is unreachable. 
    } 
} 
else 
{ 
    // Email is bad. 
} 

checkdnsrr()は(私の経験では)かなりの瞬間であり、私はまだそれが動作しない環境を見つけていませんでした。

+0

私は時間があるときにチェックをしますが、手を離れて私はあなたが@gmailcomについて言及した例はfilter_varによって検証されないことを保証することができます。 –

+0

本当に十分です。かなり不明確な状況であっても、それ自体の問題です。 FILTER_VALIDATE_EMAILの失敗を一覧表示する[PHPバグレポート](https://bugs.php.net/bug.php?id=49576)があります。 checkdnsrr()を実行すると、そこのコードパッドの例で示されているすべての誤検出が検出されます。 – richplane

+0

checkdnsrrには20秒のタイムアウトがあることに注意してください(アプリケーションで経験したように、一部のドメインは20秒に達するように応答します)、ドメイン名は '特別な文字(ö、éなど)を持つドメインをサポートするために、まずidn_to_ascii()を使用します。私は 'passthru'で' dig 'を呼び出すように切り替えたので、タイムアウトとネームサーバを指定することができます。 – iquito

1

残念なことに、filter_varはアドレスのローカル部分(@の前)でUTF8をサポートしていないため、ドメイン名を別途idn_to_asciiで実行する必要があります(これは面倒です) 。

filter_varは、私の意見ではかなりユニークな電子メールアドレスが表示されますが、より正当な電子メールアドレスは失敗します。特に、中国やブラジルのような国では、より正当な電子メールアドレスが失敗します。これらのアドレス。 filter_varでは、[email protected]のような電子メールアドレスも許可されていません。これは有効であり、サーバーコンテキストで役立ちます。

電子メールライブラリが特定の指示に従って検証するために存在していた場合、本当に便利です - ドメイン名のみが許可されているか、localhostのような任意のホストか、有効であるべきカスタムドメインのホワイトリストがありますか?ユニコードを許可する必要がありますか? freemailドメイン名(@ homail.comなど)の一般的なタイプミスは失敗するはずです。

さらに特定の方法でドメイン名を検証することは賢明です - hotmail.comでは現在ユニコード文字は使用できず、使用可能な文字には特定の制限があります。 PHPアプリケーションで使用されるほとんどの電子メールアドレスはおそらく100種類の異なるドメインに集中しているため、これらのドメイン名をより良い方法で検証するために使用できます。残念ながら、私が知る限り、そのようなライブラリはまだ存在しません。

+0

あなたは電子メールアドレスをSANITIZEする必要がありますので、あなたのポイントは本当に完全に説明するものではありません。フィルタオプションなどを調べてください。 –

0

私が見たコメントの中には私のテストと一致しないものがあったので、私はPHP 5.xで見つかった機能を指摘したいと思っていました。電子メールを最初にSANITIZEすると、不要な文字がすべて削除されます。次に、VALIDATEを実行します。私は誰かがちょうどどちらかをやりたければ2つの機能を持っています。メールが有効な場合

チェック:

function isValidEmailAddress($email = '', $check_domain = false) 
{ 
    if (empty($email)) { 
     return false; 
    } else { 
     $success = true; 
    } 

    if (!filter_var((string) $email, FILTER_VALIDATE_EMAIL)) { 
     $success = false; 
    } 
    if ($check_domain && $success) { 
     list($name, $domain) = explode('@', trim($email) . "@"); 
     if (!checkdnsrr($domain, 'MX')) { 
      $success = false; 
     } 
    } 
    return array("success" => $success, "email" => $email); 
} 

が<を削除>をUTF8など:

function sanitizeEmailAddress($email = '') { 
    if (!empty($email)) { 
     $email = filter_var(strtolower(trim($email)), FILTER_SANITIZE_EMAIL); 
    } 
    return $email; 
} 

使用例:

// test -- 
$list = array('goodÂ@bad.com', '[email protected]', '[email protected]', '[email protected]', '', '<[email protected]>', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]'); 

foreach($list as $email) { 

    $ret = isValidEmailAddress(sanitizeEmailAddress($email), false); 
    if ($ret['success']) { 
     echo "GOOD " . $ret['email']; 
    } else { 
     echo "BAD " .$email; 
    } 
     echo "\n"; 
    } 

結果:

GOOD [email protected] 
GOOD [email protected] 
GOOD [email protected] 
BAD [email protected] 
BAD 
GOOD [email protected] 
GOOD [email protected] 
GOOD [email protected] 
GOOD [email protected] 
GOOD [email protected] 
GOOD [email protected] 

ドメインオプションを使用する場合:$ ret = isValidEmailAddress(sanitizeEmailAddress($ email)、true);

GOOD [email protected] 
GOOD [email protected] 
GOOD [email protected] 
BAD [email protected] 
BAD 
GOOD [email protected] 
GOOD [email protected] 
GOOD [email protected] 
BAD [email protected] 
BAD [email protected] 
BAD [email protected] 
関連する問題