npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

eml-parser

v2.1.1

Published

Parse .eml and .msg files or convert to pdf, html, jpeg or png format. Extract headers and attachments from .eml and msg files.

Readme

📧 eml-parser

npm version license CI

Parse .eml and .msg files, extract headers and attachments, or convert messages to PDF / HTML / image formats.

✨ Features

  • 📨 Parse .eml and .msg email files
  • 📋 Extract headers, body, attachments, and embedded files
  • 🎨 Render emails as complete HTML documents with an Outlook-style header (avatar, recipients, date)
  • 🔗 Expand / collapse long recipient lists with a CSS-only toggle — no JavaScript
  • 🔍 Highlight keywords in email body with <mark> tags
  • 📄 Convert emails to PDF, PNG, or JPEG (stream or buffer)
  • 🔤 TypeScript declarations included out of the box
  • ⚡ Requires Node.js 18+

📖 Table of Contents


📦 Installation

npm install eml-parser

Requires Node.js 18 or later.


🚀 Quick Start

.eml file

const fs = require('fs');
const EmlParser = require('eml-parser');

const parser = new EmlParser(fs.createReadStream('./email.eml'));

// Get headers
const headers = await parser.getEmailHeaders();
console.log(headers.subject, headers.from, headers.to);

// Get full HTML (with styled header)
const html = await parser.getEmailAsHtml();
fs.writeFileSync('email.html', html);

// Extract attachments
const attachments = await parser.getEmailAttachments();
for (const att of attachments) {
  fs.writeFileSync(att.filename, att.content);
}

.msg file

const parser = new EmlParser(fs.createReadStream('./email.msg'));

const headers = await parser.getMessageHeaders();
console.log(headers.subject, headers.from, headers.to);

const html = await parser.getMessageAsHtml();
fs.writeFileSync('email.html', html);

Convert to PDF

const parser = new EmlParser(fs.createReadStream('./email.eml'));
const stream = await parser.convertEmailToStream('pdf');
stream.pipe(fs.createWriteStream('email.pdf'));

All methods return Promises — use async/await (shown above) or .then()/.catch().


🔤 TypeScript

This package ships with index.d.ts — no extra @types package needed.

import fs from 'fs';
import EmlParser, { EmailHeaders, HighlightOptions } from 'eml-parser';

const parser = new EmlParser(fs.createReadStream('./email.eml'));
const headers: EmailHeaders = await parser.getEmailHeaders();

const html: string = await parser.getEmailAsHtml({
  highlightKeywords: ['invoice'],
  includeSubject: false,
});

Available Types

| Type | Description | |------|-------------| | Address | { name: string, address: string } | | EmailHeaders | Parsed .eml headers (subject, from, to, cc, date, messageId, inReplyTo) | | MessageHeaders | Parsed .msg headers (subject, from, to, cc, date) | | HighlightOptions | { highlightKeywords?: string[], highlightCaseSensitive?: boolean } | | ParseEmlOptions | HighlightOptions & { ignoreEmbedded?: boolean } | | ParseMsgOptions | HighlightOptions |


📋 API Reference

Constructor

const parser = new EmlParser(readableStream);

| Param | Type | Description | |-------|------|-------------| | readableStream | Readable | A Node.js readable stream pointing to an .eml or .msg file |

One parser per file. Create a new EmlParser instance for each file you want to process.


Shared Options

These options are accepted by multiple methods. They are documented here once and referenced below.

HighlightOptions

| Option | Type | Default | Description | |--------|------|---------|-------------| | highlightKeywords | string[] | — | Keywords to wrap with <mark> tags in the email HTML | | highlightCaseSensitive | boolean | false | When true, matches keywords case-sensitively |

See Keyword Highlighting for details and examples.

Conversion Parameters

These apply to convertEmailToStream, convertEmailToBuffer, convertMessageToStream, and convertMessageToBuffer.

| Param | Type | Default | Description | |-------|------|---------|-------------| | type | 'pdf' \| 'jpeg' \| 'png' | 'pdf' | Output format | | orientation | 'potrait' \| 'landscape' | 'landscape' | Page orientation | | format | 'A3' \| 'A4' \| 'A5' \| 'Legal' \| 'Letter' \| 'Tabloid' | — | Page size | | options | HighlightOptions | — | Keyword highlighting options |


.eml Methods

parseEml(options?)

Parse the full .eml file. Returns the complete parsed email object.

| Param | Type | Description | |-------|------|-------------| | options.ignoreEmbedded | boolean | When true, excludes embedded files from the attachments array | | options.highlightKeywords | string[] | Keywords to highlight — see HighlightOptions | | options.highlightCaseSensitive | boolean | Case-sensitive matching — see HighlightOptions |

Returns: Promise<ParsedMail> — the full parsed email with these key properties:

{
  subject: string;
  from: { value: Address[] };
  to: { value: Address[] };
  cc: { value: Address[] };
  date: Date;
  messageId: string;
  inReplyTo: string;
  html: string;           // HTML body (with highlights applied if requested)
  text: string;           // Plain text body
  textAsHtml: string;     // Plain text converted to HTML
  attachments: Attachment[];
  headers: Map;
  headerLines: object[];
  references: string;
}
const result = await parser.parseEml({ ignoreEmbedded: true });
console.log(result.subject, result.html);

getEmailHeaders()

Extract a simplified headers object from the .eml file.

Returns: Promise<EmailHeaders>

{
  subject: string;
  from: Address[];     // [{ name: 'John', address: '[email protected]' }]
  to: Address[];
  cc?: Address[];
  date: Date;
  inReplyTo?: string;
  messageId: string;
}
const headers = await parser.getEmailHeaders();
console.log(headers.subject);
console.log(headers.from[0].name, headers.from[0].address);

getEmailBodyHtml(options?)

Get the email body as an HTML string — without headers (subject, from, to, etc.).

| Param | Type | Description | |-------|------|-------------| | options | HighlightOptions | Keyword highlighting — see HighlightOptions |

Returns: Promise<string>

const bodyHtml = await parser.getEmailBodyHtml();
fs.writeFileSync('body.html', bodyHtml);

getEmailAsHtml(options?)

Get the complete email as a full HTML document (<!DOCTYPE html>) with an Outlook-style header section and the email body. See HTML Output for details on the rendered layout.

| Param | Type | Default | Description | |-------|------|---------|-------------| | options.includeSubject | boolean | true | Set to false to hide the subject line | | options.highlightKeywords | string[] | — | See HighlightOptions | | options.highlightCaseSensitive | boolean | false | See HighlightOptions |

Returns: Promise<string> — a complete HTML5 document string

const html = await parser.getEmailAsHtml({ includeSubject: false });
fs.writeFileSync('email.html', html);

convertEmailToStream(type?, orientation?, format?, options?)

Convert the email to a readable stream in PDF, PNG, or JPEG format. Pipe the result to a writable stream to save to a file.

See Conversion Parameters for the parameter details.

Returns: Promise<Readable>

const stream = await parser.convertEmailToStream('pdf', 'landscape', 'A4');
stream.pipe(fs.createWriteStream('email.pdf'));

convertEmailToBuffer(type?, orientation?, format?, options?)

Convert the email to a Buffer in PDF, PNG, or JPEG format.

See Conversion Parameters for the parameter details.

Returns: Promise<Buffer>

const buffer = await parser.convertEmailToBuffer('png');
fs.writeFileSync('email.png', buffer);

getEmailAttachments(options?)

Extract attachments from the .eml file.

| Param | Type | Default | Description | |-------|------|---------|-------------| | options.ignoreEmbedded | boolean | false | When true, excludes embedded files (e.g. inline images) |

Returns: Promise<Attachment[]> — each attachment has filename, content (Buffer), contentType, etc.

const attachments = await parser.getEmailAttachments({ ignoreEmbedded: true });
for (const att of attachments) {
  fs.writeFileSync(att.filename, att.content);
}

getEmailEmbeddedFiles()

Extract only embedded files (e.g. inline images) — excludes regular attachments.

Returns: Promise<Attachment[]>

const embedded = await parser.getEmailEmbeddedFiles();
for (const file of embedded) {
  fs.writeFileSync(file.filename, file.content);
}

.msg Methods

parseMsg(options?)

Parse the full .msg file. Returns the complete parsed message object.

| Param | Type | Description | |-------|------|-------------| | options.highlightKeywords | string[] | Keywords to highlight — see HighlightOptions | | options.highlightCaseSensitive | boolean | Case-sensitive matching — see HighlightOptions |

Returns: Promise<object> — the parsed message with these key properties:

{
  subject: string;
  senderName: string;
  senderEmail: string;
  recipients: [{
    name: string;
    email: string;
    recipType: 'to' | 'cc';
  }];
  body: string;
  html: string;
  attachments: Attachment[];
  messageDeliveryTime: string;
  creationTime: string;
  headers: string;
  // ...and more (messageClass, internetCodepage, etc.)
}
const parser = new EmlParser(fs.createReadStream('./email.msg'));
const result = await parser.parseMsg();
console.log(result.subject, result.senderName);

getMessageHeaders()

Extract a simplified headers object from the .msg file.

Returns: Promise<MessageHeaders>

{
  subject: string;
  from: Address[];     // [{ name: 'John', address: '[email protected]' }]
  to: Address[];
  cc: Address[];
  date: string | Date;
}
const headers = await parser.getMessageHeaders();
console.log(headers.subject, headers.from[0].name);

getMessageBodyHtml(options?)

Get the message body as an HTML string — without headers (subject, from, to, etc.).

| Param | Type | Description | |-------|------|-------------| | options | HighlightOptions | Keyword highlighting — see HighlightOptions |

Returns: Promise<string>

const bodyHtml = await parser.getMessageBodyHtml();
fs.writeFileSync('body.html', bodyHtml);

getMessageAsHtml(options?)

Get the complete message as a full HTML document (<!DOCTYPE html>) with an Outlook-style header section and the message body. See HTML Output for details.

| Param | Type | Default | Description | |-------|------|---------|-------------| | options.includeSubject | boolean | true | Set to false to hide the subject line | | options.highlightKeywords | string[] | — | See HighlightOptions | | options.highlightCaseSensitive | boolean | false | See HighlightOptions |

Returns: Promise<string>

const parser = new EmlParser(fs.createReadStream('./email.msg'));
const html = await parser.getMessageAsHtml({ includeSubject: true });
fs.writeFileSync('message.html', html);

convertMessageToStream(type?, orientation?, format?, options?)

Convert the message to a readable stream in PDF, PNG, or JPEG format.

See Conversion Parameters for the parameter details.

Returns: Promise<Readable>

const parser = new EmlParser(fs.createReadStream('./email.msg'));
const stream = await parser.convertMessageToStream('pdf');
stream.pipe(fs.createWriteStream('message.pdf'));

convertMessageToBuffer(type?, orientation?, format?, options?)

Convert the message to a Buffer in PDF, PNG, or JPEG format.

See Conversion Parameters for the parameter details.

Returns: Promise<Buffer>

const parser = new EmlParser(fs.createReadStream('./email.msg'));
const buffer = await parser.convertMessageToBuffer('jpeg');
fs.writeFileSync('message.jpeg', buffer);

getMessageAttachments()

Extract attachments from the .msg file.

Returns: Promise<Attachment[]> — each attachment has filename, content (Buffer), contentType, etc.

const parser = new EmlParser(fs.createReadStream('./email.msg'));
const attachments = await parser.getMessageAttachments();
for (const att of attachments) {
  fs.writeFileSync(att.filename, att.content);
}

🎨 HTML Output

getEmailAsHtml() and getMessageAsHtml() return a complete HTML5 document with an Outlook-style header:

┌─────────────────────────────────────────────────────┐
│  [J]  John Doe  <[email protected]>                  │
│  To: alice@...; bob@...; charlie@...  17 Mar 2026   │
│  Cc: dave@...; +4 more                              │
│─────────────────────────────────────────────────────│
│                                                     │
│  (email body)                                       │
│                                                     │
└─────────────────────────────────────────────────────┘

Layout details:

  • Circular avatar with the sender's initial (color: teal)
  • From name and email address on the first row
  • To recipients and formatted date on the second row
  • Cc recipients on the third row
  • Long recipient lists (more than 3) are automatically truncated with a "+N more" toggle that expands on click — pure CSS, no JavaScript

Options:

| Option | Type | Default | Description | |--------|------|---------|-------------| | includeSubject | boolean | true | Show or hide the <h2> subject heading above the header |


🔍 Keyword Highlighting

Any method that accepts HighlightOptions can highlight keywords in the email's HTML body by wrapping matches in <mark> tags.

const html = await parser.getEmailAsHtml({
  highlightKeywords: ['invoice', 'payment due'],
  highlightCaseSensitive: false,  // default
});
// Matches are wrapped: <mark>invoice</mark>
  • Regex special characters in keywords are automatically escaped — safe to pass user input
  • When highlightCaseSensitive is false (default), matching is case-insensitive
  • Highlighting is applied to html content first; falls back to textAsHtml for plain-text emails
  • Works with parseEml, parseMsg, getEmailBodyHtml, getMessageBodyHtml, getEmailAsHtml, getMessageAsHtml, and all conversion methods

📄 License

MIT © Ankit Prakash