正则表达式电子邮件验证

269

我使用这个。

@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$"

正则表达式用于验证电子邮件

([\w\.\-]+) - 这是一级域名(包括多个字母和数字、点号和连字符)

([\w\-]+) - 这是二级域名

((\.(\w){2,3})+) - 这是其他等级的域名(从3到无限)包括一个点和2或3个字符

这个正则表达式有什么问题吗?

编辑:它无法匹配"something@someth.ing"类型的电子邮件地址。


1
除了您未包含RFC [5321]和[5322]指定的有效字符之外,没有其他问题。 - Brad Christie
14
你有一个问题 -> 你想到了“正则表达式” -> 现在你有两个问题 ;-) - Jakub Konecki
foo+bar@example.com是什么意思? - Valerij
2
只是关于你的正则表达式的一个评论。随着这些新的.amsterdam,.info和其他域名,正则表达式应该是:@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,})+)$"" - Ton Snoei
显示剩余2条评论
37个回答

485

.museum这样的顶级域名不是按照这种方式匹配的,还有一些其他较长的顶级域名。此外,您可以使用MailAddress类来验证电子邮件地址,正如Microsoft在此处的说明中所述:

您可以使用System.Net.Mail.MailAddress类而不是使用正则表达式来验证电子邮件地址。要确定电子邮件地址是否有效,请将电子邮件地址传递给MailAddress.MailAddress(String)类构造函数。

public bool IsValid(string emailaddress)
{
    try
    {
        MailAddress m = new MailAddress(emailaddress);

        return true;
    }
    catch (FormatException)
    {
        return false;
    }
}

这可以让你省去很多麻烦,因为你不需要编写(或试图理解别人的)正则表达式。
编辑:对于那些对try/catch过敏的人:在.NET 5中,你可以使用MailAddress.TryCreate。另请参见https://dev59.com/0m435IYBdhLWcg3wkA5e#68198658,其中包括修复..、空格、缺少.TLD等内容的示例。

84
这个没有捕捉双点 ".." 或者内联空格 ". "。我会用正则表达式来处理。 - Benny Skogberg
45
尽管这个答案很流行,但它是错误的,无法捕获至少两种无效格式:"Abc.@example.com","Abc..123@example.com"。 - sean717
13
@sean717: 请查看RFC和/或链接。我同意你的例子可能在现实世界中行不通,但这并不意味着它们无效。 - Dan Pichelman
13
使用try catch来验证输入是否有效,无论是否成功都不是推荐的做法。正则表达式绝对是更好的选择。 - mrt
181
糟糕的代码。捕获异常并不是验证字段的正确方式。 - ken2k
显示剩余7条评论

121

我认为@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$"应该可以工作。
你需要写成:

string email = txtemail.Text;
Regex regex = new Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");
Match match = regex.Match(email);
if (match.Success)
    Response.Write(email + " is correct");
else
    Response.Write(email + " is incorrect");

请注意,如果出现以下情况,则此方法将失败:

  1. @符号后面有子域名。

  2. 您使用长度大于3的顶级域名,例如.info


3
test@-online.com返回为有效地址。实际上应该是无效的。 - Mathias F
8
我相信这将在新发行的顶级域名中失败,因为现在可以拥有超过3个字符的顶级域名。 - AaronLS
16
gmail.com.in.in.in.in是一个完全有效的域名,所以我不明白为什么它不应该被允许? - larsw
它验证了电子邮件地址是否以点号开头,例如'.email@domain.com'。 - Avinash
1
要允许更长的顶级域名只需移除“3”即可: new Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,})+)$");。如果您仅需要基本验证,则我认为这是一个不错的解决方案。如果您需要RFC验证,则不应使用它。 - fsinisi90
显示剩余6条评论

91

我有一个用于检查电子邮件地址的表达式。

由于上述任何一种都不如我的短小精悍和准确,所以我想在这里发布它。

@"^[\w!#$%&'*+\-/=?\^_`{|}~]+(\.[\w!#$%&'*+\-/=?\^_`{|}~]+)*"
+ "@"
+ @"((([\-\w]+\.)+[a-zA-Z]{2,4})|(([0-9]{1,3}\.){3}[0-9]{1,3}))$";

了解更多信息,请阅读此处:C# - 电子邮件正则表达式

此外,它基于电子邮件语法检查RFC的有效性,而不是电子邮件是否真实存在。测试电子邮件是否真实存在的唯一方法是发送电子邮件,并要求用户通过单击链接或输入令牌来验证他们收到了电子邮件。

然后还有一些一次性域名,例如Mailinator.com等。这并不能验证电子邮件是否来自一次性域名。


7
我已经更新了我的正则表达式项目,加入了单元测试,并修复了一些bug:C# - 电子邮件正则表达式 http://www.rhyous.com/2010/06/15/csharp-email-regular-expression - Rhyous
有了新的顶级域名(TLDs),我们或许应该在第三行中用 {0} 替换 [a-zA-Z]{2,4},然后使用 string.format(pattern, pipeSeparatedAllowedTlds) 进行格式化字符串处理。pipeSeparatedAllowedTlds 需要通过遍历此文件进行创建:http://data.iana.org/TLD/tlds-alpha-by-domain.txt - Rhyous
12
Parth,你能告诉我你的电子邮件违反了RFC规则中的哪一条吗?因为你猜怎么着,根据RFC,它是有效的!!!如果你购买了in.in的URL,你就可以创建这个电子邮件地址。明白了吗? - Rhyous
2
实际上,看起来我已经在我的Github上更新了这个:https://github.com/rhyous/EmailRegEx。然而,\w可能包括下划线,所以我可能需要编辑它以提高准确性。 - Rhyous
1
首先,检查电子邮件是否符合RFC标准与检查它是否是一个“真实”的电子邮件地址是不同的。
  • 如果JSON中的电子邮件未通过RFC标准,请不要尝试向其发送电子邮件,因为它肯定不是真实的。您能否使用无效的电子邮件响应拒绝JSON?
  • 如果它通过了RFC标准,则可能是一个“真实”的电子邮件。您被迫接受JSON,然后尝试将邮件发送到它。 但要小心。大量发送错误的电子邮件可能会影响您的邮件发送程序。它可能会使您的IP地址被列入黑名单,或者如果使用像MailChimp这样的邮件工具,则限制您的帐户。
- Rhyous
显示剩余9条评论

49

我在MSDN上找到了一份很好的文件。

如何:验证字符串是否为有效的电子邮件格式 http://msdn.microsoft.com/zh-cn/library/01escwtf.aspx (请注意,此代码还支持在互联网域名中使用非ASCII字符。)

有两个实现版本,分别适用于 .Net 2.0/3.0 和 .Net 3.5 及更高版本。
2.0/3.0 版本如下:

bool IsValidEmail(string strIn)
{
    // Return true if strIn is in valid e-mail format.
    return Regex.IsMatch(strIn, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"); 
}

我的测试结果是:

Invalid: @majjf.com
Invalid: A@b@c@example.com
Invalid: Abc.example.com
Valid: j..s@proseware.com
Valid: j.@server1.proseware.com
Invalid: js*@proseware.com
Invalid: js@proseware..com
Valid: ma...ma@jjf.co
Valid: ma.@jjf.com
Invalid: ma@@jjf.com
Invalid: ma@jjf.
Invalid: ma@jjf..com
Invalid: ma@jjf.c
Invalid: ma_@jjf
Invalid: ma_@jjf.
Valid: ma_@jjf.com
Invalid: -------
Valid: 12@hostname.com
Valid: d.j@server1.proseware.com
Valid: david.jones@proseware.com
Valid: j.s@server1.proseware.com
Invalid: j@proseware.com9
Valid: j_9@[129.126.118.1]
Valid: jones@ms1.proseware.com
Invalid: js#internal@proseware.com
Invalid: js@proseware.com9
Invalid: js@proseware.com9
Valid: m.a@hostname.co
Valid: m_a1a@hostname.com
Valid: ma.h.saraf.onemore@hostname.com.edu
Valid: ma@hostname.com
Invalid: ma@hostname.comcom
Invalid: MA@hostname.coMCom
Valid: ma12@hostname.com
Valid: ma-a.aa@hostname.com.edu
Valid: ma-a@hostname.com
Valid: ma-a@hostname.com.edu
Valid: ma-a@1hostname.com
Valid: ma.a@1hostname.com
Valid: ma@1hostname.com

1
不匹配 [me]@whatever.museum - Toto
无效:Abc.example.com。是的,那个可以正常工作,但是这个“toms.email.@gmail.com”不行。 - Tom Stickel
2
不得不添加加号: @"^([\w-.+]+)@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.)|(([\w-]+.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(]?)$"11个字符留在] Google和hotmail别名允许在@符号之前的第一部分中使用加号。 - Henk J Meulekamp
这与上面相同,允许“somename@gmail.com.in.in.in”作为有效的电子邮件地址...!! - prem30488
13
为什么你坚持认为somename@gmail.com.in.in.in不是一个有效的电子邮件地址? - Ivaylo Slavov
它没有验证arvtest26Aug2021+2@gmail.com。Tarek El-Mallah提出的一个答案更好。 - Arvind Krmar

21
下面的代码基于Microsoft在GitHub上的数据注释实现,我认为这是最完整的电子邮件验证:
public static Regex EmailValidation()
{
    const string pattern = @"^((([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])))\.?$";
    const RegexOptions options = RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture;

    // Set explicit regex match timeout, sufficient enough for email parsing
    // Unless the global REGEX_DEFAULT_MATCH_TIMEOUT is already set
    TimeSpan matchTimeout = TimeSpan.FromSeconds(2);

    try
    {
        if (AppDomain.CurrentDomain.GetData("REGEX_DEFAULT_MATCH_TIMEOUT") == null)
        {
            return new Regex(pattern, options, matchTimeout);
        }
    }
    catch
    {
        // Fallback on error
    }

    // Legacy fallback (without explicit match timeout)
    return new Regex(pattern, options);
}

1
这应该是最好的正则表达式,因为它似乎验证了RFC 5321和5322。它缺少一些单元测试。 - ToXinE
1
不会捕获电子邮件地址末尾的句点。 - Sellorio
解决方案优雅地适应,并且正则表达式涵盖了广泛的有效/无效评估范围,但它并不涵盖此处提供的所有电子邮件地址验证单元测试: https://codefool.tumblr.com/post/15288874550/list-of-valid-and-invalid-email-addresses - cusman
请注意,如果你天真地直接使用这个答案,每次都会创建一个新的正则表达式 - 你必须将它存储在另一个静态变量中(就像引用的 MS 数据注释代码所做的那样),否则会遭受巨大的性能损失。例如 private static Regex _emailRegex = EmailValidation(); - notracs

16

这不符合RFC 5321和5322的所有要求,但它可以与以下定义一起使用。

@"^([0-9a-zA-Z]([\+\-_\.][0-9a-zA-Z]+)*)+"@(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]*\.)+[a-zA-Z0-9]{2,17})$";

以下是代码

const String pattern =
   @"^([0-9a-zA-Z]" + //Start with a digit or alphabetical
   @"([\+\-_\.][0-9a-zA-Z]+)*" + // No continuous or ending +-_. chars in email
   @")+" +
   @"@(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]*\.)+[a-zA-Z0-9]{2,17})$";

var validEmails = new[] {
        "ma@hostname.com",
        "ma@hostname.comcom",
        "MA@hostname.coMCom",
        "m.a@hostname.co",
        "m_a1a@hostname.com",
        "ma-a@hostname.com",
        "ma-a@hostname.com.edu",
        "ma-a.aa@hostname.com.edu",
        "ma.h.saraf.onemore@hostname.com.edu",
        "ma12@hostname.com",
        "12@hostname.com",
};
var invalidEmails = new[] {
        "Abc.example.com",     // No `@`
        "A@b@c@example.com",   // multiple `@`
        "ma...ma@jjf.co",      // continuous multiple dots in name
        "ma@jjf.c",            // only 1 char in extension
        "ma@jjf..com",         // continuous multiple dots in domain
        "ma@@jjf.com",         // continuous multiple `@`
        "@majjf.com",          // nothing before `@`
        "ma.@jjf.com",         // nothing after `.`
        "ma_@jjf.com",         // nothing after `_`
        "ma_@jjf",             // no domain extension 
        "ma_@jjf.",            // nothing after `_` and .
        "ma@jjf.",             // nothing after `.`
    };

foreach (var str in validEmails)
{
    Console.WriteLine("{0} - {1} ", str, Regex.IsMatch(str, pattern));
}
foreach (var str in invalidEmails)
{
    Console.WriteLine("{0} - {1} ", str, Regex.IsMatch(str, pattern));
}

1
这个表达式不匹配有效的地址 !#$%&'*+-/=?^_.{|}~@example.com或者这个Dörte@Sörensen.example.com`。 - T.S.
这个有效!!复制和粘贴正则表达式后删除空格。 @"^(0-9a-zA-Z)+@(([0-9a-zA-Z][-\w][0-9a-zA-Z]*.)+[a-zA-Z]{2,})$" - Pavitha

14
作为对Alex受欢迎答案的更新:在.NET 5中,MailAddress现在具有TryCreate。因此,您可以执行以下操作:
public static bool IsValidEmail(string email)
{
    if (!MailAddress.TryCreate(email, out var mailAddress))
        return false;

    // And if you want to be more strict:
    var hostParts = mailAddress.Host.Split('.');
    if (hostParts.Length == 1)
        return false; // No dot.
    if (hostParts.Any(p => p == string.Empty))
        return false; // Double dot.
    if (hostParts[^1].Length < 2)
        return false; // TLD only one letter.

    if (mailAddress.User.Contains(' '))
        return false;
    if (mailAddress.User.Split('.').Any(p => p == string.Empty))
        return false; // Double dot or dot at end of user part.

    return true;
}

12

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

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

并且它的用法是:

bool isEmail = Regex.IsMatch(emailString, @"\A(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)\Z", RegexOptions.IgnoreCase);

9

为什么不使用基于EF6属性的电子邮件验证?

如上所述,电子邮件的正则表达式验证总是存在漏洞。如果您正在使用EF6数据注释,可以通过可用的EmailAddress数据注释属性轻松实现可靠且更强大的电子邮件验证。当我在电子邮件输入字段上遇到移动设备特定的正则表达式失败时,我不得不删除以前用于电子邮件的正则表达式验证。当使用电子邮件验证的数据注释属性时,移动设备上的问题得到了解决。

public class LoginViewModel
{
    [EmailAddress(ErrorMessage = "The email format is not valid")]
    public string Email{ get; set; }

自从这个程序不需要顶级域名以来,我一直收到关于它的抱怨。 - Wildly Stunted

8
new System.ComponentModel.DataAnnotations.EmailAddressAttribute().IsValid(input)

我对C#默认的EmailAddress验证存在的问题是,即使没有提供TLD,它们也会接受abc@de作为有效的电子邮件。你有什么解决办法吗? - Reza Taba
@Reza Taba - 我相信你问题的答案在这里:https://dev59.com/EGIj5IYBdhLWcg3wJCF- - StackOverflowUser

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