First of all, your regex is overly complicated and doesn't quite fit standards for domain names.
- You have
|
pipes inside of bracketed character classes, which are unnecessary since everything inside brackets is already an alternation. Furthermore, it means that you have inadvertently matched the
|
character!
- The underscore
_
character does not need to be in brackets - it is not a special character for regex. Maybe you did that just for readability?
- Domain names do not have to start with letters, and can contain dashes. You may not match some valid email addresses with your restrictions in place.
Second, I'm not sure what language you are using, but here are two different solutions, based on whether you have negative lookaheads available.
Using negative lookaheads:
^(?!(.*[_.]){2}.*@)[a-z][a-z0-9._]*@([-a-z0-9]+\.)+[a-z0-9]+$
(?!(.*[_.]){2}.*@)
is the negative lookahead to indicate that there should not be two instances of a period or underscore before the @ sign.
[a-z][a-z0-9._]*
allows for a starting letter followed by letters, numbers, periods, and underscores before the @ sign.
([-a-z0-9]+\.)+[a-z0-9]+
allows for any number of subdomains and domain name before the top-level domain.
No negative lookaheads:
^[a-z][a-z0-9]*[._]?[a-z0-9]*@([-a-z0-9]+\.)+[a-z0-9]+$
This is almost the same regex, but has an optional period or underscore embedded between two sections that match the other characters.
[a-z][a-z0-9]*
allows for a starting letter followed by letters and numbers.
[._]?
allows for up to one period or underscore.
[a-z0-9]*
allows for more letters and numbers before the @ sign.
([-a-z0-9]+\.)+[a-z0-9]+
allows for any number of subdomains and domain name before the top-level domain.