$ snippet validate-email-url
Validate an email address or URL
Practical validation that accepts real addresses and rejects obvious typos — and why you should stop looking for the perfect email regex.
/**
* Pragmatic email check: something@domain.tld, no spaces, one @, a dot in the domain.
* This is what browsers' <input type="email"> roughly enforces. Verify by sending mail.
*/
function isValidEmail(value) {
const s = String(value).trim();
if (s.length > 254) return false;
return /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(s) && !/\.\./.test(s);
}
/** True for absolute http(s) URLs the browser can actually parse. */
function isValidHttpUrl(value, { allowLocalhost = false } = {}) {
let url;
try { url = new URL(String(value).trim()); } catch { return false; }
if (url.protocol !== "http:" && url.protocol !== "https:") return false;
if (!allowLocalhost && url.hostname === "localhost") return false;
return url.hostname.includes(".") || allowLocalhost;
}
/** Normalize for storage: lowercase domain, trim. (Local part is case-sensitive per spec; most providers ignore it.) */
function normalizeEmail(value) {
const s = String(value).trim();
const at = s.lastIndexOf("@");
return at < 0 ? s : s.slice(0, at) + "@" + s.slice(at + 1).toLowerCase();
}How it works
The RFC allows addresses like "john doe"@example.com and user@[192.168.1.1], so a strict regex either rejects valid addresses or is thousands of characters long. A loose shape check catches what you actually care about — missing @, no domain, a space — and the only real validation is sending a confirmation email. For URLs, let the URL constructor do the parsing; it knows every rule you'd forget.
Gotchas
- Don't block plus-addresses (
me+tag@gmail.com) or new TLDs (.museum,.photography); both are valid and common. new URL("example.com")throws because there is no scheme. If you accept bare domains, prependhttps://before parsing.<input type="email">pluscheckValidity()gives you the same check for free in forms; keep this helper for server-side or non-form code.
Ad slot