email-addresses vs addressparser vs emailjs-addressparser vs mailparser vs parse-address
Email Address Parsing Libraries for JavaScript Applications
email-addressesaddressparseremailjs-addressparsermailparserparse-address

Email Address Parsing Libraries for JavaScript Applications

addressparser, email-addresses, emailjs-addressparser, mailparser, and parse-address are all npm packages designed to parse email addresses and related header formats, but they serve different purposes and follow different design philosophies. addressparser is a focused, RFC-compliant parser for email address headers from the nodemailer team. email-addresses provides both parsing and building capabilities with strong RFC 5322 compliance. emailjs-addressparser is a fork of addressparser maintained by the EmailJS team. mailparser is a full email message parser that includes address parsing as one of many features. parse-address offers simple address parsing with name and email extraction. Each package targets different use cases, from simple email validation to complete email message processing.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
email-addresses858,905270-295 years agoMIT
addressparser041-010 years agoMIT
emailjs-addressparser02745.3 kB4-MIT
mailparser01,66167.3 kB09 days agoMIT
parse-address0164-257 years agoISC

Email Address Parsing Libraries: Technical Deep-Dive for Frontend Architects

When building applications that handle email addresses, you'll quickly discover that parsing email headers is more complex than simple string splitting. RFC 5322 defines intricate rules for email address formats, including display names, quoted strings, comments, and grouped addresses. The five packages we're comparing — addressparser, email-addresses, emailjs-addressparser, mailparser, and parse-address — each take different approaches to solving this problem. Let's examine how they handle real-world scenarios.

📋 Parsing Simple Email Addresses

The most basic use case is extracting an email address from a simple string.

addressparser handles this with a straightforward API that returns structured objects.

import addressparser from 'addressparser';

const result = addressparser('user@example.com');
// [{ address: 'user@example.com', name: '' }]

const withName = addressparser('John Doe <user@example.com>');
// [{ address: 'user@example.com', name: 'John Doe' }]

email-addresses provides a more detailed parse tree with additional metadata.

import * as emailAddresses from 'email-addresses';

const result = emailAddresses.parseOneAddress('user@example.com');
// { address: 'user@example.com', name: null, local: 'user', domain: 'example.com' }

const withName = emailAddresses.parseOneAddress('John Doe <user@example.com>');
// { address: 'user@example.com', name: 'John Doe', local: 'user', domain: 'example.com' }

emailjs-addressparser mirrors the addressparser API since it's a fork.

import addressparser from 'emailjs-addressparser';

const result = addressparser('user@example.com');
// [{ address: 'user@example.com', name: '' }]

const withName = addressparser('John Doe <user@example.com>');
// [{ address: 'user@example.com', name: 'John Doe' }]

mailparser requires parsing a full message or using its internal addressparser module.

import { simpleParser } from 'mailparser';

// For full message parsing
const parsed = await simpleParser('From: user@example.com\r\n\r\nBody');
// parsed.from = [{ address: 'user@example.com', name: '' }]

// Or use the bundled addressparser
import addressparser from 'mailparser/lib/addressparser.js';
const result = addressparser('user@example.com');

parse-address offers the simplest API for basic extraction.

import parseAddress from 'parse-address';

const result = parseAddress.parseOne('user@example.com');
// { email: 'user@example.com', name: '' }

const withName = parseAddress.parseOne('John Doe <user@example.com>');
// { email: 'user@example.com', name: 'John Doe' }

📨 Handling Multiple Addresses (To, Cc, Bcc Headers)

Email headers often contain multiple addresses separated by commas, which requires careful parsing to avoid splitting on commas inside quoted strings.

addressparser excels at parsing multiple addresses from header strings.

import addressparser from 'addressparser';

const recipients = addressparser('John <john@example.com>, Jane <jane@example.com>');
// [
//   { address: 'john@example.com', name: 'John' },
//   { address: 'jane@example.com', name: 'Jane' }
// ]

// Handles grouped addresses too
const grouped = addressparser('Team: john@example.com, jane@example.com;');
// [{ name: 'Team', group: [{ address: 'john@example.com' }, { address: 'jane@example.com' }] }]

email-addresses provides separate functions for single vs multiple addresses.

import * as emailAddresses from 'email-addresses';

const recipients = emailAddresses.parseAddressList('John <john@example.com>, Jane <jane@example.com>');
// [
//   { address: 'john@example.com', name: 'John' },
//   { address: 'jane@example.com', name: 'Jane' }
// ]

// Returns null on failure instead of throwing
const invalid = emailAddresses.parseAddressList('invalid-email');
// null

emailjs-addressparser handles multiple addresses identically to addressparser.

import addressparser from 'emailjs-addressparser';

const recipients = addressparser('John <john@example.com>, Jane <jane@example.com>');
// [
//   { address: 'john@example.com', name: 'John' },
//   { address: 'jane@example.com', name: 'Jane' }
// ]

mailparser extracts multiple addresses as part of full message parsing.

import { simpleParser } from 'mailparser';

const email = `From: sender@example.com
To: john@example.com, jane@example.com
Cc: manager@example.com

Message body`;

const parsed = await simpleParser(email);
// parsed.to = [{ address: 'john@example.com' }, { address: 'jane@example.com' }]
// parsed.cc = [{ address: 'manager@example.com' }]

parse-address can parse multiple addresses but with less RFC compliance.

import parseAddress from 'parse-address';

const recipients = parseAddress.parse('John <john@example.com>, Jane <jane@example.com>');
// [
//   { email: 'john@example.com', name: 'John' },
//   { email: 'jane@example.com', name: 'Jane' }
// ]

🔍 RFC 5322 Compliance and Edge Cases

Real-world email headers contain complex cases: quoted names, escaped characters, comments, and unusual formatting.

addressparser handles most RFC 5322 edge cases reliably.

import addressparser from 'addressparser';

// Quoted display names
const quoted = addressparser('"Doe, John" <john@example.com>');
// [{ address: 'john@example.com', name: 'Doe, John' }]

// Comments in addresses
const withComment = addressparser('john@example.com (work account)');
// [{ address: 'john@example.com', name: '' }]

// Escaped quotes
const escaped = addressparser('"John \\"The Dev\\" Doe" <john@example.com>');
// [{ address: 'john@example.com', name: 'John "The Dev" Doe' }]

email-addresses provides the strictest RFC 5322 compliance with detailed error information.

import * as emailAddresses from 'email-addresses';

// Strict parsing with error details
const result = emailAddresses.parseOneAddress('"Doe, John" <john@example.com>');
// { address: 'john@example.com', name: 'Doe, John' }

// Get parse tree for debugging
const tree = emailAddresses.parse('john@example.com');
// { addresses: [{ ... }], ast: { ... } }

// Validation without throwing
const valid = emailAddresses.validateEmail('john@example.com');
// true

emailjs-addressparser inherits addressparser's RFC compliance with minor variations.

import addressparser from 'emailjs-addressparser';

const quoted = addressparser('"Doe, John" <john@example.com>');
// [{ address: 'john@example.com', name: 'Doe, John' }]

mailparser handles edge cases as part of complete message parsing.

import { simpleParser } from 'mailparser';

const email = `From: "Doe, John" <john@example.com>
Subject: Test

Body`;

const parsed = await simpleParser(email);
// parsed.from = [{ address: 'john@example.com', name: 'Doe, John' }]

parse-address handles basic cases but may struggle with complex RFC edge cases.

import parseAddress from 'parse-address';

const quoted = parseAddress.parseOne('"Doe, John" <john@example.com>');
// { email: 'john@example.com', name: 'Doe, John' }

// May not handle all escaped characters correctly

🌐 Browser vs Node.js Compatibility

Frontend developers need to know which packages work in browser environments.

addressparser works in both Node.js and browsers without bundler configuration.

// Works in browser via CDN or bundler
import addressparser from 'addressparser';
// No Node.js-specific dependencies

email-addresses is designed for universal JavaScript (Node.js and browsers).

// Universal module
import * as emailAddresses from 'email-addresses';
// Works in browser and Node.js without modification

emailjs-addressparser works in both environments, optimized for EmailJS browser SDK.

// Browser-compatible
import addressparser from 'emailjs-addressparser';
// Designed with browser usage in mind

mailparser is primarily designed for Node.js server-side use.

import { simpleParser } from 'mailparser';
// Requires Node.js streams and buffers
// Not recommended for browser use due to size and dependencies

parse-address works in both environments with minimal dependencies.

import parseAddress from 'parse-address';
// Lightweight enough for browser bundling

⚠️ Maintenance Status and Deprecation Warnings

addressparser is actively maintained by the nodemailer team. It's stable and receives updates for bug fixes and RFC compliance improvements. Safe for production use.

email-addresses is actively maintained with regular updates. It has strong test coverage and is considered production-ready for applications requiring strict RFC compliance.

emailjs-addressparser is maintained by the EmailJS team but receives fewer updates than the original addressparser. Consider using addressparser directly unless you need EmailJS-specific integration.

mailparser is actively maintained and widely used for server-side email processing. However, it's overkill if you only need address parsing — consider using addressparser standalone instead.

parse-address has less active maintenance compared to addressparser and email-addresses. Review the repository activity before using in critical production applications. May be suitable for simple internal tools but evaluate carefully for customer-facing features.

🏗️ Architecture Considerations

Bundle Size Impact

For frontend applications, bundle size matters. mailparser is significantly larger than the others because it parses complete email messages. If you only need address parsing, addressparser, email-addresses, or parse-address are more appropriate.

Tree-Shaking Support

email-addresses exports individual functions that can be tree-shaken:

// Only import what you need
import { parseOneAddress } from 'email-addresses';
// Bundler can eliminate unused exports

addressparser has a single default export, so tree-shaking benefits are minimal:

import addressparser from 'addressparser';
// Entire module included

TypeScript Support

email-addresses includes TypeScript definitions out of the box:

import * as emailAddresses from 'email-addresses';

const result: emailAddresses.ParsedAddress | null = 
  emailAddresses.parseOneAddress('user@example.com');

addressparser has community-maintained TypeScript definitions available via @types/addressparser:

import addressparser from 'addressparser';
// Install @types/addressparser for TypeScript support

📊 Feature Comparison Summary

Featureaddressparseremail-addressesemailjs-addressparsermailparserparse-address
Primary PurposeAddress header parsingParse + build addressesAddress parsing (EmailJS fork)Full email message parsingSimple address extraction
RFC 5322 ComplianceHighVery HighHighHighMedium
Browser Support✅ Yes✅ Yes✅ Yes❌ Node.js only✅ Yes
Multiple Addresses✅ Yes✅ Yes✅ Yes✅ Yes (in context)✅ Yes
Grouped Addresses✅ Yes✅ Yes✅ Yes✅ Yes⚠️ Limited
Build/Serialize❌ No✅ Yes❌ No❌ No❌ No
TypeScriptVia @typesBuilt-inVia @typesBuilt-inCommunity
Active Maintenance✅ Active✅ Active⚠️ Moderate✅ Active⚠️ Moderate

💡 Practical Recommendations

For Form Validation

Use email-addresses for strict validation with detailed error reporting:

import * as emailAddresses from 'email-addresses';

function validateEmail(input) {
  const result = emailAddresses.parseOneAddress(input);
  if (!result) {
    return { valid: false, error: 'Invalid email format' };
  }
  return { valid: true, address: result.address };
}

For Email Client Headers

Use addressparser for parsing From, To, Cc headers:

import addressparser from 'addressparser';

function parseEmailHeaders(rawHeaders) {
  return {
    from: addressparser(rawHeaders.from),
    to: addressparser(rawHeaders.to),
    cc: addressparser(rawHeaders.cc)
  };
}

For Complete Email Processing

Use mailparser when you receive raw email data:

import { simpleParser } from 'mailparser';

async function processIncomingEmail(rawEmail) {
  const parsed = await simpleParser(rawEmail);
  return {
    from: parsed.from,
    to: parsed.to,
    subject: parsed.subject,
    body: parsed.text,
    attachments: parsed.attachments
  };
}

For Simple Contact Extraction

Use parse-address for lightweight needs:

import parseAddress from 'parse-address';

function extractContact(input) {
  const parsed = parseAddress.parseOne(input);
  return { name: parsed.name, email: parsed.email };
}

🎯 Final Architecture Guidance

Choose addressparser when you need reliable, RFC-compliant address parsing without extra features. It's the sweet spot for most applications that parse email headers.

Choose email-addresses when you need both parsing and building capabilities, strict RFC compliance, or detailed parse trees for debugging and validation.

Choose emailjs-addressparser only if you're already committed to the EmailJS ecosystem. Otherwise, prefer the original addressparser.

Choose mailparser when you need to process complete email messages, not just addresses. Don't use it solely for address parsing — it's too heavy.

Choose parse-address for simple, internal tools where absolute RFC compliance isn't critical. For customer-facing features, prefer addressparser or email-addresses.

The right choice depends on your specific requirements: RFC compliance level, browser support needs, whether you need to build addresses (not just parse), and if you're processing full messages or just headers. For most frontend applications, addressparser or email-addresses will serve you best.

How to Choose: email-addresses vs addressparser vs emailjs-addressparser vs mailparser vs parse-address

  • email-addresses:

    Choose email-addresses if you need both parsing and building capabilities with strict RFC 5322 compliance. It provides detailed parse trees and validation, making it suitable for email clients, form validation, or any application requiring deep inspection of email address structures. Best for projects that need to both parse and construct email address strings programmatically.

  • addressparser:

    Choose addressparser if you need a lightweight, RFC-compliant parser specifically for email address headers (From, To, Cc, etc.). It's well-maintained by the nodemailer team and works in both Node.js and browsers. Ideal for applications that need to parse email headers without the overhead of a full email parser. Avoid if you need to parse complete email messages or build email addresses.

  • emailjs-addressparser:

    Choose emailjs-addressparser if you're already using the EmailJS ecosystem and want consistency with their other tools. It's a fork of addressparser with minor modifications for EmailJS integration. However, for new projects not tied to EmailJS, prefer the original addressparser which has broader community adoption and more active maintenance.

  • mailparser:

    Choose mailparser if you need to parse complete email messages (headers, body, attachments) rather than just addresses. It includes address parsing as part of a larger toolkit for processing raw email data. Ideal for email servers, forwarding services, or applications that receive and process full email messages. Overkill if you only need address parsing.

  • parse-address:

    Choose parse-address if you need simple name and email extraction with minimal dependencies. It's straightforward for basic use cases like contact form processing or simple address validation. However, it has less active maintenance compared to addressparser and email-addresses, so evaluate carefully for production use in critical applications.

README for email-addresses

email-addresses.js

An RFC 5322 email address parser.

v 5.0.0

What?

Want to see if something could be an email address? Want to grab the display name or just the address out of a string? Put your regexes down and use this parser!

This library does not validate email addresses - we can't really do that without sending an email. However, it attempts to parse addresses using the (fairly liberal) grammar specified in RFC 5322. You can use this to check if user input looks like an email address.

Note carefully though - this parser supports all features of RFC 5322, which means that "Bob Example" <bob@example.com> is a valid email address. If you just want to validate the bob@example.com part, that is RFC 5321, for which you want to use something like node-address-rfc2821.

Why use this?

Use this library because you can be sure it really respects the RFC:

  • The functions in the recursive decent parser match up with the productions in the RFC
  • The productions from the RFC are written above each function for easy verification
  • Tests include all of the test cases from the is_email project, which are extensive

Installation

npm install email-addresses

Example

$ node
> addrs = require("email-addresses")
{ [Function: parse5322]
  parseOneAddress: [Function: parseOneAddressSimple],
  parseAddressList: [Function: parseAddressListSimple] }
> addrs.parseOneAddress('"Jack Bowman" <jack@fogcreek.com>')
{ parts:
   { name: [Object],
     address: [Object],
     local: [Object],
     domain: [Object] },
  name: 'Jack Bowman',
  address: 'jack@fogcreek.com',
  local: 'jack',
  domain: 'fogcreek.com' }
> addrs.parseAddressList('jack@fogcreek.com, Bob <bob@example.com>')
[ { parts:
     { name: null,
       address: [Object],
       local: [Object],
       domain: [Object] },
    name: null,
    address: 'jack@fogcreek.com',
    local: 'jack',
    domain: 'fogcreek.com' },
  { parts:
     { name: [Object],
       address: [Object],
       local: [Object],
       domain: [Object] },
    name: 'Bob',
    address: 'bob@example.com',
    local: 'bob',
    domain: 'example.com' } ]
> addrs("jack@fogcreek.com")
{ ast:
   { name: 'address-list',
     tokens: 'jack@fogcreek.com',
     semantic: 'jack@fogcreek.com',
     children: [ [Object] ] },
  addresses:
   [ { node: [Object],
       parts: [Object],
       name: null,
       address: 'jack@fogcreek.com',
       local: 'jack',
       domain: 'fogcreek.com' } ] }
> addrs("bogus")
null

API

obj = addrs(opts)

Call the module directly as a function to get access to the AST. Returns null for a failed parse (an invalid address).

Options:

  • string - An email address to parse. Parses as address-list, a list of email addresses separated by commas.
  • object with the following keys:
    • input - An email address to parse. Required.
    • rfc6532 - Enable rfc6532 support (unicode in email addresses). Default: false.
    • partial - Allow a failed parse to return the AST it managed to produce so far. Default: false.
    • simple - Return just the address or addresses parsed. Default: false.
    • strict - Turn off features of RFC 5322 marked "Obsolete". Default: false.
    • rejectTLD - Require at least one . in domain names. Default: false.
    • startAt - Start the parser at one of address, address-list, angle-addr, from, group, mailbox, mailbox-list, reply-to, sender. Default: address-list.
    • atInDisplayName - Allow the @ character in the display name of the email address. Default: false.
    • commaInDisplayName - Allow the , character in the display name of the email address. Default: false.
    • addressListSeparator - Specifies the character separating the list of email addresses. Default: ,.

Returns an object with the following properties:

  • ast - the full AST of the parse.
  • addresses - array of addresses found. Each has the following properties:
    • parts - components of the AST that make up the address.
    • type - The type of the node, e.g. mailbox, address, group.
    • name - The extracted name from the email. e.g. parsing "Bob" <bob@example.com> will give Bob for the name.
    • address - The full email address. e.g. parsing the above will give bob@example.com for the address.
    • local - The local part. e.g. parsing the above will give bob for local.
    • domain - The domain part. e.g. parsing the above will give example.com for domain.

Note if simple is set, the return will be an array of addresses rather than the object above.

Note that addresses can contain a group address, which in contrast to the address objects will simply contain two properties: a name and addresses which is an array of the addresses in the group. You can identify groups because they will have a type of group. A group looks something like this: Managing Partners:ben@example.com,carol@example.com;

obj = addrs.parseOneAddress(opts)

Parse a single email address.

Operates similarly to addrs(opts), with the exception that rfc6532 and simple default to true.

Returns a single address object as described above. If you set simple: false the returned object includes a node object that contains the AST for the address.

obj = addrs.parseAddressList(opts)

Parse a list of email addresses separated by comma.

Operates similarly to addrs(opts), with the exception that rfc6532 and simple default to true.

Returns a list of address objects as described above. If you set simple: false each address will include a node object that contains the AST for the address.

obj = addrs.parseFrom(opts)

Parse an email header "From:" address (specified as mailbox-list or address-list).

Operates similarly to addrs(opts), with the exception that rfc6532 and simple default to true.

Returns a list of address objects as described above. If you set simple: false each address will include a node object that contains the AST for the address.

obj = addrs.parseSender(opts)

Parse an email header "Sender:" address (specified as mailbox or address).

Operates similarly to addrs(opts), with the exception that rfc6532 and simple default to true.

Returns a single address object as described above. If you set simple: false the returned object includes a node object that contains the AST for the address.

obj = addrs.parseReplyTo(opts)

Parse an email header "Reply-To:" address (specified as address-list).

Operates identically to addrs.parseAddressList(opts).

Usage

If you want to simply check whether an address or address list parses, you'll want to call the following functions and check whether the results are null or not: parseOneAddress for a single address and parseAddressList for multiple addresses.

If you want to examine the parsed address, for example to extract a name or address, you have some options. The object returned by parseOneAddress has four helper values on it: name, address, local, and domain. See the example above to understand is actually returned. (These are equivalent to parts.name.semantic, parts.address.semantic, etc.) These values try to be smart about collapsing whitespace, quotations, and excluding RFC 5322 comments. If you desire, you can also obtain the raw parsed tokens or semantic tokens for those fields. The parts value is an object referencing nodes in the AST generated. Nodes in the AST have two values of interest here, tokens and semantic.

> a = addrs.parseOneAddress('Jack  Bowman  <jack@fogcreek.com >')
> a.parts.name.tokens
'Jack  Bowman  '
> a.name
'Jack Bowman'
> a.parts.name.semantic
'Jack Bowman '
> a.parts.address.tokens
'jack@fogcreek.com '
> a.address
'jack@fogcreek.com'
> a.parts.address.semantic
'jack@fogcreek.com'

If you need to, you can inspect the AST directly. The entire AST is returned when calling the module's function.

References

Props

Many thanks to Dominic Sayers and his documentation and tests for the is_email function which helped greatly in writing this parser.

License

Licensed under the MIT License. See the LICENSE file.