简体   繁体   中英

What is the correct design pattern to implement email validation for each provider?

I have to validate email through several validators. I have class( EmailValidator ) that has list of validators( RegexValidator , MXValidator ...) and it validates email through that validators. RegexValidator , for example, has its own validators for each provider. If it recognizes that this is gmail , so it check if it match specific pattern, if it is mygmail , so it checks if it match mygmail's pattern otherwize it return true. MXValidator will validates something else.

What is the correct design pattern to implement this?

public interface IValidator
{
   bool Validate(string email);
}
public class RegexValidator : IValidator
    {
        private const string EMAIL_REGEX = @"\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b";
        public bool Validate(string email)
        {
            var regex = new Regex(EMAIL_REGEX);
            var isEmailFormat regex.IsMatch(email);
            if(isEmailFormat)
            {
                 //here it should recognize the provider and check if it match the provider's pattern
            }

            return true;
        }
    }

Chain of Responsibility.

As soon as one validator finds invalid pattern, returns false. You pass an ordered list of validators.

bool ValidateEmail(string email, IEnumerable<IValidator> validators, ref errorMessage)
{
    return !validators.Any(v => !v.Validate(email, ref errorMessage);
}

Assuming

interface IValidator
{
    bool Validate(object value, ref errorMessage);
}

UPDATE

I see this implemented as another validator:

public class EmailDomainValidator : IValidator
{

   public EmailDomainValidator(string domain)
   {
      _domain = domain;
   }

   ...
}

It's not a direct answer to your problem but I think that you are doing it wrong.

The real validation of an email is not based on his string representation, but with a simple test. You send a mail, someone answer, the mail is good. Otherwise it's bad.

You have an infinity of valid mail address that are not valid in the real world because they are not related to a mailbox.

Maybe you are already aware of that and it's your job to do this thing, but if it's not, I suggest you to make a really simple and permissive Regex like:

(?<=[\w-\.@]+@)[\w-\.]+

Wich will show you only the part after the @ and will contains a lot of false positive that you can test easily.


About the chaining the validators, I'll make a List<Func<string,bool>> wich contains all the tests and call all them in a foreach loop, throwing and catching an exception in case of false.

EDIT: in fact, the LINQ method with a lambda is far better. Throwing an exception is expensive.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM