【问题标题】:System.Net.MailMessage allows some invalid email address formatsSystem.Net.MailMessage 允许一些无效的电子邮件地址格式
【发布时间】:2014-11-14 08:20:11
【问题描述】:

正如许多人可能已经意识到的那样,正确验证电子邮件地址可能是一场噩梦。您可以整天搜索符合当前 RFC 标准的 C# 正则表达式,您会发现不同的正则表达式会给出不同的结果。

如果您查看http://en.wikipedia.org/wiki/Email_address#Local_part,您会发现不允许在本地部分的开头或结尾使用句点。两个连续的时期也是不允许的。但是,以下 NUnit 测试证明 System.Net.MailMessage 允许您为某些无效的电子邮件地址格式实例化 MailMessage 对象。

[Test]
[TestCase(@"foobar@exampleserver")] //technically valid from the wiki article
[TestCase(@"jsmith@[192.168.2.1]")] //technically valid from the wiki article
[TestCase(@"niceandsimple@example.com")] //vanilla email address
[TestCase(@"very.common@example.com")] //also standard
[TestCase(@"a.little.lengthy.but.fine@dept.example.com")] //long with lots of periods
[TestCase(@"disposable.style.email.with+symbol@example.com")] //disposable with the + symbol
[TestCase(@"other.email-with-dash@example.com")] //period and dash in local part
[TestCase(@"user-test-hyphens@example-domain.com")] //lots of hyphens
[TestCase(@"!#$%&'*+-/=?^_`{|}~@example-domain.com")] //all these symbols are allowed in local part
[TestCase(@"ër_%لdev@gكňil.com")] //characters outside the ascii range are permitted
[TestCase(@"""abcdefghixyz""@example.com")] //technically valid
//[TestCase(@"abc.""defghi"".xyz@example.com")] //technically valid, but .NET throws exception
public void CanCreateMailMessageObjectTest(string emailAddress)
{
     var mailMessage = new System.Net.Mail.MailMessage("noreply@example.com", emailAddress);  
}

除最后一个测试用例外,上述所有测试用例均通过。

[Test]
[TestCase(@".test@example.com")] //leading period
[TestCase(@"test.@example.com")] //period at end of local part <---FAIL
[TestCase(@"test..example@example.com")] //double period in local part <---FAIL
[TestCase(@"foobar@example!#$%^&*()=server.com")] //special characters in domain part
[TestCase(@"Abc.example.com")] //No @ separating local and domain part
[TestCase(@"A@b@c@example.com")] //more than one @ symbol
[TestCase(@"just""not""right@example.com")] //quoted strings must be dot separated
[TestCase(@"a""b(c)d,e:f;g<h>i[j\k]l@example.com")] //special symbols "(),:;<>@[\] not inside quotes
[TestCase(@"[test@example.com")] //leading special symbol in local part
[TestCase(@"this is""not\allowed@example.com")] //spaces not in quotes
[TestCase(@"this\ still\""not\\allowed@example.com")] //backslashes not in quotes
[ExpectedException(typeof (System.FormatException))]
public void CannotCreateMailMessageObjectTest(string emailAddress)
{
    var mailMessage = new System.Net.Mail.MailMessage("noreply@example.com", emailAddress);
}

到底为什么test.@example.comtest..example@example.com 无法抛出 System.FormatException?谁错了,微软还是维基百科?是否有任何电子邮件地址允许使用尾随句点或双句点?我的验证应该允许他们吗?我有适当的异常处理,以允许我的电子邮件递送服务在发生异常时继续进行,但我想丢弃无效或保证会抛出异常的电子邮件地址。

【问题讨论】:

    标签: c# .net regex email-validation rfc


    【解决方案1】:

    没有解释原因,但MSDN's docs on System.Net.Mail.MailAddress 表示支持这种地址格式:

    MailAddress 类支持以下邮件地址格式:

    ...

    • 用户名中的连续点和尾随点。例如,用户...名称..@host。

    所以这不是 MailAddress 类中的错误 - 明确支持该形式。但我不知道支持他们的原因是什么。我假设也许某些系统实际上接受了它们,并且 MS 觉得有必要支持这种情况。

    另一方面,虽然我可以理解提供一些电子邮件地址验证的必要性,但我个人认为在验证方面几乎不需要非常严格。无论如何,系统都需要处理错误但在语法上有效的地址。另一方面,似乎本地部分末尾的双倍句点或句点可能是一个常见的错字,所以我可以理解为什么您可能希望它们验证失败。

    【讨论】:

    • “可能是一个常见的错字” --> 没错。因为这个原因,我辜负了他们。我主要只是想让地址失败,a)明显无效,或者 b)我知道不会被传递,因为 MailAddress/MailMessage 抛出异常(我处理,但仍然......)。
    【解决方案2】:

    好吧,既然 RFC 定义了标准,那么微软的实现就是不正确的。

    如果您想进行更好的验证,请尝试validator I posted in this answer 到问题C# Email Address validation

    它应该正确(并且严格)验证您可能遇到的几乎所有格式为 local-part@domain 的“正常”电子邮件地址,但它不会处理新的非允许的 ASCII 样式的东西。我不保证自几年前就没有出现过一点点腐烂,并且电子邮件 RFC 在我编写后已经更新。

    local-part 必须不带引号:它不支持带引号的本地部分或带引号的标签。

    就域部分而言,我的验证器不支持 IPv4 或 IPv6 文字(尽管添加它并不难)。

    如果您想允许任何/所有符合 RFC 的地址,这将变得更加困难。

    【讨论】:

    • 感谢您发布 3 1/2 年前的解决方案,但这并不是我真正想要的。我可以从 FluentValidation 和 Microsoft 获得正则表达式,也可以自己编写,但问题是它们都是不同的。这篇文章不要求使用正则表达式,而是质疑为什么 MailMessage 不会引发 FormatException。
    猜你喜欢
    • 2015-01-23
    • 1970-01-01
    • 2012-05-28
    • 2022-08-21
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    相关资源
    最近更新 更多