postal-mime

repository·master·Indexed 20 days ago

https://github.com/postalsys/postal-mime

An email parsing library for Node.js and browser environments, including Web Workers and Cloudflare Email Workers. It converts raw RFC822 email messages into structured JavaScript objects containing headers, recipients, attachments, and body content (HTML/Text). The library includes the PostalMime.parse() method, an addressParser utility for header strings, and a decodeWords function for RFC 2047 encoded-word syntax.

Tokens
4.5K
Snippets
20
Records
21
Agent score
64%

What's inside postal-mime

  1. Use PostalMime in Node.js

    master

    In Node.js or serverless environments, you can import PostalMime directly from the package name. You can also pass a PostalMimeOptions object to configure parsing behavior, such as attachment encoding.

    import PostalMime from 'postal-mime';
    import util from 'node:util';
    
    const options = {
        attachmentEncoding: 'base64'
    };
    
    const email = await PostalMime.parse(rawEmailData, options);
    
    // Use 'util.inspect' for pretty-printing the result
    console.log(util.inspect(email, false, 22, true));
  2. Use PostalMime with CommonJS (require)

    master

    For projects using CommonJS, postal-mime provides a compatible build that allows you to use require() for both the main class and utility functions.

    const PostalMime = require('postal-mime');
    const { addressParser, decodeWords } = require('postal-mime');
    
    const email = await PostalMime.parse(rawEmailData);
  3. Use PostalMime in the Browser

    master

    When using the library in a browser environment (including Web Workers), you should import the module directly from the src directory to ensure compatibility with browser-native ESM.

    import PostalMime from './node_modules/postal-mime/src/postal-mime.js';
    
    const email = await PostalMime.parse(rawEmailData);
  4. Use PostalMime in Cloudflare Email Workers

    master

    In Cloudflare Email Workers, you can parse the incoming email by passing message.raw to PostalMime.parse().

    import PostalMime from 'postal-mime';
    
    export default {
        async email(message, env, ctx) {
            const email = await PostalMime.parse(message.raw);
    
            console.log('Subject:', email.subject);
            console.log('HTML:', email.html);
            console.log('Text:', email.text);
        }
    };
  5. Understand the parsed message object structure

    master

    The object returned by parse() contains the following key fields:

    • headers: An array of objects { key, originalKey, value } representing all MIME headers.
    • from / sender: The parsed address object from the respective headers.
    • to / cc / bcc / replyTo: Arrays of parsed address objects.
    • deliveredTo / returnPath: The email address string from the respective headers.
    • subject / messageId / inReplyTo / references: Decoded header strings.
    • date: An ISO 8601 formatted date string (or the raw header value if invalid).
    • text: The plain text body of the email.
    • html: The HTML body of the email.
    • attachments: An array of attachment objects. Each contains:
      • filename: Decoded filename string.
      • mimeType: The MIME type (e.g., image/png).
      • disposition: The content disposition (e.g., attachment).
      • content: The actual data (type depends on attachmentEncoding).
      • encoding: The encoding used (if not arraybuffer).
      • related: Boolean if the attachment is part of a multipart/related structure.
      • contentId: The Content-ID header value if present.
      • description: The Content-Description header value if present.
    • headerLines: An array of raw header lines (reversed to match original order).

    Additionally, addressParser and decodeWords are exported utilities for manual parsing/decoding.

  6. Narrow Address types in TypeScript

    master

    Since Address is a union type (representing either a Mailbox or an address group), you can use type guards to safely access properties like address on a Mailbox.

    import type { Address, Mailbox } from 'postal-mime';
    
    function isMailbox(addr: Address): addr is Mailbox {
        return !('group' in addr) || addr.group === undefined;
    }
    
    // Usage
    if (email.from && isMailbox(email.from)) {
        console.log(email.from.address); // TypeScript knows this is a Mailbox
    }
  7. Parse email addresses with addressParser()

    master

    The addressParser() utility converts a raw address header string into an array of Address objects. If the header contains address groups, the returned array will be nested.

    Options

    • flatten (boolean, default: false): If set to true, the parser ignores address groups and returns a flat array of addresses.
    import { addressParser } from 'postal-mime';
    
    const addressStr = '=?utf-8?B?44Ko44Od44K544Kr44O844OJ?= <support@example.com>';
    console.log(addressParser(addressStr));
    // [ { name: 'エポスカード', address: 'support@example.com' } ]
  8. Decode MIME encoded-words with decodeWords()

    master

    The decodeWords() function takes a string that may contain MIME encoded-words (e.g., =?utf-8?B?...?=) and returns a Unicode string with all encoded-words decoded.

    import { decodeWords } from 'postal-mime';
    
    const encodedStr = 'Hello, =?utf-8?B?44Ko44Od44K544Kr44O844OJ?=';
    console.log(decodeWords(encodedStr));
    // Hello, エポスカード
  9. Parse emails with PostalMime.parse()

    master

    The primary method for parsing RFC822 formatted emails is PostalMime.parse(). It accepts various input types including string, ArrayBuffer/Uint8Array, Blob, Node.js Buffer, or a ReadableStream.

    Configuration Options

    You can pass an optional PostalMimeOptions object to control parsing behavior:

    • rfc822Attachments (boolean, default: false): Treat message/rfc822 attachments without a Content-Disposition as attachments.
    • forceRfc822Attachments (boolean, default: false): Treat all message/rfc822 parts as attachments.
    • attachmentEncoding (string, default: "arraybuffer"): Determines how attachment content is decoded. Options: "base64", "utf8", or "arraybuffer" (returns raw ArrayBuffer).
    • maxNestingDepth (number, default: 256): Maximum allowed MIME part nesting depth. Throws an error if exceeded.
    • maxHeadersSize (number, default: 2097152): Maximum allowed total header size in bytes (default 2MB). Throws an error if exceeded.

    Returned Email Object

    The method returns a Promise<Email> which resolves to an object containing:

    • headers: Array of { key: string, value: string } objects.
    • from, sender: Processed Address objects (can be a Mailbox or an address group).
    • to, cc, bcc, replyTo: Arrays of Address objects.
    • subject: String.
    • date: ISO 8601 formatted string.
    • html: HTML content string.
    • text: Plain text content string.
    • attachments: Array of Attachment objects containing filename, mimeType, disposition, content, etc.
    // Basic usage
    const email = await PostalMime.parse(rawEmail);
    
    // With options
    const options = {
        attachmentEncoding: 'base64',
        maxNestingDepth: 100
    };
    const email = await PostalMime.parse(rawEmail, options);
  10. Parse an email with PostalMime.parse()

    master

    The core functionality of postal-mime is the PostalMime.parse() method. It accepts a raw email message (RFC822 format) and returns a structured Email object containing headers, recipients, attachments, and body content (HTML/Text).

    import PostalMime from 'postal-mime';
    
    const email = await PostalMime.parse(`Subject: My awesome email 🤓
    Content-Type: text/html; charset=utf-8
    
    <p>Hello world 😵‍💫</p>`);
    
    console.log(email.subject); // "My awesome email 🤓"
  11. Configure PostalMime options

    master

    When instantiating PostalMime via the constructor, you can provide an options object to control parsing behavior:

    • maxNestingDepth: Maximum depth for MIME tree nesting (default: 256).
    • maxHeadersSize: Maximum size in bytes for headers (default: 2097152 / 2MB).
    • attachmentEncoding: Determines how attachment content is returned. Supported values are 'arraybuffer' (default), 'base64', and 'utf8'.
    • rfc822Attachments: Boolean determining if message/rfc822 parts are treated as inline messages or attachments.
    • forceRfc822Attachments: Boolean to force message/rfc822 parts to be treated as attachments (useful for certain report emails).

    Note: attachmentEncoding is case-insensitive and ignores hyphens, underscores, and spaces.

    const parser = new PostalMime({
      attachmentEncoding: 'base64',
      maxNestingDepth: 128
    });