Skip to main content

PostalMime

postal-mime mascot with structure

The main class for parsing RFC822 email messages.

Import​

import PostalMime from 'postal-mime';

Static Methods​

PostalMime.parse()​

Parse an email message using the static method (recommended for most use cases).

PostalMime.parse(email, options?) -> Promise<Email>

Parameters​

ParameterTypeRequiredDescription
emailRawEmailYesThe raw email content to parse
optionsPostalMimeOptionsNoParsing configuration options

RawEmail Types​

The email parameter accepts multiple input formats:

TypeDescription
stringRaw email as a string
ArrayBufferRaw email as ArrayBuffer
ArrayBufferViewA Uint8Array, a Node.js Buffer, a DataView or any other typed array
BlobBlob or File object
ReadableStreamWeb ReadableStream of bytes, read to completion before parsing

Options​

OptionTypeDefaultDescription
rfc822AttachmentsbooleanfalseTreat message/rfc822 parts without Content-Disposition as attachments
forceRfc822AttachmentsbooleanfalseTreat all message/rfc822 parts as attachments
attachmentEncodingstring'arraybuffer'How to encode attachment content: 'arraybuffer', 'base64', or 'utf8'
maxNestingDepthnumber256Maximum MIME part nesting depth
maxHeadersSizenumber2097152Maximum total header size in bytes (2MB), counted across every part
maxPartCountnumber10000Maximum number of MIME parts in a message, the top-level part included, counted across every level
maxRfc822NestingDepthnumber10Maximum depth of inline message/rfc822 parsing; deeper messages become attachments flagged with rfc822DepthExceeded

The limit options must be non-negative integers. Any other value, including a numeric string, NaN or Infinity, rejects the parse with a TypeError, and 0 means a literal zero rather than the default.

Returns​

Promise<Email> - A Promise that resolves to the parsed email object.

Example​

import PostalMime from 'postal-mime';

const rawEmail = `From: sender@example.com
To: recipient@example.com
Subject: Hello
Content-Type: text/plain

Hello, World!`;

const email = await PostalMime.parse(rawEmail);
console.log(email.subject); // "Hello"

With Options​

const email = await PostalMime.parse(rawEmail, {
attachmentEncoding: 'base64',
maxNestingDepth: 50
});

Constructor​

new PostalMime()​

Create a new parser instance.

new PostalMime(options?)

Parameters​

ParameterTypeRequiredDescription
optionsPostalMimeOptionsNoParsing configuration options

Example​

const parser = new PostalMime({ attachmentEncoding: 'base64' });
const email = await parser.parse(rawEmail);
caution

Parser instances cannot be reused. Create a new instance for each email you parse.

Instance Methods​

parse()​

Parse an email message.

parser.parse(email) -> Promise<Email>

Parameters​

ParameterTypeRequiredDescription
emailRawEmailYesThe raw email content to parse

Returns​

Promise<Email> - A Promise that resolves to the parsed email object.

Example​

const parser = new PostalMime();
const email = await parser.parse(rawEmail);

Email Object​

The parsed email object contains the following properties:

Headers​

PropertyTypeDescription
headersHeader[]Every header in message order, duplicates included (values unfolded, not decoded)
headerLinesHeaderLine[]Array of raw header lines (original formatting)
// Unfolded header values (line breaks removed, whitespace kept; encoded words are NOT decoded)
email.headers.forEach(header => {
console.log(header.key); // Lowercase header name
console.log(header.originalKey); // Original header name preserving case
console.log(header.value); // Header value (not decoded, use decodeWords() if needed)
});

// Raw header lines (preserves original formatting for DKIM, etc.)
email.headerLines.forEach(headerLine => {
console.log(headerLine.key); // Lowercase header name
console.log(headerLine.line); // Complete raw header line
});
tip

The headerLines property is useful for DKIM signature verification and other cases where original header formatting must be preserved:

const dkimLine = email.headerLines.find(h => h.key === 'dkim-signature');
if (dkimLine) {
console.log(dkimLine.line);
// Original folding, whitespace, and encoded words are preserved
}

Where a header is exposed as a single property, such as subject, from or messageId, the first occurrence wins. The address lists to, cc, bcc and replyTo collect every occurrence in message order.

Addresses​

PropertyTypeDescription
fromAddress | undefinedFrom address
senderAddress | undefinedSender address
replyToAddress[] | undefinedReply-To addresses
toAddress[] | undefinedTo addresses
ccAddress[] | undefinedCC addresses
bccAddress[] | undefinedBCC addresses
deliveredTostring | undefinedDelivered-To address (string only)
returnPathstring | undefinedReturn-Path address (string only)

Message Identifiers​

PropertyTypeDescription
messageIdstring | undefinedMessage-ID header
inReplyTostring | undefinedIn-Reply-To header
referencesstring | undefinedReferences header

Content​

PropertyTypeDescription
subjectstring | undefinedSubject line (decoded)
datestring | undefinedDate in ISO 8601 format
textstring | undefinedPlain text content, CRLF line endings normalized to LF
htmlstring | undefinedHTML content, CRLF line endings normalized to LF
attachmentsAttachment[]Array of attachments, see Attachment

Complete Example​

import PostalMime from 'postal-mime';

async function processEmail(rawEmail) {
const email = await PostalMime.parse(rawEmail, {
attachmentEncoding: 'base64'
});

console.log('From:', email.from?.address);
console.log('To:', email.to?.map(a => a.address).join(', '));
console.log('Subject:', email.subject);
console.log('Date:', email.date);

if (email.text) {
console.log('Text content:', email.text);
}

if (email.html) {
console.log('HTML content available');
}

console.log(`Attachments: ${email.attachments.length}`);
email.attachments.forEach(att => {
console.log(` - ${att.filename} (${att.mimeType})`);
});
}

TypeScript​

import PostalMime from 'postal-mime';
import type { Email, PostalMimeOptions } from 'postal-mime';

const options: PostalMimeOptions = {
attachmentEncoding: 'base64',
maxNestingDepth: 100
};

const email: Email = await PostalMime.parse(rawEmail, options);

Error Handling​

try {
const email = await PostalMime.parse(rawEmail);
} catch (error) {
if (error instanceof TypeError) {
console.error('Invalid parser option:', error.message);
} else if (error.message.includes('nesting depth')) {
console.error('Email has too many nested parts');
} else if (error.message.includes('header size')) {
console.error('Email headers are too large');
} else if (error.message.includes('Can not reuse parser')) {
console.error('Parser instance already used');
} else {
console.error('Parsing failed:', error);
}
}

See Also​