問題描述

我正在使用 is_email()來檢查 user-provided 電子郵件地址是否有效。例如:

$email = $_POST['email'];
if ( is_email( $email ) )
    // Do something.

據我所知,此功能中的任何內容都不會將資訊寫入資料庫。在將 $email 傳遞給函式之前,是否應該進行消毒?

最佳解決方案

看看在 trac 上的 is_email()功能,看起來你不需要聖誕節,因為它只是字串測試。我甚至會說,如果這個函式返回 true,那麼在將資料傳送到資料庫之前不需要對它進行清理。

次佳解決方案

WordPress 和 PHP 核心

is_email()功能 Source 是一種典型的 WordPress 實現,不能與 RFC 6531 允許的功能完全相同。一個原因可能是,filter_var()的預設 PHP FILTER_VALIDATE_EMAIL 常數在根據 The Internet Engineering Task Force (IETF®)指南驗證某些內容方面沒有太大的好轉。

Standards

要點是 RFC 6531 允許 「Unicode 字元超出 ASCII 範圍」 。那就是 (對於 @之前的本地部分):

  • Uppercase and lowercase English letters (a–z, A–Z) (ASCII: 65–90, 97–122)
  • Digits 0 to 9 (ASCII: 48–57)
  • These special characters: ! # $ % & ' * + - / = ? ^ _ ` { | } ~
  • Character . (dot, period, full stop) (ASCII: 46) provided that it is not the first or last character, and provided also that it does not appear consecutively (e.g. John..Doe@example.com is not allowed).
  • Special characters are allowed with restrictions. They are:
    • Space and "(),:;<>@[] (ASCII: 32, 34, 40, 41, 44, 58, 59, 60, 62, 64, 91–93)
    • The restrictions for special characters are that they must only be used when contained between quotation marks, and that 2 of them (the backslash and quotation mark ” (ASCII: 92, 34)) must also be preceded by a backslash (e.g. "\" and """).
  • Comments are allowed with parentheses at either end of the local part; e.g. john.smith(comment)@example.com and (comment)john.smith@example.com are both equivalent to "john.smith@example.com", but john.(comment)smith@example.com would be invalid.
  • International characters above U+007F, encoded as UTF-8, are permitted by RFC 6531, though mail systems may restrict which characters to use when assigning local parts.

對於全域性/域名部分:

The domain name part of an email address has to conform to strict guidelines: it must match the requirements for a hostname, consisting of letters, digits, hyphens and dots. In addition, the domain part may be an IP address literal, surrounded by square braces, such as jsmith@[192.168.2.1] or jsmith@[IPv6:2001:db8::1] […]

Source: Wikipedia

什麼是有效的?

這可能導致奇怪的,但有效的 e-mail 地址,如下所示:

  • localpart.ending.with.dot.@example.com
  • (comment)localpart@example.com
  • "this is v@lid!"@example.com
  • "much.more unusual"@example.com
  • postbox@com
  • admin@mailserver1
  • "()<>[]:,;\@"\\!#$%&'*+-/=?^_`{}| ~.a"@example.org
  • " "@example.org

Source: php.net /作者 gt@kani.hu – 這個帖子的作者固定的例子

Limits

還有當地& 域長限制:

The format of email addresses is local-part@domain where the local-part may be up to 64 characters long and the domain name may have a maximum of 253 characters – but the maximum of 256-character length of a forward or reverse path restricts the entire email address to be no more than 254 characters long.[2] The formal definitions are in RFC 5322 (sections 3.2.3 and 3.4.1) and RFC 5321 – with a more readable form given in the informational RFC 3696[3] and the associated errata.

資料來源:維基百科

WordPress 限制

這是 WordPress 檢查的:

  • 測試電子郵件的最小長度:strlen( $email ) < 3

  • 測試一個 @字元後的第一個位置:strpos( $email, '@', 1 ) === false

  • 測試無效字元:!preg_match( '/^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~.-]+$/', $local )

  • 測試期間序列:preg_match( '/.{2,}/', $domain )

  • 測試領​​先和尾隨時段和空白:trim( $domain, " tnrx0B." ) !== $domain

  • 假設域將至少有兩個 subs:$subs = explode( '.', $domain ); 然後

    • 2 > count( $subs )

    • trim( $sub, " tnrx0B-" ) !== $sub

    • !preg_match('/^[a-z0-9-]+$/i', $sub )

資料來源:WP Core v4.0

過濾器自定義驗證

所有上述情況都會觸發 is_email()返回 false 。結果是 filter-able(可以附加回撥),過濾器將有三個引數,其中最後一個引數是原因。例:

return apply_filters( 'is_email', false, $email, 'sub_hyphen_limits' );

這意味著您可以覆蓋特定檢查返回的結果。

這允許您新增特殊檢查,例如允許 Umlaut-domains,TLD-only 域名等。

Conclusion

WordPress 在大多數情況下是安全的,但是由於郵件伺服器實際上必須符合 RFC 要求,因此更為嚴格。請記住,並不是每個郵件伺服器都符合 RF 6531 指南。

Edit

有趣的一面:~/wp-includes/formatting 內有兩個相關的功能:is_email()sanitize_email()。它們幾乎是相同的功能。我不知道為什麼有人決定將功能內容從一個複製到另一個是一個好主意,而不是將一個作為回撥新增到另一個提供的過濾器。自從 v0.71 起 is_email()和 v1.5 之後的 sanitize_email()是一樣的,我個人會使用後來的,因為你得到一個清理的字串。請注意,is_email()甚至宣告它不符合 RFC 。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。