为啥 MailAddress 认为 'john@gmail.'是有效的电子邮件地址吗?
Posted
技术标签:
【中文标题】为啥 MailAddress 认为 \'john@gmail.\'是有效的电子邮件地址吗?【英文标题】:Why does MailAddress think 'john@gmail.' is a valid email address?为什么 MailAddress 认为 'john@gmail.'是有效的电子邮件地址吗? 【发布时间】:2011-11-02 15:45:53 【问题描述】:像一个优秀的 C# 用户一样,我使用 MailAddress
对象来验证电子邮件地址。
我的一个客户为他的电子邮件输入了john@gmail.
,该电子邮件由MailAddress
验证,并破坏了我的软件。我希望下面的代码会引发异常,但事实并非如此。
static void Main(string[] args)
string addressmail = string.Empty;
try
MailAddress mail = new MailAddress(@"john@gmail.");
addressmail = mail.Address;
catch (FormatException)
// address is invalid
// address is valid
Console.WriteLine(addressmail);
你知道如何捕捉这种虚假的邮件地址吗?
【问题讨论】:
它对我来说失败了,..oops 你实际上是指单引号内的值 为什么不正常验证正则表达式中的电子邮件地址? @V4Vendetta 我在.NET 4.O,你使用哪个框架? @Ofer Zelig:正如 jwz 所说:开发人员有问题。他想:让我们用正则表达式吧!现在,开发人员遇到了两个问题...... @Ofer:没有人要求正则表达式。请在 Vinzz 链接的问题中使用正则表达式阅读反对的要点。 【参考方案1】:我认为在这种情况下,MS 对有效电子邮件地址的实现是不正确的,至少按照 RFC822。我还没有真正尝试过你的代码,所以我假设它按照你说的那样做。
还有其他方法可以验证电子邮件地址,例如实际连接到 SMTP 服务器并要求它确认地址有效(如 here 和 here 所述)。如果不这样做,您总会遇到一些麻烦。就个人而言,我认为根据某些规范(除了我们可以使用的快速检查;例如您的代码)花太多时间验证电子邮件地址是不值得的 - 真正的测试是该地址是否收到电子邮件如果你发送它。一个简单的电子邮件验证可以确认这一点,虽然我知道这可能并不适用于所有情况,但在这些情况下,你不走运。
【讨论】:
嗯,这是最合理的方法。也就是说,考虑到 .NET 的成熟度,我对这个实现感到有些失望 M$ 执行 some normalization 可能没有帮助,具体取决于您的使用方式。【参考方案2】:MailAddress 类型对验证电子邮件地址的支持非常有限,并且从 .NET 4.0 开始,不支持大多数相关的 IETF 标准。如果您需要验证电子邮件地址的语法,可能不使用正则表达式,我建议您查看 EmailVerify.NET,这是一个支持所有当前标准(RFC 1123、RFC 2821、RFC 2822、RFC 3696、RFC 4291、RFC 5321 和 RFC 5322)。如果您需要,该组件甚至允许对地址执行额外的测试,包括 DNS、SMTP 和邮箱检查。
EmailVerify.NET 网站:http://cobisi.com/email-validation/.net-component 在线演示:http://cobisi.com/email-validation/validate-address免责声明:我是该产品的首席开发人员。
【讨论】:
感谢您的提示,这对我当前的项目来说太过分了,但绝对是要记住的一个组件。 一次性电子邮件地址验证...这很淘气 ;o) 一个不错的功能,我必须承认。 :) 对于那些想知道的人,disposable email addresses 是由许多提供商(包括 filtzmail、10minutemail、mailinator、despam 等)生成的临时电子邮件地址的官方名称。 EmailVerify.NET 可以轻松检测到这种地址。【参考方案3】:不知何故修复了版本,混合了 MailAddress 和一个简单的正则表达式来验证主机:
静态正则表达式,由 SLaks 建议
private static readonly Regex hostReg = new Regex(@"(\w+)\.(\w+)");
public bool IsMailAddress(string addParam)
try
MailAddress mail = new MailAddress(addParam);
string address = mail.Address;
//not handled by MailAdress, which is a shame
return hostReg.IsMatch(mail.Host);
catch (FormatException)
//address is invalid
return false;
catch (Exception)
return false;
【讨论】:
您应该将正则表达式缓存在static readonly
字段中。此外,a@b
是有效的(虽然很少使用);检查!mail.Host.EndsWith(".")
可能会更好。
a@b ?哦,我的,多么规范...感谢您的投入!
我的一个错误输入是“john@gmail”,所以我会坚持使用正则表达式,希望我的客户不会太古怪。
我什至不确定a@b.
是否真的无效。 (我还没有阅读规范)
a@b.
在技术上是有效的(虽然通常是错字),但MailAddress
解析器肯定仍然存在问题:a @a.b
将 返回 true
上面的函数,因为它标准化为a@a.b
。但是,如果您在保存字符串时没有new MailAddress(...).Address
,那么您最终会得到一个不是有效电子邮件地址的东西。 M$ 解释为具有DisplayName
的字符串也会发生类似的情况:例如,试试a a@a.b
。【参考方案4】:
MailboxValidator 有一个免费的 API 供您使用。只需在 http://www.mailboxvalidator.com/plans#api 注册免费 API 计划,集成部分就非常简单,因为他们还有一个 C# 类 http://www.mailboxvalidator.com/dotnet 供您包装 API 调用。
C#类代码在https://github.com/MailboxValidator/mailboxvalidator-csharp
要通过 NuGet (https://www.nuget.org/packages/MailboxValidator.SingleValidation/) 安装 MailboxValidator SingleValidation 类,请在包管理器控制台中运行以下命令:
Install-Package MailboxValidator.SingleValidation
然后你可以像下面这样使用类:
using System;
using System.Windows.Forms;
using MailboxValidator;
namespace TestMailboxValidatorCSharp
public class TestMailboxValidatorCSharp
static void Main(string[] args)
var mbv = new SingleValidation("PASTE_YOUR_API_KEY_HERE");
String results = "";
try
MBVResult rec = mbv.ValidateEmail("example@example.com");
if (rec.ErrorCode == "")
results += "email_address: " + rec.EmailAddress + "\n";
results += "domain: " + rec.Domain + "\n";
results += "is_free: " + rec.IsFree + "\n";
results += "is_syntax: " + rec.IsSyntax + "\n";
results += "is_domain: " + rec.IsDomain + "\n";
results += "is_smtp: " + rec.IsSMTP + "\n";
results += "is_verified: " + rec.IsVerified + "\n";
results += "is_server_down: " + rec.IsServerDown + "\n";
results += "is_greylisted: " + rec.IsGreylisted + "\n";
results += "is_disposable: " + rec.IsDisposable + "\n";
results += "is_suppressed: " + rec.IsSuppressed + "\n";
results += "is_role: " + rec.IsRole + "\n";
results += "is_high_risk: " + rec.IsHighRisk + "\n";
results += "is_catchall: " + rec.IsCatchall + "\n";
results += "mailboxvalidator_score: " + rec.MailboxValidatorScore + "\n";
results += "time_taken: " + rec.TimeTaken + "\n";
results += "status: " + rec.Status + "\n";
results += "credits_available: " + rec.CreditsAvailable + "\n";
else
results += "error_code: " + rec.ErrorCode + "\n";
results += "error_message: " + rec.ErrorMessage + "\n";
results += "version: " + rec.Version + "\n";
MessageBox.Show(results);
catch (Exception ex)
MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
【讨论】:
【参考方案5】:MailAddress 尝试与已废弃 RFC822 的 RFC2822 兼容。当您阅读 MailAddress 的源代码时,您会看到它被接受的结束点只是为了与某些电子邮件客户端兼容。 使用正则表达式验证电子邮件地址不是正确的做法(参见 RFC2822),最好的方法是实现解析器,就像 MailAddress 所做的那样。
see DotAtomReader used by MailAddressParser
【讨论】:
【参考方案6】:不是免费的解决方案,但Cobisi's email validation library 可以在不同的准确度级别(语法、IspSpecificSyntax、DeaDomain、Dns、DeaMailExchanger、Smtp、邮箱、CatchAll)内判断电子邮件是否有效
var engine = new VerificationEngine();
var result = engine.Run("john@example.com",
VerificationLevel.Mailbox).Result;
if (result.LastStatus == VerificationStatus.Success)
// TODO: Show a message box with the great news
免责声明:我与公司或项目无关。
【讨论】:
以上是关于为啥 MailAddress 认为 'john@gmail.'是有效的电子邮件地址吗?的主要内容,如果未能解决你的问题,请参考以下文章
检查电子邮件地址是不是对 System.Net.Mail.MailAddress 有效