为什么jQuery的电子邮件validation正则表达式如此简单?

我们都知道正确validation电子邮件的正则表达式会非常复杂 。 但是,jQuery的validation插件有一个较短的正则表达式(由Scott Gonzalez提供 ) ,只有几行:

/^((([az]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]) +(\.([az]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)| ((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21| [\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f] |[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)? (\x22)))@((([az]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([az]|\d| [\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([az]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])* ([az]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([az]| [\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([az]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]) ([az]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([az]| [\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/ 

与众所周知的怪物相比,为什么这么“简单”? 是否存在一个正则表达式失败而另一个正式成功的情况(案例是有效还是无效的电子邮件)?

正则表达式是一个自定义组合:

  • RFC 2234 ABNF
  • RFC 2396 URI通用语法(由RFC 3986引用)
  • RFC 2616超文本传输​​协议 – HTTP / 1.1
  • RFC 2822 Internet邮件格式
  • RFC 3987 IRI
  • RFC 3986 URI通用语法

当我正在起草Web Forms 2.0并且RFC 5322不存在时,我编写了正则表达式。 如果查看RFC的编写顺序,您会注意到写入Internet消息格式后IRI和URI的定义已更改。 这意味着RFC 2822不支持当前的IRI定义。 不幸的是,这不仅仅是替换定义的简单任务,因此我必须从哪个RFC中选择使用哪些定义。 我还选择了要删除的内容(例如支持评论)。

正则表达式不是完全手写的。 当我手动编写正则表达式的每个部分时,我编写了“胶水”脚本。 RFC中的每个定义都存储在一个变量中,复合定义利用存储更简单定义的变量(@Walf:这就是为什么有这么多的子模式和ors)。

为了使问题复杂化,jQuery Validation插件中使用的正则表达式的版本进一步修改,以解决规范有效地址与用户对有效地址的期望之间的差异。 我不记得我做了什么修改。 我向JörnZaefferer(validation插件的作者)承诺,我会编写一个更新的脚本来生成正则表达式。 新脚本允许您指定您要做和不想支持的选项(所需的TLD,特定TLD,IPv6,注释,过时的定义,引用的本地名称等)。 那是5年前的事了。 我开始了一次,但从未完成。 也许有一天我会。 我到目前为止在GitHub上托管: https : //github.com/scottgonzalez/regex-builder

如果你想要一个用于validation电子邮件地址的正则表达式,我建议使用HTML5规范中包含的以下正则表达式:

/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/

如果你使用正则表达式构建器并关闭所有选项,你会得到类似的东西。 但是我看了一年已经有一年了,所以我不记得有什么不同。


我还想指出原始问题中的链接特别提到了RFC 822.虽然RFC 822将我们从Arpanet推进到ARPA Internet非常棒,但这并不是最新的。 互联网在过去三十年取得了一些进展,这个RFC已经被取代了两次。 我希望看到遵循最新标准的任何新工作。


更新:

一位朋友问我为什么HTML5正则表达式不支持UTF-8。 我从未向Hixie询问过这个问题,但我认为这就是原因:尽管一些TLD在2000年开始支持IDN(国际域名),而RFC 3987(IRI)是在2005年编写的,当时RFC 5322是在2008年编写的。它仅将33-90和94-126范围内的字符列为有效dtext(允许在域文字中使用的字符)。 HTML5基于RFC 5322,因此没有UTF-8支持。 RFC 5322并没有考虑到IDN,这似乎很奇怪,但即使在2008年的IDN实际上并不可用,它也是值得的。 直到2010年,ICANN才批准了第一套IDN。 但是,即使在今天如果你想使用IDN,如果你真的希望像电子邮件和DNS这样的东西在全球范围内工作,你几乎需要使用Punycode完全破坏你的域名。

更新2:

更新了HTML5正则表达式以匹配更新的规范,该规范将标签长度限制从255个字符更改为63个字符,如RFC 1034第3.5节中所述 。

这看起来不对:Unicode有什么用? 这个validation哪个RFC?

请参阅此答案以获取正确的RFC5322validation正则表达式。