为啥 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.'是有效的电子邮件地址吗?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以通过 MailAddress 类进行 XSS?

检查电子邮件地址是不是对 System.Net.Mail.MailAddress 有效

MailAddress 构造函数中的多个地址

相对于 mailAddress 类,Regex 是不是稳定用于电子邮件验证?

Vue-邮箱正则验证

为啥if认为这里有文件