I Built an Email Validation Library and Published It on npm. Here's Everything I Learned
Source: Dev.to
The Story
I spent the last few weeks building an email‑validation library from scratch and publishing it on npm. Not because the world desperately needed another npm package, but because I wanted to deeply understand how email validation actually works. The existing solutions frustrated me, so I decided to create my own.
In this post I’ll share:
- Why I built it
- What I learned
- The technical decisions that made it 3× faster than alternatives
- How you can use the same approach to build your own npm packages
Let’s dive in…
What I’m Going to Cover
- Why I started this project
- The 5 layers of email validation most developers don’t know about
- How I made it 3× faster than the competition
- The tech‑stack decisions (and why)
- How to publish your first npm package
- What I’d do differently next time
Why Build Another Email Validator?
I was using deep-email-validator in a project. It worked, but several issues annoyed me:
- The TypeScript types were outdated (still using 3.8)
- No bulk‑validation support
- No caching (validating the same email twice repeated all work)
- Error messages were generic strings like “Invalid email”
- The regex validation wasn’t RFC 5322‑compliant
I thought, “How hard can it be to build something better?”
Famous last words. Turns out email validation is far more complex than most people think—exactly why the project was worth building.
The 5 Layers of Email Validation
Most developers think email validation is just a regex check. That’s maybe 20 % of proper validation. A production‑ready validator needs to check:
Layer 1 – Regex (Format Validation)
Does the email look like an email? It must follow RFC 5322.
Examples of technically valid addresses:
"john doe"@example.com(quoted strings)user+tag@example.com(plus addressing)user@[192.168.1.1](IP‑address domain)
Many Stack‑Overflow regexes would reject half of these.
Layer 2 – Typo Detection
user@gmial.com is syntactically valid, but Gmail doesn’t exist at gmial.com.
This layer catches common typos and suggests corrections, e.g., “Did you mean gmail.com?”
Layer 3 – Disposable Email Detection
Mailinator, Guerrillamail, 10 Minute Mail…
There are > 40 000 disposable‑email services. If you don’t block them, your database fills with fake users.
Layer 4 – MX Record Validation
Even if the domain looks legit, does it have mail servers?
A DNS lookup for MX records tells you whether the domain can receive email. No MX → invalid.
Layer 5 – SMTP Verification
The final boss: connect to the mail server and ask, “Does this mailbox exist?”
It’s slow (network calls) and sometimes unreliable (servers may block verification), but when you need certainty it’s the way to go.
Making It 3× Faster
The original deep-email-validator validates emails sequentially, with no caching, and hits the network for every DNS and SMTP check. I wanted to process 100 emails in under 5 seconds.
Solution 1 – Concurrent Processing
Validate many emails in parallel with configurable concurrency:
const result = await validateBulk(emails, {
concurrency: 10,
onProgress: (completed, total) => {
console.log(`Progress: ${completed}/${total}`);
},
});
10 concurrent validations ≈ 10× faster bulk processing.
Solution 2 – Built‑In Rate Limiting
Hammering mail servers can get you blacklisted. I added a token‑bucket limiter:
await validateBulk(emails, {
rateLimit: {
perDomain: { requests: 10, window: 60 }, // 10 reqs per domain per minute
global: { requests: 100, window: 60 }, // 100 reqs globally per minute
},
});
Prevents abuse while keeping performance high.
Solution 3 – Early Exit
If the regex fails, there’s no point checking MX records. An early‑exit option stops validation on the first failure, rejecting invalid emails in:
- 💻 GitHub:
- 📚 Docs:
What’s Next?
I’m planning to add:
- In‑memory LRU caching (v1.1)
- Enhanced reputation scoring with configurable weights
- CLI tool for quick validations
- Maybe a browser build
If you found this useful, star the repo on GitHub—it helps more than you’d think. And if you build something cool with it, let me know; I’d love to see what you create.