电子邮件验证的正则表达式

14

我写了下面的正则表达式来进行简单的电子邮件验证。我打算发送一个确认链接。

/.*@[a-z0-9.-]*/i

然而,我希望从当前状态开始改进它,因为像这样的字符串不会产生预期的结果:

test ,my.name+test@gmail-something.co.uk, test

"test ,"部分被不希望地包含在匹配项中。我尝试过使用单词边界,但没有成功。

  1. 我应该如何修改?
  2. 即使我保持了简单,它是否会排除任何有效的电子邮件格式?

谢谢!


这个问题已经出现很多次了...您有没有看到输入标题后显示的问题? - Tomalak
https://dev59.com/uHVC5IYBdhLWcg3wtzut#201378 - Brad Mace
7个回答

20

这个东西远比你想象的复杂得多!!! 看看Mail::RFC822::Address,你会很害怕......非常害怕。


第一次看到这个正则表达式时,我非常害怕,我向朋友展示了它,他起初不相信这是THE EMAIL REGEX,然后也感到恐惧。好的回忆。 - Random Developer
Mail::RFC822::Address接受的内容远不止常见的电子邮件地址。请参阅底部的注释,其中写道:“此正则表达式仅验证已剥离任何注释并替换为空格的地址”。因此它接受空格。 - dolmen
好的,我已经做好了惊恐的准备。但是这已经超越了洛夫克拉夫特式... - Arani

17

不要使用正则表达式验证电子邮件地址

取而代之的是,参考Ben Finney在mail.python.org/pipermail/python-list1中的建议。

当人们问“如何验证电子邮件地址是否有效?”时,我看到的最好建议是,“尝试向其发送邮件”。

这既符合Python的编程风格,也是最佳方法。如果您想要确认,不要试图静态验证它; 使用该电子邮件地址,并检查结果。向该地址发送电子邮件,除非收件人回复“是的,这是要使用的正确地址”,否则不要再使用它。

发送系统的邮件传输代理(MTA),而不是正则表达式,确定将邮件发送到哪个域。

域名系统(DNS),而不是正则表达式,确定哪些域是有效的,以及应该为该域接收邮件的主机。

尤其要注意,接收邮件系统,而不是正则表达式,确定哪些本地部分是有效的。

1这是链接失效前的原始链接


3
你被解雇了。人们有奇怪的电子邮件地址可以去吐口水。 - alxp
1
有时候我会告诉那些使用愚蠢正则表达式检查的网站去滚,再也不用它们了。我需要我的 Gmail + 语法! - Chase Seibert
15
这个链接现在似乎失效了。 - Aron Rotteveel
2
当我们说验证电子邮件地址时,我们谈论的是两件事。1. 验证它是一个真实的电子邮件地址(您可以通过向该地址发送确认链接来验证)。2. 大多数人谈论的是验证。也就是使用正则表达式来帮助用户输入地址。x@x.x就足够了。我们不在这里验证imanidiot@yourmomshouse.lol是否是真实的电子邮件地址。反对使用正则表达式验证电子邮件的人要么没有完全理解问题,要么只是彻底的恶意评论者。 - The Muffin Man
只要你有一个双向系统,这个方法就有效。然而,如果你有一个只能发送电子邮件而无法接收回复的系统配置应用程序,那么你需要尽可能静态地验证它。 - undefined
显示剩余3条评论

12

几乎没有你使用的东西可以简短地验证电子邮件地址。然而,这是我通常使用的方法:

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

这实际上是 ASP.NET 的正则表达式验证器内置的用于电子邮件地址的正则表达式。

注意:本主题中提供的许多正则表达式可能在 90 年代有效,但是在当今的网络环境中,顶级域名(TLD)可以少于 2 个字符或多于 4 个字符。例如,info@about.museum 是一个有效的电子邮件地址,因为 .museum 是其中一个新的、长的 TLD。


'' 匹配 \w。但是在域名中不允许使用 ''. 现在我们也有国际化域名(例如阿拉伯语)。 - dolmen
这不检查空格,因此“joe blogs@email.com”被视为有效电子邮件。 - Weggo
1
@Weggo,这个不允许有空格。如果你允许了的话,在开头可能缺少了脱字符 (^)。 - Rick
1
@Rick - 你说得对,我没有(^)。我已经给你的答案点赞了。 - Weggo

4

我发现,与其使用正则表达式对整个电子邮件地址进行匹配,不如将字符串在@处分割,并:

  • 首先通过DNS库检查域部分的现有MX或A记录。
  • 然后针对较简单的正则表达式检查本地部分(@左侧的部分)。

进行DNS检查的原因是,即使符合RFC标准的电子邮件地址无法访问,也毫无价值。另外检查A记录的原因是,当没有找到MX记录时,它们用于确定要向何处发送邮件。(参见RFC2821,3.6)

进一步提示:

  • 使用健壮的DNS解析器库,不要自行开发。对其进行大型公司测试。这些公司有时拥有大量的邮件服务器,这可能会导致问题。我曾看到一个有Bug的库在bmw.com上出了问题。只是说一下。 :)

1

不要使用 . ,而是匹配除了 \s(空格)以外的每个字符:

/[^\s]*@[a-z0-9.-]*/i

为了匹配除空格外的所有内容,我们不应该使用(大写字母S)\S来进行匹配吗?除非它在所有正则表达式引擎中都无法使用。 - Fábio Santos
方括号前面的 ^ 表示不在列表中的字符。因此,它会反转 \s 的含义。我想你可以使用 /\S*@[a-z0-9.-]*/i 来代替。 - Martin Brown

-1

这来自于 Regex Buddy(绝对需要购买的程序!)

\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,6}\b

它与.museum顶级域不匹配。 - dolmen

-1

一个较小的两步正则表达式可以提供良好的结果

/** 检查电子邮件地址是否符合有效格式。 * 邮箱的首字母必须是字母
* 其余字符必须为字母数字、- _ 和点
* 域名基本上必须至少包含2个字符
* 域名扩展名必须至少为2个字母,不超过4个字母
* 子域名是允许的。 * @version 050208 添加撇号作为有效字符 * @version 04/25/07 允许单字母电子邮件地址和单字母域名。 */ public static boolean isValidEmailAddress(String address){ String sRegExp;

    // 050208 using the literal that was actually in place
    // 050719 tweaked 
    // 050907 tweaked, for spaces next to @ sign, two letter email left of @ ok
    // 042507 changed to allow single letter email addresses and single letter domain names
    // 080612 added trap and unit test for two adjacent @signs
    sRegExp =   "[a-z0-9#$%&]"          // don't lead with dot
        +   "[a-z0-9#$%&'\\.\\-_]*"     // more stuff dots OK
        +   "@[^\\.\\s@]"               // no dots or space or another @ sign next to @ sign
        +   "[a-z0-9_\\.\\-_]*"         // may or may  not have more character
        +   "\\.[a-z]{2,4}";            // ending with top level domain: com,. biz, .de, etc.

    boolean bTestOne =  java.util.regex.Pattern.compile( sRegExp,
            java.util.regex.Pattern.CASE_INSENSITIVE).matcher(address).matches();

    // should this work ?
    boolean bTwoDots =  java.util.regex.Pattern.compile("\\.\\.",  // no adjacent dots
                    java.util.regex.Pattern.CASE_INSENSITIVE).matcher(address).find();

    boolean bDotBefore = java.util.regex.Pattern.compile("[\\.\\s]@", //no dots or spaces before @
                         java.util.regex.Pattern.CASE_INSENSITIVE).matcher(address).find();

    return bTestOne && !bTwoDots && !bDotBefore;
}   // end IsValidEmail

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接