Php 非英语电子邮件地址(国际域名)的预匹配验证

Php 非英语电子邮件地址(国际域名)的预匹配验证,php,regex,email,idn,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.ф 查找完整的列表。(请注意列表底部的所

我们都知道电子邮件地址验证是一个敏感的话题,对于如何在不对整个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(/^[\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মহাজোটের面向对象文%网+d-fελλληνικά@πyÄhooαράΔειγμα。Δοκμή

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

更新

我刚刚发现,虽然在诸如和本地解析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');

这是我最终想到的

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মহাজোটের面向对象文%网+d-fελλληνικά@πyÄhooαράΔειγμα。Δοκμή

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

更新

我刚刚发现,虽然在诸如和本地解析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');

请考虑:每次您在没有根据完整的RFC规范验证地址的情况下编写自己的新regex,您只会使在web上使用“外来”电子邮件地址的情况变得更糟。你正在发明一些新的官方RFC规范的特别子集或超集;这意味着你要么有误报,要么有误报,要么两者都有,你会拒绝人们使用他们的实际地址,因为你的正则表达式没有正确地解释他们,或者你会接受不正确的地址