0

我们都知道电子邮件地址验证是一个敏感的话题,关于在不编码整个 RFC 的情况下处理它的最佳方法有很多意见。但自 2009 年以来,它变得更加困难,我还没有真正看到有人解决 IDN 的问题。

这是我一直在使用的:

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

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

在此处查看完整列表。(请注意列表底部的所有非拉丁语域扩展。)

可以在此处找到有关此主题的信息,我认为他们所说的是这些新字符将在机器级别上简单地读取为“.xn--fiqz9s”和“.xn--p1ai”,但我不是 100%当然。

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

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

注意:这与此页面上的讨论无关使用正则表达式验证电子邮件地址

4

3 回答 3

4

考虑一下:每次你在没有根据完整的 RFC 规范验证地址的情况下编写自己的新正则表达式时,你只会让在网络上使用“异国情调”电子邮件地址的情况变得更糟。您正在发明官方 RFC 规范的一些新的临时子集或超集;这意味着您将有误报或误报或两者兼有,您将拒绝人们使用他们的实际地址,因为您的正则表达式没有正确解释他们,或者您将接受实际上无效的地址。

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

如果您要验证语法,要么进行非常粗略的常规检查,确保不会拒绝任何有效地址(例如/.+@.+/),要么根据所有 RFC 规则进行验证;不要在你刚刚提出的半途而废的严格但不是真正的验证之间进行一些验证。

于 2016-02-26T10:11:58.713 回答
2

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

当这种情况出现时,我总是这样做。如果有的话,我会让他们两次输入他们的电子邮件。它会让您腾出更多时间在您的网站/项目的重要部分上。

于 2016-02-25T21:57:13.763 回答
-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 这样的普通电子邮件地址和像 as中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');
于 2016-02-26T09:21:06.310 回答