Email正则表达式问题

有段email的正则表达写法是这样的:

^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$

测试指出,这段正则的逻辑里,允许了域名的部分包含下划线,这是不合法的,比如这个非法的email用上面的可以通过:

scala> val pattern = """^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"""

scala> "a@b_.cn" matches pattern
res45: Boolean = true

于是开发后来修改成了这样的表达式:

[a-zA-Z0-9._+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}

这个限制了域名部分只能是字母、数字、点和横杠,甚至最后边的顶级域名是2到4位字符,看上去靠谱,但测试又测出了这种情况:

scala> val pattern = """[a-zA-Z0-9._+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}"""

scala> "a@..info" matches pattern
res46: Boolean = true

开发开始google,然后发现这个问题并没有那么简单。首先如果按照rfc规范来说,Email地址从语义上可以支持的格式非常广泛,可以说是五花八门,参考这里:http://en.wikipedia.org/wiki/Email_address

对于域名中是否允许包含下划线的问题,在rfc1034和2181规范里没有禁止使用下划线的,参考这里:http://stackoverflow.com/questions/2180465/can-someone-have-a-subdomain-with-an-underscore-in-it,他举例这两个都是:

_jabber._tcp.gmail.com 
_sip._udp.apnic.net

但貌似为了避免混乱,又不建议DNS里使用下划线: http://www.quora.com/Domain-Name-System-(DNS)/Why-are-underscores-not-allowed-in-DNS-host-names

Email的RFC经历过好几次修订,从最初的rfc822到后来的rfc2822再到rfc5322,是在不断补充增强的。

要支持完整的合理语义Email,并不是一个简单的正则能表达的,从这里http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address 的讨论看来,能够完整的支持Email地址的那个正则复杂度已经大大超出了预期,所以只能选择一个对业务来说适合绝大部分情况的,最终从这篇帖子里选择了下面的表达式:

^[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])?)*$

发表评论

电子邮件地址不会被公开。 必填项已用*标注