2013-10-22 39 views
20

我有一個類在我將其發送到數據庫層之前驗證每個輸入。請注意,我的問題不是逃避或任何東西。我的數據庫層將處理SQL注入問題。我想要做的就是驗證電子郵件是否有效,因爲之後該電子郵件可能被用作「發送至」。例如,用戶將通過發送到電子郵件的鏈接恢復對其帳戶的訪問。我讀了很多關於filter_var的文章,並且有很多人反對和其他一些人贊成。將重點放在'我只想驗證電子郵件並且不過濾數據庫或HTML或XSS或其他',使用filter_var時是否存在問題?我應該使用filter_var來驗證電子郵件嗎?

+5

如果您想確保電子郵件的格式正確,那就很好了。如果您想知道它是否是真實的電子郵件地址,那麼您最需要爲電子郵件驗證服務付費。 –

+4

您無需爲驗證服務付費。只需發送一封包含驗證鏈接的電子郵件。 – ComFreek

+0

是的,你應該使用'filter_var'來檢查這是否是一個有效的電子郵件地址,因爲這是PHP中檢查電子郵件地址的唯一可靠方法... – feeela

回答

23

是的,你應該。

使用標準庫的驗證,而不是家釀一個有多方面的好處:

  1. 無數眼球已經看過的代碼(當然,至少兩個)將要使用,希望在電子郵件驗證,即使經驗在合併到發佈之前。
  2. 這是unit tested
  3. 其他人將使用相同的支票和report bugs,你可以在PHP更新中免費獲得這些修復程序。

但是,檢查電子郵件地址的格式只是第一道防線,如果你真的想知道它是否真實,你將不得不發送一條消息給它。

+2

不幸的是,這是隻有當有人真正維護並進一步改進了這種驗證庫時纔是如此。在這種情況下,使用'filter_var'有一些危險:它在本地部分不支持UTF8,即使這已經有效一段時間了,並且實際上您必須自己將域名轉換爲idn_to_ascii來驗證國際域名,這並不明顯。如果你使用'filter_var',爲許多失敗的電子郵件地址做好準備,而且這種情況只會在unicode在電子郵件地址中被廣泛使用時變得更糟。 – 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

夠正確。這本身就是一個問題,儘管只是在相當模糊的情況下。有一個[PHP錯誤報告](https://bugs.php.net/bug.php?id=49576)列出了FILTER_VALIDATE_EMAIL的缺陷;做checkdnsrr()會捕獲鍵盤示例中給出的所有誤報。 – richplane

+0

請注意,checkdnsrr的超時時間爲20秒,顯然無法更改(某些域的響應方式使其達到20秒,因爲我必須在我的應用程序中體驗過),並且域名應由「 idn_to_ascii()'首先支持帶有特殊字符的域(如ö,é等)。我改用'passthru'調用'dig',這樣我就可以指定一個超時和使用什麼名字服務器。 – iquito

1

不幸的是,filter_var在地址的本地部分(位於@之前)不支持UTF8,並且爲了支持國際域名,您需要分別通過idn_to_ascii運行域名(這很麻煩而且不明顯) 。

這使得filter_var在我看來相當無用:越是unicode的電子郵件地址出現,越合法的電子郵件地址將失敗,對於像中國或巴西這樣的國家來說尤其如此,這些地址。 filter_var也不允許使用電子郵件地址,例如[email protected],這些地址在服務器上下文中有效且可能有用。

如果存在根據特定指令進行驗證的電子郵件庫會非常有用 - 只允許使用域名,還是像localhost這樣的任意主機,或者是否存在適用於自定義域的白名單?應該允許unicode?免費郵箱域名(如@ homail.com)常見的拼寫錯誤是什麼?

此外,以更具體的方式驗證某些域名將是明智的 - hotmail.com目前不允許unicode字符,並對可用字符有特定的限制。由於PHP應用程序中大多數使用的電子郵件地址都集中在可能有100個不同的域上,因此可以用它來更好地驗證這些域名。不幸的是,據我所知,目前還沒有這樣的圖書館。

+0

你需要SANITIZE的電子郵件地址,所以你的觀點並不是完全解釋的東西..看看過濾器選項等。 –

0

我看到的一些評論與我的測試不符,所以我想指出我在PHP 5.x中找到的功能。如果你第一次SANITIZE電子郵件它會刪除所有你不想要的字符,那麼你可以驗證。我有兩個功能,以防有人想要做一個或另一個。

檢查電子郵件是有效的:

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]