C#电子邮件地址验证

时间:2011-06-23 04:33:03

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

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

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

2 个答案:

答案 0 :(得分:5)

下面的正则表达式实现了电子邮件地址的官方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])?

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

答案 1 :(得分:3)

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

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

它应该接受几乎所有可以表达的电子邮件地址

  • foo.bar@bazbat.com

无需使用引号("),尖括号('&lt;&gt;')或方括号([])。

未尝试验证中最右侧的dns标签是否为有效TLD(顶级域)。这是因为TLD列表现在比“大6”(.com,.edu,.gov,.mil,.net,.org)加上2个字母的ISO国家/地区代码要大得多。 ICANN actually updates the TLD list daily,虽然我怀疑列表实际上并没有每天都在变化。此外,ICANN just approved a big expansion of the generic TLD namespace)。并且某些电子邮件地址没有您认可的TLD(您是否知道postmaster@.理论上有效且可邮寄?该地址的邮件应该传递给DNS根区域的邮局主管。)< / p>

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

你走了。使用它健康:

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 ;
    }

  }
}

干杯!