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.
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.
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' }
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' }
// ]
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
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
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.
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.
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
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 | addressparser | email-addresses | emailjs-addressparser | mailparser | parse-address |
|---|---|---|---|---|---|
| Primary Purpose | Address header parsing | Parse + build addresses | Address parsing (EmailJS fork) | Full email message parsing | Simple address extraction |
| RFC 5322 Compliance | High | Very High | High | High | Medium |
| 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 |
| TypeScript | Via @types | Built-in | Via @types | Built-in | Community |
| Active Maintenance | ✅ Active | ✅ Active | ⚠️ Moderate | ✅ Active | ⚠️ Moderate |
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 };
}
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)
};
}
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
};
}
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 };
}
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.
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.
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.
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.
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.
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.
An RFC 5322 email address parser.
v 5.0.0
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.
Use this library because you can be sure it really respects the RFC:
npm install email-addresses
$ 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
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).
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.
Many thanks to Dominic Sayers and his documentation and tests for the is_email function which helped greatly in writing this parser.
Licensed under the MIT License. See the LICENSE file.