验证字符串是否是有效的电子邮件地址的最优雅的代码是什么?
当前回答
我发现这个正则表达式在检查@标记以外的东西和接受奇怪的边缘情况之间是一个很好的权衡:
^[^@\s]+@[^@\s]+(\.[^@\s]+)+$
它至少会让你在@标记周围放一些东西,并且至少放一个正常的域。
其他回答
我写了一个函数来检查电子邮件是否有效。在大多数情况下,这似乎对我很有效。
结果:
dasddas-@.com => FALSE
-asd@das.com => FALSE
as3d@dac.coas- => FALSE
dsq!a?@das.com => FALSE
_dasd@sd.com => FALSE
dad@sds => FALSE
asd-@asd.com => FALSE
dasd_-@jdas.com => FALSE
asd@dasd@asd.cm => FALSE
da23@das..com => FALSE
_dasd_das_@9.com => FALSE
d23d@da9.co9 => TRUE
dasd.dadas@dasd.com => TRUE
dda_das@das-dasd.com => TRUE
dasd-dasd@das.com.das => TRUE
代码:
private bool IsValidEmail(string email)
{
bool valid = false;
try
{
var addr = new System.Net.Mail.MailAddress(email);
valid = true;
}
catch
{
valid = false;
goto End_Func;
}
valid = false;
int pos_at = email.IndexOf('@');
char checker = Convert.ToChar(email.Substring(pos_at + 1, 1));
var chars = "qwertyuiopasdfghjklzxcvbnm0123456789";
foreach (char chr in chars)
{
if (checker == chr)
{
valid = true;
break;
}
}
if (valid == false)
{
goto End_Func;
}
int pos_dot = email.IndexOf('.', pos_at + 1);
if(pos_dot == -1)
{
valid = false;
goto End_Func;
}
valid = false;
try
{
checker = Convert.ToChar(email.Substring(pos_dot + 1, 1));
foreach (char chr in chars)
{
if (checker == chr)
{
valid = true;
break;
}
}
}
catch
{
valid = false;
goto End_Func;
}
Regex valid_checker = new Regex(@"^[a-zA-Z0-9_@.-]*$");
valid = valid_checker.IsMatch(email);
if (valid == false)
{
goto End_Func;
}
List<int> pos_list = new List<int> { };
int pos = 0;
while (email.IndexOf('_', pos) != -1)
{
pos_list.Add(email.IndexOf('_', pos));
pos = email.IndexOf('_', pos) + 1;
}
pos = 0;
while (email.IndexOf('.', pos) != -1)
{
pos_list.Add(email.IndexOf('.', pos));
pos = email.IndexOf('.', pos) + 1;
}
pos = 0;
while (email.IndexOf('-', pos) != -1)
{
pos_list.Add(email.IndexOf('-', pos));
pos = email.IndexOf('-', pos) + 1;
}
int sp_cnt = pos_list.Count();
pos_list.Sort();
for (int i = 0; i < sp_cnt - 1; i++)
{
if (pos_list[i] + 1 == pos_list[i + 1])
{
valid = false;
break;
}
if (pos_list[i]+1 == pos_at || pos_list[i]+1 == pos_dot)
{
valid = false;
break;
}
}
if(valid == false)
{
goto End_Func;
}
if (pos_list[sp_cnt - 1] == email.Length - 1 || pos_list[0] == 0)
{
valid = false;
}
End_Func:;
return valid;
}
老实说,在产品代码中,我所做的最好的事情就是检查@符号。
我从来没有在一个地方完全验证电子邮件。你知道我怎么判断它是否有效吗?如果发送出去了。如果没有,那就糟了,如果有,生活就好了。这就是我需要知道的。
public bool IsValidEmail(string email)
{
try
{
var addr = new System.Net.Mail.MailAddress(email);
return addr.Address == email;
}
catch
{
return false;
}
}
我将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);
}
我根据维基百科的规则和样本地址创建了一个电子邮件地址验证程序。对于那些不介意多看一点代码的人,这里。说实话,我不知道电子邮件地址规范中有这么多疯狂的规则。我没有完全验证主机名或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;
}
}
}
推荐文章
- 实体框架核心:在上一个操作完成之前,在此上下文中开始的第二个操作
- 如何为构造函数定制Visual Studio的私有字段生成快捷方式?
- 如何使用JSON确保字符串是有效的JSON。网
- AppSettings从.config文件中获取值
- 通过HttpClient向REST API发布一个空体
- 如何检查IEnumerable是否为空或空?
- 自动化invokerrequired代码模式
- 在c#代码中设置WPF文本框的背景颜色
- 在c#中,什么是单子?
- c#和Java中的泛型有什么不同?和模板在c++ ?
- c#线程安全快速(est)计数器
- 如何将此foreach代码转换为Parallel.ForEach?
- 如何分裂()一个分隔字符串到一个列表<字符串>
- 如何转换列表<字符串>列表<int>?
- c#对象列表,我如何得到一个属性的和