验证字符串是否是有效的电子邮件地址的最优雅的代码是什么?
当前回答
基于@Cogwheel的回答,我想分享一个修改后的解决方案,适用于SSIS和“脚本组件”:
Place the "Script Component" into your Data Flow connect and then open it. In the section "Input Columns" set the field that contains the E-Mail Adresses to "ReadWrite" (in the example 'fieldName'). Switch back to the section "Script" and click on "Edit Script". Then you need to wait after the code opens. Place this code in the right method: public override void Input0_ProcessInputRow(Input0Buffer Row) { string email = Row.fieldName; try { System.Net.Mail.MailAddress addr = new System.Net.Mail.MailAddress(email); Row.fieldName= addr.Address.ToString(); } catch { Row.fieldName = "WRONGADDRESS"; } }
然后,您可以使用条件分割过滤掉所有无效记录或任何您想做的事情。
其他回答
这是一个老问题,但我在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;
}
}
我根据维基百科的规则和样本地址创建了一个电子邮件地址验证程序。对于那些不介意多看一点代码的人,这里。说实话,我不知道电子邮件地址规范中有这么多疯狂的规则。我没有完全验证主机名或ipaddress,但它仍然通过了维基百科上的所有测试用例。
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace EmailValidateUnitTests
{
[TestClass]
public class EmailValidationUnitTests
{
[TestMethod]
public void TestEmailValidate()
{
// Positive Assertions
Assert.IsTrue("prettyandsimple@example.com".IsValidEmailAddress());
Assert.IsTrue("very.common@example.com".IsValidEmailAddress());
Assert.IsTrue("disposable.style.email.with+symbol@example.com".IsValidEmailAddress());
Assert.IsTrue("other.email-with-dash@example.com".IsValidEmailAddress());
Assert.IsTrue("\"much.more unusual\"@example.com".IsValidEmailAddress());
Assert.IsTrue("\"very.unusual.@.unusual.com\"@example.com".IsValidEmailAddress()); //"very.unusual.@.unusual.com"@example.com
Assert.IsTrue("\"very.(),:;<>[]\\\".VERY.\\\"very@\\\\ \\\"very\\\".unusual\"@strange.example.com".IsValidEmailAddress()); //"very.(),:;<>[]\".VERY.\"very@\\ \"very\".unusual"@strange.example.com
Assert.IsTrue("admin@mailserver1".IsValidEmailAddress());
Assert.IsTrue("#!$%&'*+-/=?^_`{}|~@example.org".IsValidEmailAddress());
Assert.IsTrue("\"()<>[]:,;@\\\\\\\"!#$%&'*+-/=?^_`{}| ~.a\"@example.org".IsValidEmailAddress()); //"()<>[]:,;@\\\"!#$%&'*+-/=?^_`{}| ~.a"@example.org
Assert.IsTrue("\" \"@example.org".IsValidEmailAddress()); //" "@example.org (space between the quotes)
Assert.IsTrue("example@localhost".IsValidEmailAddress());
Assert.IsTrue("example@s.solutions".IsValidEmailAddress());
Assert.IsTrue("user@com".IsValidEmailAddress());
Assert.IsTrue("user@localserver".IsValidEmailAddress());
Assert.IsTrue("user@[IPv6:2001:db8::1]".IsValidEmailAddress());
Assert.IsTrue("user@[192.168.2.1]".IsValidEmailAddress());
Assert.IsTrue("(comment and stuff)joe@gmail.com".IsValidEmailAddress());
Assert.IsTrue("joe(comment and stuff)@gmail.com".IsValidEmailAddress());
Assert.IsTrue("joe@(comment and stuff)gmail.com".IsValidEmailAddress());
Assert.IsTrue("joe@gmail.com(comment and stuff)".IsValidEmailAddress());
// Failure Assertions
Assert.IsFalse("joe(fail me)smith@gmail.com".IsValidEmailAddress());
Assert.IsFalse("joesmith@gma(fail me)il.com".IsValidEmailAddress());
Assert.IsFalse("joe@gmail.com(comment and stuff".IsValidEmailAddress());
Assert.IsFalse("Abc.example.com".IsValidEmailAddress());
Assert.IsFalse("A@b@c@example.com".IsValidEmailAddress());
Assert.IsFalse("a\"b(c)d,e:f;g<h>i[j\\k]l@example.com".IsValidEmailAddress()); //a"b(c)d,e:f;g<h>i[j\k]l@example.com
Assert.IsFalse("just\"not\"right@example.com".IsValidEmailAddress()); //just"not"right@example.com
Assert.IsFalse("this is\"not\\allowed@example.com".IsValidEmailAddress()); //this is"not\allowed@example.com
Assert.IsFalse("this\\ still\\\"not\\\\allowed@example.com".IsValidEmailAddress());//this\ still\"not\\allowed@example.com
Assert.IsFalse("john..doe@example.com".IsValidEmailAddress());
Assert.IsFalse("john.doe@example..com".IsValidEmailAddress());
Assert.IsFalse(" joe@gmail.com".IsValidEmailAddress());
Assert.IsFalse("joe@gmail.com ".IsValidEmailAddress());
}
}
public static class ExtensionMethods
{
private const string ValidLocalPartChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&'*+-/=?^_`{|}~";
private const string ValidQuotedLocalPartChars = "(),:;<>@[]. ";
private const string ValidDomainPartChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-:";
private enum EmailParseMode
{
BeginLocal, Local, QuotedLocalEscape, QuotedLocal, QuotedLocalEnd, LocalSplit, LocalComment,
At,
Domain, DomainSplit, DomainComment, BracketedDomain, BracketedDomainEnd
};
public static bool IsValidEmailAddress(this string s)
{
bool valid = true;
bool hasLocal = false, hasDomain = false;
int commentStart = -1, commentEnd = -1;
var mode = EmailParseMode.BeginLocal;
for (int i = 0; i < s.Length; i++)
{
char c = s[i];
if (mode == EmailParseMode.BeginLocal || mode == EmailParseMode.LocalSplit)
{
if (c == '(') { mode = EmailParseMode.LocalComment; commentStart = i; commentEnd = -1; }
else if (c == '"') { mode = EmailParseMode.QuotedLocal; }
else if (ValidLocalPartChars.IndexOf(c) >= 0) { mode = EmailParseMode.Local; hasLocal = true; }
else { valid = false; break; }
}
else if (mode == EmailParseMode.LocalComment)
{
if (c == ')')
{
mode = EmailParseMode.Local; commentEnd = i;
// comments can only be at beginning and end of parts...
if (commentStart != 0 && ((commentEnd + 1) < s.Length) && s[commentEnd + 1] != '@') { valid = false; break; }
}
}
else if (mode == EmailParseMode.Local)
{
if (c == '.') mode = EmailParseMode.LocalSplit;
else if (c == '@') mode = EmailParseMode.At;
else if (c == '(') { mode = EmailParseMode.LocalComment; commentStart = i; commentEnd = -1; }
else if (ValidLocalPartChars.IndexOf(c) >= 0) { hasLocal = true; }
else { valid = false; break; }
}
else if (mode == EmailParseMode.QuotedLocal)
{
if (c == '"') { mode = EmailParseMode.QuotedLocalEnd; }
else if (c == '\\') { mode = EmailParseMode.QuotedLocalEscape; }
else if (ValidLocalPartChars.IndexOf(c) >= 0 || ValidQuotedLocalPartChars.IndexOf(c) >= 0) { hasLocal = true; }
else { valid = false; break; }
}
else if (mode == EmailParseMode.QuotedLocalEscape)
{
if (c == '"' || c == '\\') { mode = EmailParseMode.QuotedLocal; hasLocal = true; }
else { valid = false; break; }
}
else if (mode == EmailParseMode.QuotedLocalEnd)
{
if (c == '.') { mode = EmailParseMode.LocalSplit; }
else if (c == '@') mode = EmailParseMode.At;
else if (c == '(') { mode = EmailParseMode.LocalComment; commentStart = i; commentEnd = -1; }
else { valid = false; break; }
}
else if (mode == EmailParseMode.At)
{
if (c == '[') { mode = EmailParseMode.BracketedDomain; }
else if (c == '(') { mode = EmailParseMode.DomainComment; commentStart = i; commentEnd = -1; }
else if (ValidDomainPartChars.IndexOf(c) >= 0) { mode = EmailParseMode.Domain; hasDomain = true; }
else { valid = false; break; }
}
else if (mode == EmailParseMode.DomainComment)
{
if (c == ')')
{
mode = EmailParseMode.Domain;
commentEnd = i;
// comments can only be at beginning and end of parts...
if ((commentEnd + 1) != s.Length && (commentStart > 0) && s[commentStart - 1] != '@') { valid = false; break; }
}
}
else if (mode == EmailParseMode.DomainSplit)
{
if (ValidDomainPartChars.IndexOf(c) >= 0) { mode = EmailParseMode.Domain; hasDomain = true; }
else { valid = false; break; }
}
else if (mode == EmailParseMode.Domain)
{
if (c == '(') { mode = EmailParseMode.DomainComment; commentStart = i; commentEnd = -1; }
else if (c == '.') { mode = EmailParseMode.DomainSplit; }
else if (ValidDomainPartChars.IndexOf(c) >= 0) { hasDomain = true; }
else { valid = false; break; }
}
else if (mode == EmailParseMode.BracketedDomain)
{
if (c == ']') { mode = EmailParseMode.BracketedDomainEnd; }
else if (c == '.' || ValidDomainPartChars.IndexOf(c) >= 0) { hasDomain = true; }
else { valid = false; break; }
}
else if (mode == EmailParseMode.BracketedDomain)
{
if (c == '(') { mode = EmailParseMode.DomainComment; commentStart = i; commentEnd = -1; }
else { valid = false; break; }
}
}
bool unfinishedComment = (commentEnd == -1 && commentStart >= 0);
return hasLocal && hasDomain && valid && !unfinishedComment;
}
}
}
正如在许多回答中提到的,电子邮件地址的领域是复杂的。在这种情况下,我强烈反对使用正则表达式。那些匹配(大多数)用例的异常复杂,难以读取,因此也难以维护。此外,它们仍然难以支持所有病例,而且速度缓慢。
微软的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);
}
老实说,在产品代码中,我所做的最好的事情就是检查@符号。
我从来没有在一个地方完全验证电子邮件。你知道我怎么判断它是否有效吗?如果发送出去了。如果没有,那就糟了,如果有,生活就好了。这就是我需要知道的。
/使用内部Regex在.Net4.5 >>>中创建“new EmailAddressAttribute();”组件,使用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
推荐文章
- LINQ读取XML
- 如何强制LINQ Sum()返回0而源集合是空的
- 将值附加到查询字符串
- Selenium c# WebDriver:等待元素出现
- 我如何添加双引号的字符串,是在一个变量?
- 检查字符串是否包含字符串列表中的元素
- 最好的方法在asp.net强制https为整个网站?
- 将字符串转换为System.IO.Stream
- 如何从枚举中选择一个随机值?
- 驻留在App_Code中的类不可访问
- 在链式LINQ扩展方法调用中等价于'let'关键字的代码
- dynamic (c# 4)和var之间的区别是什么?
- Visual Studio: ContextSwitchDeadlock
- 返回文件在ASP。Net Core Web API
- 自定义HttpClient请求头