Can it cause harm to validate email addresses with a regex?

后端 未结 8 842
旧巷少年郎
旧巷少年郎 2020-12-06 03:55

I\'ve heard that it is a bad thing to validate email addresses with a regex, and that it actually can cause harm. Why is that? I thought it never could be a bad thing to val

相关标签:
8条回答
  • 2020-12-06 04:17

    A regular expression is probably the best way to validate an email address; so long as you use the correct one. Once you've checked the address with a regular expression, there's only a few additional requirements that must be checked (that the address is not too long, and that it is valid UTF-8).

    This is because ABNF grammar that defines the form of email addresses is "regular", which means it can be described exactly as a regular expression; without backtracking, recursion, or any non-regular features.

    It's only a matter of understanding the specification; but once you do that, it turns out the regular expression for email address is actually very simple: How to validate an email address using a regular expression?

    0 讨论(0)
  • 2020-12-06 04:23

    In addition to other answers, I would like to point our, that Regex engines are susceptible to ReDOS - regex denial of service attacks. The attack is based on the fact that many non-trivial regular expressions have inputs that can take an extraordinary amount of CPU cycles to produce a non-match.

    Crafting such an input might cause trouble to the availability of the site even with small botnet.

    For more information "Regular Expressions Denial of the Service (ReDOS) Attacks": https://dzone.com/articles/regular-expressions-denial

    0 讨论(0)
  • 2020-12-06 04:25

    Regex is not harmful.

    Use a good email regex to filter the impatient fake user.

    If you are selling to that individual, you might want to contact them
    for further validation, though sellers don't care about email too much
    and just validating the credit card is good enough for them.

    Otherwise, the only other place where validation is necessary is when
    someone wants access to and interact with your forum, and for some reason
    you want get remuneration by selling their email to mass advertisers,
    even though you say you won't do that.

    A general email regex in the html5 spec is this -

    ^[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])?)*$
    

    http://www.w3.org/TR/html5/forms.html#valid-e-mail-address

     ^ 
     [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] 
          )?
     )*
     $ 
    
    0 讨论(0)
  • 2020-12-06 04:29

    It is not inherently bad to validate email addresses.

    It is not even inherently bad to validate email addresses using regexes ... though there are arguably better ways to validate them1.

    The real issues are that validation of email addresses (based on the syntax):

    • does not tell you if the address corresponds to a valid, working mailbox, and
    • does not tell you if it is an address for the correct user (or agent).

    Since users accidentally (or deliberately) use incorrect email addresses for various purposes, you need to do something else if you need to know if the address is correct; e.g. send some kind of "activation" email to the address.

    So, assuming that you are going to implement the second stage of checking, the first stage of syntax checking the email address is relatively unimportant, and not even strictly necessary.


    1 - Creating a regex that correctly deals with all of the edge-cases in the email syntax is non-trivial. However, it may be acceptable to disallow some of the more abstruse edge-cases, provided it doesn't unduly inconvenience a significant number of users.

    0 讨论(0)
  • 2020-12-06 04:34

    In general, yes - using regular expressions to validate email addresses is harmful. This is because of bad (incorrect) assumptions by the author of the regular expression.

    As @klutt indicated, an email address has two parts, the local-part and the domain. It's worth noting some things about these parts that aren't immediately obvious:

    • The local-part can contain escaped characters and even additional @ characters.
    • The local-part can be case sensitive, however it is up to the mail server at that specific domain how it wants to distinguish case.
    • The domain part can contain zero or more labels separated by a period (.), though in practice there are no MX records corresponding to the root (zero labels) or on the gTLDs (one label) themselves.

    So, there are some checks that you can do without rejecting valid email addresses that correspond with the above:

    • Address contains at least one @
    • The local-part (everything to the left of the rightmost @) is non-empty
    • The domain part (everything to the right of the rightmost @) contains at least one period (again, this isn't strictly true but pragmatic)

    That's it. As others have pointed out, it's best practice to test deliverability to that address. This will establish two important things:

    1. Whether the email currently exists; and
    2. That the user has access to the email address (is the legitimate user or owner)

    If you build email activation processes into your business process, you don't need to worry about complicated regular expressions that have issues.

    Some further reading for reference:

    RFC 5321: Simple Mail Transfer Protocol

    OWASP: Input Validation Cheat Sheet

    0 讨论(0)
  • 2020-12-06 04:37

    TL;DR

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

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

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

    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 rfc5322? 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 buisness just because they have chosen an obscure email provider?

    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.

    0 讨论(0)
提交回复
热议问题