問題描述
我正在使用 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
0to9(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.comis 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.comand(comment)john.smith@example.comare both equivalent to"john.smith@example.com", butjohn.(comment)smith@example.comwould 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]orjsmith@[IPv6:2001:db8::1][…]
什麼是有效的?
這可能導致奇怪的,但有效的 e-mail 地址,如下所示:
localpart.ending.with.dot.@example.com(comment)localpart@example.com"this is v@lid!"@example.com"much.more unusual"@example.compostbox@comadmin@mailserver1"()<>[]:,;\@"\\!#$%&'*+-/=?^_`{}| ~.a"@example.org" "@example.org
Source: php.net /作者 gt@kani.hu – 這個帖子的作者固定的例子
Limits
還有當地& 域長限制:
The format of email addresses is
local-part@domainwhere 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 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。