Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EmailAddressAttribute incorrectly categorizing French e-mail address as invalid

I'm using the EmailAddressAttribute for use on my model.

The problem is when I use a (perfectly valid) e-mail address of

ó[email protected]

it says it is invalid.

Model:

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

Is this an issue with the attribute, or do I somehow have to specify that French e-mails are okay?

Input box as rendered:

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

I've also extracted the regex from the client-side validation, the following line returns 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( 'ó[email protected]' );

which apparently complies with this standard even though the demo for this exact code also fails.

like image 220
m.edmondson Avatar asked Feb 10 '17 16:02

m.edmondson


3 Answers

You need to set custom regular expression for email validation in jQuery Validation Plugin:

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

jQuery Validation Plugin uses RFC 5322 Internet Message Protocol specification definition of a valid email. This definition disallows use of a non latin letters in local-part. Relevant excerpt from project's README.md:

IMPORTANT NOTE ABOUT EMAIL VALIDATION. As of version 1.12.0 this plugin is using the same regular expression that the HTML5 specification suggests for browsers to use. We will follow their lead and use the same check. If you think the specification is wrong, please report the issue to them. If you have different requirements, consider using a custom method. In case you need to adjust the built-in validation regular expression patterns, please follow the documentation.

Email address internationalization is defined by another specification - RFC 6530 Overview and Framework for Internationalized Email. It uses term SMTPUTF8. Check Email address page on Wikipedia for more information and support details.

like image 83
Leonid Vasilev Avatar answered Nov 14 '22 09:11

Leonid Vasilev


As you can see in the regex:

/^[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( 'ó[email protected]' );

the ó character is not in the range

you can use the following regex:

/^[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 àâäèéêëîïóôœùûüÿçÀÂÄÈÉÊËÎÏÔŒÙÛÜŸÇ.!#$%&'*+\/=?^_`{|}~-])?)*$/

And you can also creat a custom Attribute as FrenchEmailAddress in order to validate the property by using the regex I posted in the custom attribute

[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);
    }
}
like image 28
gwt Avatar answered Nov 14 '22 08:11

gwt


Context of the problem is very important to identifying the correct answer. In most scenarios, it is better to stick with the simple solution:

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

This regex will run the risk of matching some invalid email addresses, but will enforce the general structure. Ideally you would be able to an email confirmation box or a confirmation email perform a second round of validation, but even without the additional validations, this should still catch the majority of unintentionally invalid entries.

like image 1
user942620 Avatar answered Nov 14 '22 08:11

user942620