How to Validate Email in JavaScript: From Simple Regex to Full Under-the-Hood Analysis
\n\nEvery developer has encountered the question at least once: «How can I validate an email address in JavaScript?». This question on Stack Overflow has gathered thousands of views and hundreds of answers because the topic is a real tangle of nuances. Today we won't just provide ready-made code, but will look under the hood: we'll analyze why a simple check might allow a@b or block "test@[IPv6:2001:db8::1]". Let's go!
Why is «just regex» a bad idea?
\n\nThe most popular solution on the internet is to copy a regular expression. But let's be honest: email addresses are chaos. The RFC 5321 and RFC 5322 specifications allow the use of characters like +, -, ., %, and even comments in parentheses. There are also domains like museum or @[192.168.1.1]. Try to fit all of this into a single regex line — and you will either allow an invalid address or block a real user.
Here's an example often found on Stack Overflow:
\n\nconst emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\nThis code works for 90% of cases, but:
\n- \n
- Allows
test@localhost(valid for a local network) \n - Blocks
"test@[192.168.1.1]"(valid per RFC) \n - Does not check domain length or the presence of dots \n
The moral: don't try to write a perfect regex. It's better to use a combination of a simple check + server-side validation.
\n\nAnatomy of an Email Address: What You Need to Know Before Writing Code
\n\nBefore writing a validator, let's break down the email structure according to the specification:
\n\n- \n
- Local part (before @): can contain letters, numbers, dots, plus signs, hyphens, but cannot start or end with a dot. Quoted strings are allowed for special characters. \n
- Domain (after @): consists of labels separated by dots. Each label is from 1 to 63 characters. The domain can be an IP address in square brackets. \n
- Total length: no more than 254 characters. \n
Knowing this, we can write a more meaningful check.
\n\nStep 1: Simple but Functional Validation (for 99% of cases)
\n\nLet's start with code used in production projects (e.g., in Angular or React). It's not perfect, but sufficient for most forms:
\n\nfunction isEmailSimple(email) {\n // Remove whitespace\n const trimmed = email.trim();\n \n // Check for empty string\n if (!trimmed) return false;\n \n // Basic structure: something @ something . something\n const atIndex = trimmed.lastIndexOf('@');\n if (atIndex < 1 || atIndex === trimmed.length - 1) return false;\n \n const localPart = trimmed.slice(0, atIndex);\n const domain = trimmed.slice(atIndex + 1);\n \n // Domain must contain at least one dot\n const dotIndex = domain.lastIndexOf('.');\n if (dotIndex < 1 || dotIndex === domain.length - 1) return false;\n \n // Length check\n if (trimmed.length > 254) return false;\n if (localPart.length > 64) return false;\n \n return true;\n}\n\n// Examples:\nconsole.log(isEmailSimple('user@example.com')); // true\nconsole.log(isEmailSimple('a@b.c')); // true (formally valid)\nconsole.log(isEmailSimple('user@localhost')); // false (no dot)\nconsole.log(isEmailSimple('@example.com')); // false\n\n\nThis code is already better than a blind regex. It checks the structure, length, and the presence of @ with a dot. But it allows user@[192.168.1.1] — for most web forms, this is not critical.
Step 2: Advanced Validation Considering RFC (almost like in the browser)
\n\nModern browsers use built-in validation via the type="e