【问题标题】:C# Email Address validationC# 电子邮件地址验证
【发布时间】:2011-06-23 04:33:02
【问题描述】:

我只想澄清一件事。根据客户请求,我们必须创建一个正则表达式,以允许在电子邮件地址中使用撇号。

我的问题根据 RFC 标准,电子邮件地址会包含撇号吗?如果是这样,如何重新创建正则表达式以允许撇号

【问题讨论】:

标签: c# .net asp.net regex validation


【解决方案1】:

下面的正则表达式实现了电子邮件地址的官方RFC 2822 标准。不建议在实际应用中使用此正则表达式。它说明了使用正则表达式时,总是需要在精确和实用之间进行权衡。

(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])

您可以使用简化的:

[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?

是的,电子邮件中允许使用撇号,只要它不在域名中。

【讨论】:

  • RFC 2822 已被 RFC 5322(标准草案)取代。
【解决方案2】:

这是我写的验证属性。它验证几乎所有“原始”电子邮件地址,即 local-part@*domain* 形式的电子邮件地址。它不支持 RFC 允许的任何其他、更具...创造性的构造(此列表无论如何都不全面):

  • cmets(例如,jsmith@whizbang.com (work)
  • 带引号的字符串(转义文本,以允许原子中不允许的字符)
  • 域文字(例如foo@[123.45.67.012]
  • bang-paths(又名源路由)
  • 角度地址(例如John Smith <jsmith@whizbang.com>
  • 折叠空格
  • local-partdomain 中的双字节字符(仅限 7 位 ASCII)。

它应该接受几乎任何可以这样表达的电子邮件地址

  • foo.bar@bazbat.com

无需使用引号 (")、尖括号 ('') 或方括号 ([])。

未尝试验证 中最右侧的 dns 标签是否为有效的 TLD(顶级域)。这是因为现在的顶级域名列表远远大于“六大”(.com、.edu、.gov、.mil、.net、.org)加上两个字母的 ISO 国家代码。 ICANN actually updates the TLD list daily,尽管我怀疑该列表实际上并没有每天更改。此外,ICANN just approved a big expansion of the generic TLD namespace)。有些电子邮件地址没有您认为的 TLD(您知道postmaster@. 在理论上是有效且可邮寄的吗?发到该地址的邮件应该被递送到 DNS 根区域的邮递员。)

扩展正则表达式以支持域文字,应该不会太难。

给你。身体健康使用它:

using System;
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;

namespace ValidationHelpers
{
  [AttributeUsage( AttributeTargets.Property | AttributeTargets.Field , AllowMultiple = false )]
  sealed public class EmailAddressValidationAttribute : ValidationAttribute
  {
    static EmailAddressValidationAttribute()
    {
      RxEmailAddress = CreateEmailAddressRegex();
      return;
    }

    private static Regex CreateEmailAddressRegex()
    {
      // references: RFC 5321, RFC 5322, RFC 1035, plus errata.
      string atom             = @"([A-Z0-9!#$%&'*+\-/=?^_`{|}~]+)"                 ;
      string dot              = @"(\.)"                                            ;
      string dotAtom          =  "(" + atom + "(" + dot + atom + ")*" + ")"        ;
      string dnsLabel         = "([A-Z]([A-Z0-9-]{0,61}[A-Z0-9])?)"                ;
      string fqdn             = "(" + dnsLabel + "(" + dot + dnsLabel + ")*" + ")" ;

      string localPart        = "(?<localpart>" + dotAtom + ")"      ;
      string domain           = "(?<domain>" + fqdn + ")"            ;
      string emailAddrPattern = "^" + localPart + "@" + domain + "$" ;

      Regex instance = new Regex( emailAddrPattern , RegexOptions.Singleline | RegexOptions.IgnoreCase );
      return instance;
    }

    private static Regex RxEmailAddress;

    public override bool IsValid( object value )
    {
      string s      = Convert.ToString( value ) ;
      bool   fValid = string.IsNullOrEmpty( s ) ;

      // we'll take an empty field as valid and leave it to the [Required] attribute to enforce that it's been supplied.
      if ( !fValid )
      {
        Match m = RxEmailAddress.Match( s ) ;

        if ( m.Success )
        {
          string emailAddr              = m.Value ;
          string localPart              = m.Groups[ "localpart" ].Value ;
          string domain                 = m.Groups[ "domain"    ].Value ;
          bool   fLocalPartLengthValid  = localPart.Length >= 1 && localPart.Length <=  64 ;
          bool   fDomainLengthValid     = domain.Length    >= 1 && domain.Length    <= 255 ;
          bool   fEmailAddrLengthValid  = emailAddr.Length >= 1 && emailAddr.Length <= 256 ; // might be 254 in practice -- the RFCs are a little fuzzy here.

          fValid = fLocalPartLengthValid && fDomainLengthValid && fEmailAddrLengthValid ;

        }
      }

      return fValid ;
    }

  }
}

干杯!

【讨论】:

  • 我不知道这是否正确,但您“展示您的工作”并展示正则表达式的组成方式(来自电子邮件地址的 CFG?)真的很有帮助。
猜你喜欢
  • 2014-06-12
  • 1970-01-01
  • 2013-03-25
  • 2018-03-13
  • 2011-09-02
  • 2013-02-20
  • 2014-03-12
  • 1970-01-01
  • 2010-11-24
相关资源
最近更新 更多