匹配电子邮件地址

匹配字符串中的电子邮件地址是一项艰巨的任务,因为定义它的规范 RFC2822 很复杂,因此很难将其作为正则表达式实现。有关为什么将电子邮件与正则表达式匹配不是一个好主意,请在不使用正则表达式时参考反模式示例 :匹配电子邮件 。从该页面中注意的最佳建议是使用你喜欢的语言的同行评审和广泛的库来实现这一点。

验证电子邮件地址格式

当你需要快速验证条目以确保它看起来像电子邮件时,最好的选择是保持简单:

^\S{1,}@\S{2,}\.\S{2,}$

该正则表达式将检查邮件地址是否为非空格分隔的长度大于 1 的字符序列,后跟 @,后跟两个由 . 分隔的长度为 2 或更多的非空格字符序列。它并不完美,可能会验证无效地址(根据格式),但最重要的是,它不会使有效地址无效。

检查地址是否存在

检查电子邮件是否有效的唯一可靠方法是检查其是否存在。曾经有过为此目的设计的 VRFY SMTP 命令,但遗憾的是,在被垃圾邮件发送者滥用之后,它现在不再可用了

因此,你唯一能够检查邮件是否有效且存在的方法是实际向该地址发送电子邮件。

巨大的正则表达式替代品

但是,使用正则表达式验证地址电子邮件并非不可能。唯一的问题是,这些正则表达式越接近规范,它们将越大,因此它们难以阅读和维护。下面,你将找到在某些库中使用的更准确的正则表达式的示例。

⚠️ 以下正则表达式用于文档和学习目的,将代码粘贴到代码中是一个坏主意。相反,直接使用该库,因此你可以依赖上游代码和对等开发人员来保持你的电子邮件解析代码的最新和维护。

Perl 地址匹配模块

这种正则表达式的最好例子是某些语言的标准库。例如,Perl 库中的 RFC::RFC822::Address 模块中有一个根据 RFC 尝试尽可能准确。为了你的好奇心,你可以在这个 URL 上找到一个由该语法生成​​的正则表达式的版本,如果你想复制粘贴它,这里引用来自正则表达式的作者:

我没有维护正则表达式[链接]。可能存在已经在 Perl 模块中修复的错误。

.Net 地址匹配模块

另一个较短的变体是 EmailAddressAttribute 模块中 .Net 标准库使用的变体 :

^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\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)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$

但即使它*更短,*它仍然太大而不易读,易于维护。

Ruby 地址匹配模块

在 ruby 中, rfc822 模块中使用正则表达式的组合来匹配地址。这是一个很好的想法,因为在发现错误的情况下,更容易确定正则表达式部分以更改和修复它。

Python 地址匹配模块

作为一个反例,python 电子邮件解析模块不使用正则表达式,而是使用解析器实现它。