ChatGPT解决这个技术问题 Extra ChatGPT

验证电子邮件地址的 C# 代码

验证字符串是否为有效电子邮件地址的最优雅的代码是什么?

还有许多其他重要的验证,不仅仅是字符串,最好检查电子邮件是否存在于这个 smtp 服务器上,或者用户正在输入任何电子邮件。等等,或者使用 API 来处理这些,以确保电子邮件像 ver-email.com 一样是正确的
您可以使用 github.com/jstedfast/EmailValidation 库。

M
Mike Weiss

那这个呢?

bool IsValidEmail(string email)
{
    var trimmedEmail = email.Trim();

    if (trimmedEmail.EndsWith(".")) {
        return false; // suggested by @TK-421
    }
    try {
        var addr = new System.Net.Mail.MailAddress(email);
        return addr.Address == trimmedEmail;
    }
    catch {
        return false;
    }
}

根据 Stuart 的评论,这会将最终地址与原始字符串进行比较,而不是始终返回 true。 MailAddress 尝试将带有空格的字符串解析为“显示名称”和“地址”部分,因此原始版本返回误报。

为了澄清,问题是询问特定字符串是否是电子邮件地址的有效表示,而不是电子邮件地址是否是发送消息的有效目的地。为此,唯一真正的方法是发送消息进行确认。

请注意,电子邮件地址比您最初想象的要宽容。这些都是完全有效的形式:

齿轮@车轮

“橘子齿轮”@example.com

123@$.xyz

对于大多数用例,虚假的“无效”比虚假的“有效”对您的用户和未来的证明更糟糕。这是此问题的article that used to be the accepted answer(该答案已被删除)。它有更多的细节和如何解决问题的其他一些想法。

提供健全性检查对于用户体验来说仍然是一个好主意。假设电子邮件地址有效,您可以查找已知的顶级域,检查域中的 MX 记录,检查常见域名 (gmail.cmo) 中的拼写错误等。然后向用户发出警告有机会说“是的,我的邮件服务器确实允许 🌮🍳🎁 作为电子邮件地址。”

至于对业务逻辑使用异常处理,我同意这是要避免的事情。但这是方便和清晰可能超过教条的情况之一。

此外,如果您对电子邮件地址进行任何其他操作,则可能需要将其转换为 MailAddress。即使您不使用这个确切的功能,您也可能希望使用相同的模式。您还可以通过捕获 different exceptions 检查特定类型的故障:null、空或无效格式。

--- 延伸阅读 ---

Documentation for System.Net.Mail.MailAddress

Explanation of what makes up a valid email address


实际上,这并不正确。 a@a 是一个有效的电子邮件地址。请参阅 haacked.com/archive/2007/08/21/… 事实上,如果您使用带引号的地址,此方法会返回不正确的结果。
+1:如果您使用 System.Net.Mail 类发送邮件,这是最好的答案,如果您使用 .NET,您可能就是这样。我们之所以决定使用这种类型的验证,仅仅是因为我们接受电子邮件地址(即使是有效的地址)毫无意义,因为我们无法向其发送邮件。
我不推荐。它返回真:IsValidEmail("this is not valid@email$com");
很多问题似乎是因为 MailAddress 也尝试解析 DisplayName,因此“single space@domain.com”解析为 DisplayName“single”和地址“space@domain.com”。对此的解决方法是: return (addr.Address == email);
我喜欢这个;我没有强迫比实际规范更严格。误报比误报更糟糕(“你的意思是我的电子邮件无效吗?”)
i
imjosh

这是一个老问题,但我在 SO 上找到的所有答案,包括最近的答案,都与这个答案类似。但是,在 .Net 4.5 / MVC 4 中,您可以通过从 System.ComponentModel.DataAnnotations 添加 [EmailAddress] 注释来向表单添加电子邮件地址验证,所以我想知道为什么我不能只使用来自 .网一般。

这似乎有效,在我看来相当优雅:

using System.ComponentModel.DataAnnotations;

class ValidateSomeEmails
{
    static void Main(string[] args)
    {
        var email = new EmailAddressAttribute();
        email.IsValid("someone@somewhere.com");         //true
        email.IsValid("someone@somewhere.co.uk");       //true
        email.IsValid("someone+tag@somewhere.net");     //true
        email.IsValid("futureTLD@somewhere.fooo");      //true
        
        email.IsValid("fdsa");                          //false
        email.IsValid("fdsa@");                         //false
        email.IsValid("fdsa@fdsa");                     //false
        email.IsValid("fdsa@fdsa.");                    //false

        //one-liner
        if (new EmailAddressAttribute().IsValid("someone@somewhere.com")) 
            return true;
    }
}

很酷,尽管令人失望的是 MS 无法让这与 their own documentation 一致。这拒绝 js@proseware.com9
请注意,EmailAddressAttribute 不如 System.Net.Mail.MailAddress 允许 - 例如,MailAddress 接受 TLD 的地址。如果您需要尽可能宽容,请记住一些事情。
@Cogwheel:如果答案位于评论中的某处,则可能应该将其添加到答案的主体中。
@hofnarwillie:它在主体中,但评论很详细。如果您的目标是不激怒您的用户,那么您的验证不应该比规范更具限制性。真正验证电子邮件是否有效的唯一方法是发送测试消息。
请注意,foo.IsValid(null); 返回 true
M
Marc.2377

我使用这种为我工作的单班轮方法-

using System.ComponentModel.DataAnnotations;
public bool IsValidEmail(string source)
{
    return new EmailAddressAttribute().IsValid(source);
}

根据评论,如果 source(电子邮件地址)为空,这将“失败”。

public static bool IsValidEmailAddress(this string address) => address != null && new EmailAddressAttribute().IsValid(address);

这对我不起作用;我得到,“'数据注释'不存在......你是否缺少程序集参考?”我需要添加哪个参考?
如果 source 为空,这将返回 true。请参阅msdn.microsoft.com/en-us/library/hh192424“如果指定的值有效或为 null,则为 true;否则为 false。”
更好的版本:public static Boolean IsValidMailAddress(this String pThis) => pThis == null ? false : new EmailAddressAttribute().IsValid(pThis);
甚至更好:public static bool IsValidEmailAddress(this string address) => address != null && new EmailAddressAttribute().IsValid(address);
我认为这个扩展方法不应该为空字符串默默地返回 false。这就是为什么我提出(更好更好)++ 版本:public static bool IsValidEmailAddress(this string address) => new EmailAddressAttribute().IsValid(address ?? throw new ArgumentNullException());。我现在要去寻找更好更好的版本主义者的归正教会。
T
Thomas Ayoub

.net 4.5 添加了 System.ComponentModel.DataAnnotations.EmailAddressAttribute

您可以浏览 EmailAddressAttribute's source,这是它在内部使用的正则表达式:

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])))\.?$";

不幸的是,EmaillAddressAttribute 允许 Ñ 这不是电子邮件的有效字符
@BZ 是的。为什么你认为不是?
@Chad Grant:这是一个 C# 版本。你能提供一个VB.Net吗?因为这会将 \\ 到 \ 之类的字符转义,或者您可以逐字提供字符串。
这行得通,但不要忘记 RegexOptions.IgnoreCase 因为这种模式明确不允许大写字母!
请注意,Regex 是经过深思熟虑的:“此属性提供与 jquery validate 等效的服务器端电子邮件验证,因此共享相同的正则表达式”。
D
David Silva Smith

我从 #1 中获取了 Phil 的答案并创建了这个类。像这样称呼它:bool isValid = Validator.EmailIsValid(emailString);

这是课程:

using System.Text.RegularExpressions;

public static class Validator
{

    static Regex ValidEmailRegex = CreateValidEmailRegex();

    /// <summary>
    /// Taken from http://haacked.com/archive/2007/08/21/i-knew-how-to-validate-an-email-address-until-i.aspx
    /// </summary>
    /// <returns></returns>
    private static Regex CreateValidEmailRegex()
    {
        string validEmailPattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
            + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
            + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";

        return new Regex(validEmailPattern, RegexOptions.IgnoreCase);
    }

    internal static bool EmailIsValid(string emailAddress)
    {
        bool isValid = ValidEmailRegex.IsMatch(emailAddress);

        return isValid;
    }
}

只是一个小的,但我会使用: return (!string.IsNullOrEmpty(emailAddress)) && ValidEmailRegex.IsMatch(emailAddress);
这只是恐怖:)
这不会验证具有 1 个字符域的电子邮件。即:bla@a.com
@Владимiръ 你运行代码了吗?上次有人说它不起作用时,我启动了一个编码环境,它确实正确验证了。我已经有 8 年没有使用 C# 了,我真的很好奇你是否知道它不起作用,或者你是否正在阅读代码并说它不起作用。
K
Kibbee

就个人而言,我会说你应该确保那里有一个 @ 符号,可能还有一个 .特点。您可以使用许多正则表达式来获得不同的正确性,但我认为其中大多数都会遗漏有效的电子邮件地址,或者让无效的电子邮件地址通过。如果人们想输入一个假的电子邮件地址,他们就会输入一个假的。如果您需要验证电子邮件地址是否合法,并且该人控制该电子邮件地址,那么您需要向他们发送带有特殊编码链接的电子邮件,以便他们验证它确实是一个真实地址。


我个人认为你应该做更多的验证。一定有人会尝试使用 Bobby Table 的电子邮件地址或更糟。
如果您使用准备好的语句,那么 bobby table 的电子邮件地址有什么问题。我们谈论的是有效的电子邮件地址,而不是与有效电子邮件地址无关的其他事情,例如如何正确执行 SQL 查询,以免遇到 SQL 注入问题。
我猜你不知道有人会在里面放什么,但一个恶意的人知道这个值最终可能会被输入你的邮件系统。我只是更喜欢深入防守并且更严格一些。
这是邮件系统要担心的。我不会仅仅因为它可能是其他系统的安全问题而拒绝完全有效的电子邮件地址。如果您的电子邮件服务器只需要一个格式错误的电子邮件地址来导致安全问题,那么您可能应该切换到另一台服务器。
只有当您的安全洋葱的每一层都没有腐烂时,深度防御才有效。一层腐烂意味着你破坏了整个洋葱。拒绝“foo@example.com.au”,因为您想防御 Sun 的 µ-law 编码中的漏洞是没有意义的,不是吗?别笑,这件事发生在我身上。我在这里评论的原因是澳大利亚联邦医疗保险不允许“.au”地址,只有“.com”。另请阅读 Mark Swanson,“如何不验证电子邮件”,mdswanson.com/blog/2013/10/14/…
N
Naveen

简短而准确的代码

string Email = txtEmail.Text;
if (Email.IsValidEmail())
{
   //use code here 
}

public static bool IsValidEmail(this string email)
{
  string pattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|" + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)" + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";    
  var regex = new Regex(pattern, RegexOptions.IgnoreCase);    
  return regex.IsMatch(email);
}

我不得不将 public static bool IsValidEmail(this string email) 更改为 public static bool IsValidEmail(string email) 以避免这个:stackoverflow.com/questions/10412233/…
@Goner Doug,这个功能将像这样工作。(bool flag = EmailAddress.IsValidEmail())
需要删除“THIS”以避免在添加到我的表单时导致编译器问题。
@Goner Doug,它的功能将像这样工作。字符串电子邮件=“abc@xyz.com”; if (email.IsValidEmail()){ return false; }否则{返回真;}
R
Ruben Pita

我认为最好的方法如下:

    public static bool EmailIsValid(string email)
    {
        string expression = "\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";

        if (Regex.IsMatch(email, expression))
        {
            if (Regex.Replace(email, expression, string.Empty).Length == 0)
            {
                return true;
            }
        }
        return false;
    }

您可以在通用类中使用此静态函数。


此答案不接受域部分中带有 TLD 的地址。
W
WonderWorker

最优雅的方法是使用 .Net 的内置方法。

这些方法:

经过试验和测试。这些方法用于我自己的专业项目中。

内部使用正则表达式,可靠且快速。

由 Microsoft 为 C# 制作。没有必要重新发明轮子。

返回一个布尔结果。 True 表示电子邮件有效。

适用于 .Net 4.5 及更高版本的用户

将此引用添加到您的项目中:

System.ComponentModel.DataAnnotations

现在您可以使用以下代码:

(new EmailAddressAttribute().IsValid("youremailhere@test.test"));

使用示例

以下是一些声明方法:

protected List<string> GetRecipients() // Gets recipients from TextBox named `TxtRecipients`
{
    List<string> MethodResult = null;

    try
    {
        List<string> Recipients = TxtRecipients.Text.Replace(",",";").Replace(" ", "").Split(';').ToList();

        List<string> RecipientsCleaned = new List<string>();

        foreach (string Recipient in RecipientsCleaned)
        {
            if (!String.IsNullOrWhiteSpace(Recipient))
            {
                RecipientsNoBlanks.Add(Recipient);

            }

        }

        MethodResult = RecipientsNoBlanks;

    }
    catch//(Exception ex)
    {
        //ex.HandleException();
    }

    return MethodResult;

}


public static bool IsValidEmailAddresses(List<string> recipients)
{
    List<string> InvalidAddresses = GetInvalidEmailAddresses(recipients);

    return InvalidAddresses != null && InvalidAddresses.Count == 0;

}

public static List<string> GetInvalidEmailAddresses(List<string> recipients)
{
    List<string> MethodResult = null;

    try
    {
        List<string> InvalidEmailAddresses = new List<string>();

        foreach (string Recipient in recipients)
        {
            if (!(new EmailAddressAttribute().IsValid(Recipient)) && !InvalidEmailAddresses.Contains(Recipient))
            {
                InvalidEmailAddresses.Add(Recipient);

            }

        }

        MethodResult = InvalidEmailAddresses;

    }
    catch//(Exception ex)
    {
        //ex.HandleException();

    }

    return MethodResult;

}

...以及演示它们的代码:

List<string> Recipients = GetRecipients();

bool IsValidEmailAddresses = IsValidEmailAddresses(Recipients);

if (IsValidEmailAddresses)
{
    //Emails are valid. Your code here

}
else
{
    StringBuilder sb = new StringBuilder();

    sb.Append("The following addresses are invalid:");

    List<string> InvalidEmails = GetInvalidEmailAddresses(Recipients);

    foreach (string InvalidEmail in InvalidEmails)
    {
        sb.Append("\n" + InvalidEmail);

    }

    MessageBox.Show(sb.ToString());

}

另外,这个例子:

超出规范,因为单个字符串用于包含 0 个、一个或多个由分号分隔的电子邮件地址;。

清楚地演示了如何使用 EmailAddressAttribute 对象的 IsValid 方法。

替代方案,适用于 .Net 版本低于 4.5 的用户

对于 .Net 4.5 不可用的情况,我使用以下解决方案:

具体来说,我使用:

public static bool IsValidEmailAddress(string emailAddress)
{
    bool MethodResult = false;

    try
    {
        MailAddress m = new MailAddress(emailAddress);

        MethodResult = m.Address == emailAddress;

    }
    catch //(Exception ex)
    {
        //ex.HandleException();

    }

    return MethodResult;

}

public static List<string> GetInvalidEmailAddresses(List<string> recipients)
{
    List<string> MethodResult = null;

    try
    {
        List<string> InvalidEmailAddresses = new List<string>();

        foreach (string Recipient in recipients)
        {
            if (!IsValidEmail(Recipient) && !InvalidEmailAddresses.Contains(Recipient))
            {
                InvalidEmailAddresses.Add(Recipient);

            }

        }

        MethodResult = InvalidEmailAddresses;

    }
    catch //(Exception ex)
    {
        //ex.HandleException();

    }

    return MethodResult;

}

@ThomasAyoub 我没有看到 EmailAddressAttribute 答案,也没有使用 new MailAddress() 检查输入 == .Address 的答案,所以我认为它非常有用。如果不阅读评论,则接受的答案是非常错误的。 new MailAddress("Foobar Some@thing.com") 证明了这一点。
@Jan fwiw,Manik 以不到四个月的时间击败 Knickerless 到 EmailAddressAttribute,尽管这个确实抓住了 null 的问题。
N
Noon Silk

老实说,在生产代码中,我做的最好的事情就是检查 @ 符号。

我永远无法完全验证电子邮件。你知道我怎么看它是否真的有效吗?如果寄过去了。如果没有,那就糟糕了,如果有,生活就是美好的。这就是我需要知道的。


M
Matthew Lock

我发现这个正则表达式在检查不仅仅是@标记和接受奇怪的边缘情况之间是一个很好的权衡:

^[^@\s]+@[^@\s]+(\.[^@\s]+)+$

它至少会让你在 @ 标记周围加上一些东西,并至少放置一个看起来正常的域。


我想出了相同的正则表达式;)它确实允许无效字符
此答案不接受域部分中的 TLD。
@Simone 可能没有人在域部分拥有带有 TLD 的电子邮件地址,但实际上:serverfault.com/a/721929/167961 请在评论中注意这几天可能会被禁止
@MatthewLock 会不会是内网地址?喜欢bob@companyinternal
@Simone 现实生活中是否有人真正使用该方案?
M
Mauricio Scheffer

电子邮件地址验证并不像看起来那么容易。实际上,仅使用正则表达式完全验证电子邮件地址在理论上是不可能的。

查看我的blog post,了解有关该主题的讨论以及使用 FParsec 的 F# 实现。 [/无耻插件]


我喜欢你的替代方法列表;很有意思。
有趣的文章。但说真的,谁在电子邮件地址中添加评论和嵌套评论?
@matthew 我不知道为什么 IETF 甚至允许这样做,但这是可能的,因此必须进行彻底的验证。
M
Manuel Fuchs

我只想指出,最近在 .NET 文档中添加了有关电子邮件验证的内容,也使用了 Regex 操作。可以在此处找到对其实施的详尽解释。

https://docs.microsoft.com/en-us/dotnet/standard/base-types/how-to-verify-that-strings-are-in-valid-email-format

为方便起见,以下是他们的测试结果列表:

//       Valid: david.jones@proseware.com
//       Valid: d.j@server1.proseware.com
//       Valid: jones@ms1.proseware.com
//       Invalid: j.@server1.proseware.com
//       Valid: j@proseware.com9
//       Valid: js#internal@proseware.com
//       Valid: j_9@[129.126.118.1]
//       Invalid: j..s@proseware.com
//       Invalid: js*@proseware.com
//       Invalid: js@proseware..com
//       Valid: js@proseware.com9
//       Valid: j.s@server1.proseware.com
//       Valid: "j\"s\""@proseware.com
//       Valid: js@contoso.中国

V
Vasya Milovidov

我总结了截至 2021 年的所有上述答案,我为自己写了这门课:

public static class StringExt {
    private const string emailPattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|" 
            + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)" 
            + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";

    public static bool IsValidMailAddress(this string pThis) 
            => pThis is not null 
            && Regex.IsMatch(pThis, emailPattern, RegexOptions.IgnoreCase);
}

用于检测连续的多个 . 和引号之外的 ,,并且似乎遵循此处列出的标准:en.wikipedia.org/wiki/Email_address#Local-part 但不允许 RFC 6530 允许的国际字符。
R
Ralph N

这是我的答案——对于像“someone@q.com”这样的单字母域,Phil 的解决方案失败了。信不信由你,这是使用 =) (例如,去世纪链接)。

Phil 的回答也只适用于 PCRE 标准......所以 C# 会接受它,但 javascript 会爆炸。对于javascript来说太复杂了。因此,您不能将 Phil 的解决方案用于 mvc 验证属性。

这是我的正则表达式。它可以很好地与 MVC 验证属性一起使用。 - @ 之前的所有内容都被简化,因此至少 javascript 可以工作。只要交换服务器没有给我 5.1.3,我就可以在这里放松验证。 - @ 之后的所有内容都是 Phil 针对单字母域修改的解决方案。

public const string EmailPattern =
        @"^\s*[\w\-\+_']+(\.[\w\-\+_']+)*\@[A-Za-z0-9]([\w\.-]*[A-Za-z0-9])?\.[A-Za-z][A-Za-z\.]*[A-Za-z]$";

对于建议使用 system.net.mail MailMessage() 的人来说,这很灵活。当然,C# 会接受电子邮件,但是一旦您尝试发送电子邮件,Exchange 服务器就会出现 5.1.3 运行时错误。


这似乎是最好的最周到/合理/真实的答案,谢谢拉尔夫!
这是迄今为止最好的答案!我无法相信接受 basket@ball 作为有效电子邮件地址的错误解决方案已获得正确答案以及所有这些赞成票。不管怎么说,还是要谢谢你!
谢谢这是最好的解决方案,应该被接受。
C
Corniel Nobel

正如许多答案中提到的,电子邮件地址的域很复杂。在这种情况下,我强烈反对使用正则表达式。匹配(大多数)案例的那些阅读和维护非常复杂。此外,仍然难以支持所有案例,而且速度很慢。

Microsoft 的 EmailAddress 类在这方面有所帮助,但我认为也不完美。对于一个开源项目,我在几年前尝试过使用自定义的 EmailParser

这在 [EmailAddress]https://github.com/Qowaiv/Qowaiv/blob/master/src/Qowaiv/EmailAddress.cs 中使用)。

通过使用这种方法,您不仅可以验证电子邮件地址,还可以清除多种格式的显示名称、去掉 mailto: 前缀、基于 IP 地址规范化域文字以及小写所有内容 (请注意,本地部分正式区分大小写)。

场景的您的解决方案应该支持(并且提到的解决方案支持):

[TestCase(null)]
[TestCase("")]
[TestCase("..@test.com")]
[TestCase(".a@test.com")]
[TestCase("ab@sd@dd")]
[TestCase(".@s.dd")]
[TestCase("ab@988.120.150.10")]
[TestCase("ab@120.256.256.120")]
[TestCase("ab@120.25.1111.120")]
[TestCase("ab@[188.120.150.10")]
[TestCase("ab@188.120.150.10]")]
[TestCase("ab@[188.120.150.10].com")]
[TestCase("a@b.-de.cc")]
[TestCase("a@bde-.cc")]
[TestCase("a@bde.c-c")]
[TestCase("a@bde.cc.")]
[TestCase("ab@b+de.cc")]
[TestCase("a..b@bde.cc")]
[TestCase("_@bde.cc,")]
[TestCase("plainaddress")]
[TestCase("plain.address")]
[TestCase("@%^%#$@#$@#.com")]
[TestCase("@domain.com")]
[TestCase("Joe Smith &lt;email@domain.com&gt;")]
[TestCase("email.domain.com")]
[TestCase("email@domain@domain.com")]
[TestCase(".email@domain.com")]
[TestCase("email.@domain.com")]
[TestCase("email..email@domain.com")]
[TestCase("email@-domain.com")]
[TestCase("email@domain-.com")]
[TestCase("email@domain.com-")]
[TestCase("email@.domain.com")]
[TestCase("email@domain.com.")]
[TestCase("email@domain..com")]
[TestCase("email@111.222.333")]
[TestCase("email@111.222.333.256")]
[TestCase("email@[123.123.123.123")]
[TestCase("email@[123.123.123].123")]
[TestCase("email@123.123.123.123]")]
[TestCase("email@123.123.[123.123]")]
[TestCase("email@{leftbracket.com")]
[TestCase("email@rightbracket}.com")]
[TestCase("email@p|pe.com")]
[TestCase("isis@100%.nl")]
[TestCase("email@dollar$.com")]
[TestCase("email@r&amp;d.com")]
[TestCase("email@#hash.com")]
[TestCase("email@wave~tilde.com")]
[TestCase("email@exclamation!mark.com")]
[TestCase("email@question?mark.com")]
[TestCase("email@obelix*asterisk.com")]
[TestCase("email@grave`accent.com")]
[TestCase("email@colon:colon.com")]
[TestCase("email@caret^xor.com")]
[TestCase("email@=qowaiv.com")]
[TestCase("email@plus+.com")]
[TestCase("email@domain.com>")]
[TestCase("email( (nested) )@plus.com")]
[TestCase("email)mirror(@plus.com")]
[TestCase("email@plus.com (not closed comment")]
[TestCase("email(with @ in comment)plus.com")]
[TestCase(@"""Joe Smith email@domain.com")]
[TestCase(@"""Joe Smith' email@domain.com")]
[TestCase(@"""Joe Smith""email@domain.com")]
[TestCase("email@mailto:domain.com")]
[TestCase("mailto:mailto:email@domain.com")]
[TestCase("Display Name <email@plus.com> (after name with display)")]
[TestCase("ReDoSaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")]
public void IsInvalid(string email)
{
    Assert.IsFalse(EmailAddress.IsValid(email), email);
}

[TestCase("w@com")]
[TestCase("w.b.f@test.com")]
[TestCase("w.b.f@test.museum")]
[TestCase("a.a@test.com")]
[TestCase("ab@288.120.150.10.com")]
[TestCase("ab@188.120.150.10")]
[TestCase("ab@1.0.0.10")]
[TestCase("ab@120.25.254.120")]
[TestCase("ab@01.120.150.1")]
[TestCase("ab@88.120.150.021")]
[TestCase("ab@88.120.150.01")]
[TestCase("ab@[120.254.254.120]")]
[TestCase("local@2001:0db8:85a3:0000:0000:8a2e:0370:7334")]
[TestCase("local@[2001:0db8:85a3:0000:0000:8a2e:0370:7334]")]
[TestCase("2@bde.cc")]
[TestCase("-@bde.cc")]
[TestCase("a2@bde.cc")]
[TestCase("a-b@bde.cc")]
[TestCase("ab@b-de.cc")]
[TestCase("a+b@bde.cc")]
[TestCase("f.f.f@bde.cc")]
[TestCase("ab_c@bde.cc")]
[TestCase("_-_@bde.cc")]
[TestCase("k.haak@12move.nl")]
[TestCase("K.HAAK@12MOVE.NL")]
[TestCase("email@domain.com")]
[TestCase("email@domain")]
[TestCase("あいうえお@domain.com")]
[TestCase("local@あいうえお.com")]
[TestCase("firstname.lastname@domain.com")]
[TestCase("email@subdomain.domain.com")]
[TestCase("firstname+lastname@domain.com")]
[TestCase("email@123.123.123.123")]
[TestCase("email@[123.123.123.123]")]
[TestCase("1234567890@domain.com")]
[TestCase("a@domain.com")]
[TestCase("a.b.c.d@domain.com")]
[TestCase("aap.123.noot.mies@domain.com")]
[TestCase("1@domain.com")]
[TestCase("email@domain-one.com")]
[TestCase("_______@domain.com")]
[TestCase("email@domain.topleveldomain")]
[TestCase("email@domain.co.jp")]
[TestCase("firstname-lastname@domain.com")]
[TestCase("firstname-lastname@d.com")]
[TestCase("FIRSTNAME-LASTNAME@d--n.com")]
[TestCase("first-name-last-name@d-a-n.com")]
[TestCase("{local{name{{with{@leftbracket.com")]
[TestCase("}local}name}}with{@rightbracket.com")]
[TestCase("|local||name|with|@pipe.com")]
[TestCase("%local%%name%with%@percentage.com")]
[TestCase("$local$$name$with$@dollar.com")]
[TestCase("&local&&name&with&$@amp.com")]
[TestCase("#local##name#with#@hash.com")]
[TestCase("~local~~name~with~@tilde.com")]
[TestCase("!local!!name!with!@exclamation.com")]
[TestCase("?local??name?with?@question.com")]
[TestCase("*local**name*with*@asterisk.com")]
[TestCase("`local``name`with`@grave-accent.com")]
[TestCase("^local^^name^with^@xor.com")]
[TestCase("=local==name=with=@equality.com")]
[TestCase("+local++name+with+@equality.com")]
[TestCase("Joe Smith <email@domain.com>")]
[TestCase("email@domain.com (joe Smith)")]
[TestCase(@"""Joe Smith"" email@domain.com")]
[TestCase(@"""Joe\\tSmith"" email@domain.com")]
[TestCase(@"""Joe\""Smith"" email@domain.com")]
[TestCase(@"Test |<gaaf <email@domain.com>")]
[TestCase("MailTo:casesensitve@domain.com")]
[TestCase("mailto:email@domain.com")]
[TestCase("Joe Smith <mailto:email@domain.com>")]
[TestCase("Joe Smith <mailto:email(with comment)@domain.com>")]
[TestCase(@"""With extra < within quotes"" Display Name<email@domain.com>")]
[TestCase("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")]
public void IsValid(string email)
{
    Assert.IsTrue(EmailAddress.IsValid(email), email);
}

J
Joe Caffeine

如果你真的和我的意思是真的想知道一个电子邮件地址是否有效......请邮件交换器证明它,不需要正则表达式。如果需要,我可以提供代码。

一般步骤如下: 1. 邮箱地址有域名部分吗? (@ > 0 的索引) 2. 使用 DNS 查询询问域是否有邮件交换器 3. 打开与邮件交换器的 tcp 连接 4. 使用 smtp 协议,使用电子邮件地址作为接收者向服务器打开一条消息 5.解析服务器的响应。 6. 如果你做到了这一步,请退出消息,一切都很好。

正如您可以想象的那样,在时间上非常昂贵并且依赖于 smtp,但它确实有效。


您是否为这些接口创建了假货、存根和/或模拟?
那是行不通的。验证电子邮件地址的 smtp 协议已长期被弃用/未使用。在邮件服务器上启用它被认为是不好的做法,因为垃圾邮件发送者使用该功能。
我会将您的建议保留到第 2 点。比检查已知域名模式更具前瞻性。
吹毛求疵,但定义“有一个邮件交换器”?如果不存在 MX 记录,则 SMTP 应根据 RFC2821/5321 回退到 A/AAAA 记录。如果确实存在 MX 记录,它仍然可能不指示存在邮件交换器 (RFC7505)。真的,唯一的方法就是给他们发一封带有号召性用语链接的邮件,然后等待他们回复……
P
Phil C

这里有很多强有力的答案。但是,我建议我们退后一步。 @Cogwheel 回答问题 https://stackoverflow.com/a/1374644/388267。然而,如果正在验证的许多电子邮件地址无效,则在批量验证方案中成本可能很高。我建议我们在进入他的 try-catch 块之前使用一些逻辑。我知道可以使用 RegEx 编写以下代码,但是对于新开发人员来说理解起来可能会很昂贵。这是我的两便士价值:

    public static bool IsEmail(this string input)
    {
        if (string.IsNullOrWhiteSpace(input)) return false;

        // MUST CONTAIN ONE AND ONLY ONE @
        var atCount = input.Count(c => c == '@');
        if (atCount != 1) return false;

        // MUST CONTAIN PERIOD
        if (!input.Contains(".")) return false;

        // @ MUST OCCUR BEFORE LAST PERIOD
        var indexOfAt = input.IndexOf("@", StringComparison.Ordinal);
        var lastIndexOfPeriod = input.LastIndexOf(".", StringComparison.Ordinal);
        var atBeforeLastPeriod = lastIndexOfPeriod > indexOfAt;
        if (!atBeforeLastPeriod) return false;

        // CODE FROM COGWHEEL'S ANSWER: https://stackoverflow.com/a/1374644/388267 
        try
        {
            var addr = new System.Net.Mail.MailAddress(input);
            return addr.Address == input;
        }
        catch
        {
            return false;
        }
    }

E
Efran Cobisi

一般来说,验证电子邮件地址的正则表达式并不是一件容易的事情。在撰写本文时,电子邮件地址的语法必须遵循相对较多的标准,并且在正则表达式中实现所有这些标准实际上是不可行的!

我强烈建议您试试我们的 EmailVerify.NET,这是一个成熟的 .NET 库,它可以根据当前 IETF 标准(RFC 1123、RFC 2821、RFC 2822、RFC 3696、RFC 4291)验证所有的电子邮件地址, RFC 5321 和 RFC 5322),测试相关的 DNS 记录,检查目标邮箱是否可以接受邮件,甚至可以判断给定地址是否是一次性的。

免责声明:我是该组件的首席开发人员。


感人的! “接下来,它会尝试联系负责给定电子邮件地址的邮件交换器,并与该服务器开始一个虚假的 SMTP 对话,模拟真实的邮件服务器。这样可以确保服务器可以处理该地址的电子邮件。实际上有许多 SMTP 服务器回复误报答案以防止垃圾邮件发送者:为了克服这个问题,.NET 的 EmailVerify 最终尝试使用不同的伪造地址多次查询目标邮件交换器。”
谢谢,@MatthewLock ;)
很好,但我只看到付费版本。有社区/开源版本的计划吗?
@OhadSchneider 是的:我们通过我们的 SaaS email verification service Verifalia 提供免费版本的电子邮件验证技术。 Verifalia 为主要软件开发平台(包括 .NET)提供免费的开源 SDK。
a
aBertrand

一个简单的不使用正则表达式(我不喜欢它的可读性差):

bool IsValidEmail(string email)
{
    string emailTrimed = email.Trim();

    if (!string.IsNullOrEmpty(emailTrimed))
    {
        bool hasWhitespace = emailTrimed.Contains(" ");

        int indexOfAtSign = emailTrimed.LastIndexOf('@');

        if (indexOfAtSign > 0 && !hasWhitespace)
        {
            string afterAtSign = emailTrimed.Substring(indexOfAtSign + 1);

            int indexOfDotAfterAtSign = afterAtSign.LastIndexOf('.');

            if (indexOfDotAfterAtSign > 0 && afterAtSign.Substring(indexOfDotAfterAtSign).Length > 1)
                return true;
        }
    }

    return false;
}

例子:

IsValidEmail("@b.com") // 假

IsValidEmail("a@.com") // 假

IsValidEmail("a@bcom") // 假

IsValidEmail("ab@com") // 假

IsValidEmail("a@b.") // 假

IsValidEmail("ab@c.com") // 假

IsValidEmail("a@b c.com") // 假

IsValidEmail("a@b.com") // 真

IsValidEmail("a@bccom") // 真

IsValidEmail("a+b@c.com") // 真

IsValidEmail("a@123.45.67.89") // 真

它很简单,因此它不处理罕见的情况,例如带有包含空格(通常允许)的带括号域的电子邮件、带有 IPv6 地址的电子邮件等。


u
user2211290
For the simple email like goerge@xxx.com, below code is sufficient. 

 public static bool ValidateEmail(string email)
        {
            System.Text.RegularExpressions.Regex emailRegex = new System.Text.RegularExpressions.Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");
            System.Text.RegularExpressions.Match emailMatch = emailRegex.Match(email);
            return emailMatch.Success;
        }

它将无法将 a@b.info 验证为有效的电子邮件地址。
U
Ulysses Alves

如果您使用 FluentValidation,您可以编写如下简单的内容:

public cass User
{
    public string Email { get; set; }
}

public class UserValidator : AbstractValidator<User>
{
    public UserValidator()
    {
        RuleFor(x => x.Email).EmailAddress().WithMessage("The text entered is not a valid email address.");
    }
}

// Validates an user. 
var validationResult = new UserValidator().Validate(new User { Email = "açflkdj" });

// This will return false, since the user email is not valid.
bool userIsValid = validationResult.IsValid;

r
rethabile

对@Cogwheel 答案的一些修改

public static bool IsValidEmail(this string email)
{
  // skip the exception & return early if possible
  if (email.IndexOf("@") <= 0) return false;

  try
  {
    var address = new MailAddress(email);
    return address.Address == email;
  }
  catch
  {
    return false;
  }
}

这似乎没有帮助... Console.WriteLine(MailAddress("asdf@asdf.").Address); 输出“asdf@asdf.”,这是无效的。
.net 似乎有自己的有效定义。相关discussion
L
Liakat Hossain

@Cogwheel 投票最多的答案是最佳答案,但是我尝试实现 trim() 字符串方法,因此它将修剪从字符串开始到结束的所有用户空白。检查下面的代码以获取完整示例-

bool IsValidEmail(string email)
{
    try
    {
        email = email.Trim();
        var addr = new System.Net.Mail.MailAddress(email);
        return addr.Address == email;
    }
    catch
    {
        return false;
    }
}

这样做的风险是您正在验证与源不同的电子邮件地址,让您认为您可以邮寄到(在这种情况下)指定电子邮件地址的未修剪版本。更好的方法是创建一个单独的方法 SanitizeEmail(string email),使用该方法的结果来验证电子邮件并将其发送到。
a+b@b 使用此代码有效,但这不是有效的电子邮件
F
Filip

另一个正则表达式匹配答案:

   /// <summary>
   /// Validates the email input
   /// </summary>
   internal static bool ValidateEmail(string _emailAddress)
   { 

        string _regexPattern = @"^(([\w-]+\.)+[\w-]+|([a-zA-Z]{1}|[\w-]{2,}))@"
                + @"((([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\."
                + @"([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])){1}|"
                + @"([a-zA-Z]+[\w-]+\.)+[a-zA-Z]{2,4})$";

        return (string.IsNullOrEmpty(_emailAddress) == false && System.Text.RegularExpressions.Regex.IsMatch(_emailAddress, _regexPattern))
            ? true
            : false;
    }

E
ErwanLent
private static bool IsValidEmail(string emailAddress)
{
    const string validEmailPattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
                                     + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
                                     + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";

    return new Regex(validEmailPattern, RegexOptions.IgnoreCase).IsMatch(emailAddress);
}

R
Rajib Chy

通过 System.Text.RegularExpressions 检查电子邮件字符串的格式是否正确:

    public static bool IsValidEmailId(string InputEmail)
    {
        Regex regex = new Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");
        Match match = regex.Match(InputEmail);
        if (match.Success)
            return true;
        else
            return false;
    }

    protected void Email_TextChanged(object sender, EventArgs e)
    {
        String UserEmail = Email.Text;
        if (IsValidEmailId(UserEmail))
        {
            Label4.Text = "This email is correct formate";
        }
        else
        {
            Label4.Text = "This email isn't correct formate";
        }
    }

A
Aina Ademola C

/使用用于创建“new EmailAddressAttribute();”的内部正则表达式.Net4.5 中的组件 >>> 使用 System.ComponentModel.DataAnnotations; //验证电子邮件地址......经过测试和工作。

public bool IsEmail(string email)
{
    if (String.IsNullOrEmpty(email))
    {   return false;  }
    try
    {
        Regex _regex = new Regex("^((([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\\u" +
                "FDF0-\\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-\\uFF" +
                "EF])))\\.?$", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture | RegexOptions.Compiled);
        return _regex.IsMatch(email);
    }
    catch (RegexMatchTimeoutException)
    {
        return false;
    }
}

此外,您可以使用这个:

http://msdn.microsoft.com/en-us/library/01escwtf(v=vs.110).aspx


这封电子邮件说的是真的:“fulya_42_@hotmail.coö”,它在 mandrill api 处抛出错误
首先,电子邮件在 example@example.co 或 example@example.com 上是有效的......除了最后一个字符“ö”之外,电子邮件具有所有有效的字符串和条件,您可以轻松添加一个简单的条件来验证这样的字符.其次,我不确定 mandrill api 错误,你可能想验证你的使用方法,因为我已经在其他一些环境/api 上使用了这个验证,它对我很好。
B
B. Clay Shannon-B. Crow Raven

我像这样简化了 Poyson 1 的回答:

public static bool IsValidEmailAddress(string candidateEmailAddr)
{
    string regexExpresion = "\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
    return (Regex.IsMatch(candidateEmailAddr, regexExpresion)) && 
           (Regex.Replace(candidateEmailAddr, regexExpresion, string.Empty).Length == 0);
}

A
Amit Gorvadiya

识别 emailid 的简单方法是否有效。

public static bool EmailIsValid(string email)
{
        return Regex.IsMatch(email, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
}