preg_match验证非英文电子邮件地址(国际域名)

时间:2016-02-25 21:07:13

标签: php regex email idn

我们都知道电子邮件地址验证是一个棘手的主题,关于处理它的最佳方法有很多意见,而不需要对整个RFC进行编码。但自2009年以来,它变得更加困难,我还没有真正看到任何人解决IDN的问题。

以下是我一直在使用的内容:

preg_match(/^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,6}\z/i)

哪个适用于大多数电子邮件地址,但如果我需要匹配非拉丁语电子邮件地址呢?例如:bob @ china。中国,或bob@russia.рф

查看here以获取完整列表。 (注意列表底部的所有非拉丁语域扩展。)

有关此主题的信息可以找到here,我认为他们所说的是这些新角色在机器级别上只会被读作'.xn - fiqz9s'和'.xn - p1ai'但我不是百分百肯定。

如果是,那是否意味着我需要考虑在我的代码中进行以下唯一的更改? (对于域名扩展名,如.travelersinsurance和.sandvikcoromant)

preg_match(/^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,20}\z/i)

注意:这与此页Using a regular expression to validate an email address

上的讨论无关

3 个答案:

答案 0 :(得分:3)

考虑一下:每次根据完整的RFC规范构建自己的新正则表达式而不验证地址时,您只是在使用"异国情调"网络上的电子邮件地址更糟糕。您正在发明一些官方RFC规范的新ad-hoc子或超集;这意味着你会有误报或漏报或两者兼而有之,你会拒绝人们使用他们的实际地址,因为你的正则表达式没有正确地解释它们,或者你会接受实际上无效的地址。

除此之外,即使地址在语法上有效,仍然并不意味着a)实际(仍然)存在地址,b)属于该用户或c)实际上可以接收电子邮件。在授权方案中,验证语法是一个非常小的问题。

如果你要完全验证语法,要么进行非常粗略的一般性检查,确保不拒绝任何有效地址(例如/.+@.+/),< em>或根据所有RFC规则进行验证;不要在你刚刚提出的中间做一些严格但非真实的验证。

答案 1 :(得分:2)

我会坚持使用经过验证的真实建议,即您应该向他们发送验证邮件。无需花哨的正则表达式,需要一次又一次地更新。假设他们知道他们的电子邮件地址并让他们输入。

这就是我在这种情况出现时总是做的事情。如果有什么我会让他们两次输入他们的电子邮件。它可以让您将更多时间花在网站/项目的重要部分上。

答案 2 :(得分:-1)

这是我最终想出来的。

preg_match(/^[\pL\pM*+\pN._%+-]+@[\pL\pM*+\pN.-]+\.[\pL\pM*+]{2,20}\z/u)

这使用Unicode正则表达式,如 \ pL \ pM * + \ pN 来帮助我处理任何字符和数字语言。

\ pL 任何语言,大写或小写的任何类型的信件。

\ pM * + 匹配组合标记的零个或多个代码点。用于与另一个角色(例如重音符号,变音符号,封闭框等)组合的角色。

\ pN 任意数字。

上述表达式适用于普通电子邮件地址,如me@mydomain.com和嘈杂的电子邮件地址,如a.s中3_yÄhমহাজোটেরoo文%网+d-fελληνικά@πyÄhooαράδειγμα.δοκιμή。

并不是说我不相信人们能够输入他们自己的电子邮件地址,但人们确实会犯错误,我可能会在其他情况下使用此代码。例如:我需要仔细检查现有10,000个电子邮件地址列表的完整性。此外,我总是被教导不信任用户输入和总是过滤。

<强>更新

我刚刚发现尽管在phpliveregex.com等网站上进行测试时这种方法非常有效,但在解析utf-8内容的普通字符串时,它无法正常使用电子邮件字段,因为浏览器会转换该内容类型的字段正常的拉丁语。因此,bob @ china。中国或bob@russia.рф等电子邮件地址在被服务器收到之前会转换为bob@china.xn--fiqz9s或bob@russia.xn--p1ai。我原来过滤器中唯一缺少的是从域扩展中包含连字符。

以下是最终版本:

preg_match('/^[a-z0-9%+-._]+@[a-z0-9-.]+\.[a-z0-9-]{2,20}\z/i');