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


preg_match verification of non English email addresses (international domain names)

我们都知道电子邮件地址验证是一个敏感的话题,关于在不对整个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)

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

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

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

如果您要验证语法,请进行非常粗略的一般检查,以确保不会拒绝任何有效的地址(例如 /.+@.+/ ),根据所有 RFC 规则进行验证;不要做一些介于两者之间的半屁股严格但不是真正的验证,你刚刚想出

我将坚持一个久经考验的建议,即您应该向他们发送一封验证电子邮件。不需要需要一次又一次更新的花哨正则表达式。假设他们知道自己的电子邮件地址并让他们输入即可。

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

这是我最终想出的。

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.smid 3_yÄh মহাজোটেরoo文%网+d-fελληνικά@πyÄhooαράδειγμα.δοκιμή.

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

更新

我刚刚发现,尽管在 phpliveregex.com 等网站上进行测试时,在解析 utf-8 内容的普通字符串时,这在当地测试时效果很好,但它无法与电子邮件字段正常工作,因为浏览器将该内容类型的字段转换为普通拉丁语。因此,像bob@china.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');
相关文章: