验证字符串是否是有效的电子邮件地址的最优雅的代码是什么?
当前回答
对@齿轮回答做了一点修改
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;
}
}
其他回答
Personally, I would say that you should just make sure there is an @ symbol in there, with possibly a . character. There's many regexes you could use of varying correctness, but I think most of these leave out valid email addresses, or let invalid ones through. If people want to put in a fake email address, they will put in a fake one. If you need to verify that the email address is legit, and that the person is in control of that email address, then you will need to send them an email with a special coded link so they can verify that it indeed is a real address.
这是一个老问题,但我在SO上找到的所有答案,包括最近的答案,都与这个问题类似。然而,在。net 4.5 / MVC 4中,你可以通过从System.ComponentModel中添加[EmailAddress]注释来向表单添加电子邮件地址验证。DataAnnotations,所以我想知道为什么我不能只使用。net的内置功能。
这似乎是可行的,而且在我看来是相当优雅的:
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;
}
}
正如在许多回答中提到的,电子邮件地址的领域是复杂的。在这种情况下,我强烈反对使用正则表达式。那些匹配(大多数)用例的异常复杂,难以读取,因此也难以维护。此外,它们仍然难以支持所有病例,而且速度缓慢。
微软的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 <email@domain.com>")]
[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&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);
}
电子邮件地址验证并不像看起来那么简单。实际上,从理论上讲,仅使用正则表达式完全验证电子邮件地址是不可能的。
请查看我的博客文章,了解关于这个主题的讨论以及使用FParsec的f#实现。[/ shameless_plug]
如果你真的,我是说真的想知道一个电子邮件地址是否有效……请邮件交换器来证明它,不需要正则表达式。如果需要,我可以提供代码。
一般步骤如下: 1. 电子邮件地址有域名部分吗?(@ > 0的索引) 2. 使用DNS查询询问域是否有邮件交换器 3.打开到邮件交换器的TCP连接 4. 使用SMTP协议,以电子邮件地址作为接收者打开到服务器的消息 5. 解析服务器的响应。 6. 如果你能走到这一步,就别发短信了,一切都好。
正如您可以想象的那样,这是非常昂贵的时间,并且依赖于smtp,但它确实有效。
推荐文章
- c#中有任何连接字符串解析器吗?
- 在Linq中转换int到字符串到实体的问题
- 是否可以动态编译和执行c#代码片段?
- 创建自定义MSBuild任务时,如何从c#代码获取当前项目目录?
- c#和Java的主要区别是什么?
- 在c#中创建一个特定时区的DateTime
- .NET中的属性是什么?
- csproj文件中的“Service Include”是干什么用的?
- 如何使用try catch进行异常处理是最佳实践
- 替换字符串中第一次出现的模式
- .NET中字节的字面后缀?
- 如何处理AccessViolationException
- c#忽略证书错误?
- LINQ读取XML
- 如何强制LINQ Sum()返回0而源集合是空的