如何验证真实,实用,普遍接受的电子邮件地址(但包括unicode)?

时间:2014-01-19 01:47:00

标签: php regex email unicode

如何验证真实,实用,普遍接受的电子邮件地址(但包括unicode)?

验证电子邮件地址的主题在SO上已经出现了很多,并且由于理论上允许电子邮件地址包含许多“特殊”字符,因此经常会分心。有人说许多电子邮件验证器过于严格,但事实上,如果GMail,facebook,Yahoo等非常严格,那意味着99.999%的电子邮件将符合那些比RFC允许更严格的标准,所以那是真实的世界。

我已经完成了一项免费电子邮件服务调查(14-01-19),这里有一些最常见的电子邮件名称限制:

GMail:不允许:! “#$%&()* +,/:;< =>?@ [\ _] ^`{|}〜

Yahoo.com:只允许使用字母,数字,下划线(_)和一个点(。):

Zoho.com:只允许使用字母,数字,下划线(_)和点(。):

facebook.com:只允许使用字母,数字,下划线(_),点(。)和连字符( - ):

hushmail.com:只允许使用字母,数字,下划线(_),点(。)和连字符( - ):

AIM(美国在线):不允许使用的字符:@,!,*或$(许多其他字符,但未指定)

Hotmail / Outlook.com:字母,数字,_-。好;没有重音或非拉丁字母

iCloud.com:典型的Apple,你必须下载一堆废话(67.5 MBytes)并让它                 甚至可以在创建帐户之前入侵您的系统。我没打扰。

最重要的是,绝大多数电子邮件服务只允许使用字母,数字,下划线(_),点(。)和连字符( - )。此外,我在许多网站上阅读有关此内容的消息,很多人在他们的电子邮件地址中使用了“+”。

所以,我想要一个很好的简单过滤器来筛选出因整体结构而无效的任何电子邮件,或者因为它们使用除了绝大多数人使用和/或大多数电子邮件服务所接受的简单字符以外的任何其他内容:AZ az 0-9 _。+ -

不幸的是,PHP的filter_var函数与FILTER_VALIDATE_EMAIL / FILTER_SANITIZE_EMAIL允许这些字符通过:!#$%&'* / =?^`{|}〜@ []所以我认为它几乎没用 - 特别是因为它允许引号(')符号。只有最讨厌的书呆子会在他们的电子邮件地址中使用这些符号,如果他们这样做,他们将被绝大多数网站拒绝,所以无论如何他们必须有一个更正常的备份电子邮件地址。

一个复杂因素:我住在越南,必须允许在地址中使用unicode字符。我怎么能这样做?

2 个答案:

答案 0 :(得分:4)

验证电子邮件地址的唯一正确方法是发送一封带有确认链接的电子邮件。

如果您有这种倾向,请检查一般(string)@(string).(string)模式以捕捉用户错误和明显的虚假条目,例如lalalalala

filter_var function(您已经提到过)就是这样做的。

除此之外的任何事情都是浪费时间。

答案 1 :(得分:0)

电子邮件有多种无效方式。它不只是在使用角色。验证某些格式的字符串不适合正则表达式。例如,电子邮件地址中的双点(..)无效,您应该将其放在reqex中。

您可以查看Zend_Validate_EmailAddress。如果您检查源代码,您将得到问题的复杂性。

// Split email address up and disallow '..'
if ((strpos($value, '..') !== false) or
    (!preg_match('/^(.+)@([^@]+)$/', $value, $matches))) {

    ...
}

$this->_localPart = $matches[1];
$this->_hostname  = $matches[2];

...

    $hostname = $this->_validateHostnamePart();
...
$local = $this->_validateLocalPart();

在_validateLocalPart中他们这样做:

// atext: ALPHA / DIGIT / and "!", "#", "$", "%", "&", "'", "*",
//        "+", "-", "/", "=", "?", "^", "_", "`", "{", "|", "}", "~"
$atext = 'a-zA-Z0-9\x21\x23\x24\x25\x26\x27\x2a\x2b\x2d\x2f\x3d\x3f\x5e\x5f\x60\x7b\x7c\x7d\x7e';
if (preg_match('/^[' . $atext . ']+(\x2e+[' . $atext . ']+)*$/', $this->_localPart)) {
    ...
}