TL;DR
Don't use regexes for validating emails, unless you have a good reason to use them. Use a verification mail instead. In most cases, a regex that simply checks that the string contains an @ is enough.
Short version
In most cases, the question "How do I validate an email address with a regex" is an XY-problem because it's most likely not the solution to your actual problem. The real problem is probably "How do I make sure that the the email address the user is entering can be used to communicate with the user?" or as zsalya mentioned in comments "What sanitization should you apply to a user-entered email address before storing it in your database?"
Constructing regexes for validating emails can be a good and fun exercise, but in general, you should really avoid it in production code. The proper way of verifying an email address is in most cases to send a verification mail. Trying to verify if a mail address matches the specification is very tricky, and even if you get it right, it's still often useless information unless you know that it's a mail address that you can send mails to and that someone reads.
Think of it. How often do you have use for storing a mail address that's wrong?
If you're just want to make sure that a user does not mix up input fields, check that the mail address contains a @
character. That's enough. Well, it would not catch those who insists on that character in user names or passwords, but that's their head ache. ;)
Long version
In a majority of the cases where you would want to use this, just knowing that the email address is valid does not mean a thing. What you really want to know is if it is the right email address.
The reason may differ. You may want to send newsletters, use it for regular communication, password recovery or something else. But whatever it is, it's important that it is the right address. It's not important to know if the address fulfills a complicated standard. The only important thing is to know if it can be used for the purpose you have of storing the address.
The proper way to verify this is by sending a mail with a verification link.
If you have verified the email address with a verification link, there's often no point in checking if it is a correct email address, since you know it works. It could however be used for basically checking that the user is entering the email address in the correct field. My advice in this case is to be extremely forgiving. I'd say it's enough to just check that it is a @
in the field. It's a simple check and ALL email addresses includes a @
. If you want to make it more complicated than that, I would suggest just warning the user that it might be something wrong with the address, but not forbidding it. A pretty simple regex that would have extremely few false negatives (if any) is
.+@.+\..+
This means a non empty string before @
followed by a non empty domain, a dot and a non empty top domain. But actually, I'd just stick with @.+
which means that the right part is non empty, and I don't know of any dns server that would accept an empty server name.
Properly checking an email against the standard is actually really tricky
But one worse concern is that a regex for accurately verifying an email address is actually a very complex matter. If you try to create a regex on your own, you will almost certainly make mistakes. One thing worth mentioning here is that the standard RFC 5322 does allow comments within parentheses. To make things worse, nested comments are allowed. A standard regex cannot match nested patterns. You will need extended regex for this. While extended regexes are not unusual, it does say something about the complexity. And even if you get it right, will you update the regex when a new standard comes?
The mail server might support non-standard addresses
And one more thing, even if you get it 100% right, that still may not be enough. An email address has the local part on the left side of the @ and domain part on the right. Everything in the local part is meant to be handled by the server. Sure, RFC 5322 is pretty detailed about what a valid local part looks like, but what if a particular email server accepts addresses that is not valid according to RFC 5322? Are you really sure you don't want to allow a particular email address that does work just because it does not follow the standard? Do you want to lose customers for your business just because they have chosen an obscure email provider? Or because you have made a mistake in the regex? (Hint: It's very easy to make mistakes with language specific characters)
Here, I might add that I have experienced not being able to register to various web sites because of my email address. And I don't even have a strange address. It's simply <name>@protonmail.com
but some sites claims that it's not a valid address. I have a hard time believing it's because of <name>
, since it only contains 12 lowercase letters from a-z.
If you really want to check if an address is correct in production code, then use MailAddress class or something equivalent. But first take a minute to ponder if this really is what you want. Ask yourself if the address has any value if it is not the correct address. If the answer is no, then you don't. Use verification links instead.
That being said, it can be a good thing to validate input. The important thing is to know why you are doing it. Validating the email with a regex or (preferably) something like the Mailaddress
class could give some protection against malicious input, such as SQL injections and such. But if this is the only method you have to protect you against malicious input, then you're doing something else very wrong.