EmailAddressAttribute 错误地将法国电子邮件地址分类为无效

Posted

技术标签:

【中文标题】EmailAddressAttribute 错误地将法国电子邮件地址分类为无效【英文标题】:EmailAddressAttribute incorrectly categorizing French e-mail address as invalid 【发布时间】:2017-06-29 02:32:57 【问题描述】:

我在我的模型上使用EmailAddressAttribute。

问题是当我使用

的(完全有效的)电子邮件地址时
óscar@yahoo.com

它说它是无效的。

型号:

public class ForgotPasswordViewModel

    [Required]
    [EmailAddress]
    [Display(Name = "Email")]
    public string Email  get; set; 

    public CmsContentPagesModel PageCmsContent  get; set; 

    public CmsContentPagesModel PageCmsContentInfoIcon  get; set; 
    public CmsContentPagesModel PageCmsContentRightPanel  get; set; 

这是属性的问题,还是我必须以某种方式指定法语电子邮件是否正常?

渲染的输入框:

<div class="col-md-5">
     <input class="form-control" data-val="true" data-val-email="The Email field is not a valid e-mail address." data-val-required="The Email field is required." id="Email" name="Email" type="text" value="" />
     <span class="field-validation-valid text-danger" data-valmsg-for="Email" data-valmsg-replace="true"></span>
</div>

我还从客户端验证中提取了正则表达式,以下行返回 false

/^[a-zA-Z0-9.!#$%&'*+\/=?^_`|~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]0,61[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]0,61[a-zA-Z0-9])?)*$/.test( 'óscar@yahoo.com' );

这显然符合this standard,即使这个确切的code also fails 的演示。

【问题讨论】:

EmailAddressAttribute 使用以下正则表达式来验证值:source。您提供的电子邮件地址与正则表达式匹配,因此它应该是有效的。你可以发布c#模型吗?顺便说一句,我最近写了一篇关于validating email address .NET的博文 @meziantou - 好消息,我已经添加了模型。 查看这个帖子:***.com/questions/12180753/… 但是客户端表达式使用纯 ASCII 范围 a-zA-Z 这似乎是一个错误。 @m.edmondson 规范中提到的 Unicode 无关紧要。检查这个specification issue。 【参考方案1】:

您需要在 jQuery Validation Plugin 中为电子邮件验证设置自定义正则表达式:

$.validator.methods.email = function( value, element ) 
  return this.optional( element ) || /INSERT_YOUR_REGEX_HERE/.test( value );

jQuery 验证插件使用RFC 5322 Internet Message Protocol specification 定义有效电子邮件。此定义不允许在本地部分中使用非拉丁字母。项目README.md的相关摘录:

关于电子邮件验证的重要说明。 从 1.12.0 版开始,此 插件使用与html5 specification suggests for browsers to use 相同的正则表达式。我们将跟随他们的脚步 并使用相同的检查。如果您认为规范有误, 请向他们报告问题。如果您有不同的要求, 考虑using a custom method。如果您需要调整 内置验证正则表达式模式,请follow the documentation。

电子邮件地址国际化由另一个规范定义 - RFC 6530 Overview and Framework for Internationalized Email。它使用术语 SMTPUTF8。查看 Wikipedia 上的 Email address page 了解更多信息和支持详情。

【讨论】:

我使用了这个并使用了EmailAddressAttribute在服务器上使用的正则表达式,所以我可以确定客户端+服务器会同意。此外,我启动了一个错误over on the project,因此至少相关人员都知道。这个答案的优雅,意味着我可以将代码与原始文件一起包含在一个新的 .js 文件中,这就是我授予这个赏金的原因。非常感谢@Leonid Vesilyev,继续努力。【参考方案2】:

正如您在正则表达式中看到的:

/^[a-zA-Z0-9.!#$%&'*+\/=?^_`|~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]0,61[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]0,61[a-zA-Z0-9])?)*$/.test( 'óscar@yahoo.com' );

ó 字符不在范围内

您可以使用以下正则表达式:

/^[a-zA-Z0-9 àâäèéêëîïóôœùûüÿçÀÂÄÈÉÊËÎÏÔŒÙÛÜŸÇ.!#$%&'*+\/=?^_`|~-]+@[a-zA-Z0-9 àâäèéêëîïóôœùûüÿçÀÂÄÈÉÊËÎÏÔŒÙÛÜŸÇ.!#$%&'*+\/=?^_`|~-](?:[a-zA-Z0-9 àâäèéêëîïóôœùûüÿçÀÂÄÈÉÊËÎÏÔŒÙÛÜŸÇ.!#$%&'*+\/=?^_`|~-]0,61[a-zA-Z0-9 àâäèéêëîïóôœùûüÿçÀÂÄÈÉÊËÎÏÔŒÙÛÜŸÇ.!#$%&'*+\/=?^_`|~-])?(?:\.[a-zA-Z0-9 àâäèéêëîïóôœùûüÿçÀÂÄÈÉÊËÎÏÔŒÙÛÜŸÇ.!#$%&'*+\/=?^_`|~-](?:[a-zA-Z0-9 àâäèéêëîïóôœùûüÿçÀÂÄÈÉÊËÎÏÔŒÙÛÜŸÇ.!#$%&'*+\/=?^_`|~-]0,61[a-zA-Z0-9 àâäèéêëîïóôœùûüÿçÀÂÄÈÉÊËÎÏÔŒÙÛÜŸÇ.!#$%&'*+\/=?^_`|~-])?)*$/

您还可以创建一个自定义属性作为 FrenchEmailAddress,以便使用我在自定义属性中发布的正则表达式来验证属性

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class FrenchEmailAddressAttribute : ValidationAttribute

    public string Pattern  get; set; 
    public RegexOptions Options  get; set; 

    public FrenchEmailAddressAttribute(string pattern, RegexOptions options = RegexOptions.None)
    
        Pattern = pattern;
        Options = options;
    

    public override bool IsValid(object value)
    
        return IsValid(value as string);
    

    public bool IsValid(string value)
    
        return string.IsNullOrEmpty(value) ? true : new Regex(Pattern, Options).IsMatch(value);
    

【讨论】:

您也必须更改其他 A-Z 范围。 @HenkHolterman 感谢提及,我编辑了我的答案【参考方案3】:

问题的上下文对于确定正确答案非常重要。在大多数情况下,最好还是坚持简单的解决方案:

^\S+@\S+\.\S+$

此正则表达式会冒匹配某些无效电子邮件地址的风险,但会强制执行一般结构。理想情况下,您可以通过电子邮件确认框或确认电子邮件执行第二轮验证,但即使没有额外的验证,这仍应捕获大多数无意中无效的条目。

【讨论】:

【参考方案4】:

System.ComponentModel.DataAnnotations.EmailAddressAttribute 类使用这个正则表达式。

const string pattern = @"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`\|~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`\|~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$";

并像@ThomasRainero 所说的那样验证您的电子邮件地址

【讨论】:

【参考方案5】:

我不知道您如何验证电子邮件地址,我尝试像字符串一样验证您的电子邮件,而我的变量 isValid 已通过 true 验证。

EmailAddressAttribute testEmailAddress = new EmailAddressAttribute();
bool isValid = testEmailAddress.IsValid("óscar@yahoo.com");

希望这些有用。

【讨论】:

@MarcelN.:这是问题扩展之前的有效非重复声明。

以上是关于EmailAddressAttribute 错误地将法国电子邮件地址分类为无效的主要内容,如果未能解决你的问题,请参考以下文章

允许 EmailAddressAttribute 为空字符串

EmailAddressAttribute 允许在末尾添加点

为啥 EmailAddressAttribute.IsValid 和 MailAddress 认为包含“ª”的电子邮件是有效的? [复制]

针对无效字符验证电子邮件地址

接口错误地扩展接口

算术错误:Python 错误地划分变量