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

mailintel

v0.4.0

Published

Email domain intelligence. Takes any email address, resolves the provider, returns IMAP/SMTP connection settings. Supports custom domains via MX lookups.

Readme

Mailintel

Resolve email providers and IMAP/SMTP settings from any email address or domain. Zero npm dependencies.

If you're building an app where users connect their email - a CRM, helpdesk, mail client, or anything that sends/receives on their behalf - you normally have to ask them to manually enter their SMTP host, IMAP port, SSL toggle, and username. Mailintel does this automatically. Give it an email or domain and it returns everything you need to connect.

Install

npm install mailintel

API

import { mailintel } from 'mailintel';

// With an email - username is resolved automatically
const result = await mailintel('[email protected]');
// result.provider             => 'google'
// result.connection.imap      => { host: 'imap.gmail.com', port: 993, secure: true }
// result.connection.username  => '[email protected]'
// result.type                 => 'business'
// result.confidence           => 'high'

// With just a domain - same result, username stays as template
const result = await mailintel('acme-corp.com');
// result.connection.username  => '%EMAILADDRESS%'

// Multiple inputs at once
const results = await mailintel(['[email protected]', 'example.com', '[email protected]']);
{
  "email": "[email protected]",
  "domain": "acme-corp.com",
  "provider": "google",
  "providerDisplayName": "Google Workspace",
  "mx": "smtp.google.com",
  "type": "business",
  "isFree": false,
  "hasMx": true,
  "connection": {
    "imap": { "host": "imap.gmail.com", "port": 993, "security": "tls" },
    "smtp": { "host": "smtp.gmail.com", "port": 465, "security": "tls" },
    "username": "[email protected]",
    "usernameTemplate": "%EMAILADDRESS%"
  },
  "confidence": "high",
  "source": "mx-lookup",
  "raw": {
    "mx": [{ "priority": 1, "exchange": "smtp.google.com" }],
    "dns": { "Status": 0, "Answer": [{ "name": "acme-corp.com", "type": 15, "TTL": 300, "data": "1 smtp.google.com." }] },
    "ispdb": null
  }
}

The API and CLI return the same structure. The CLI's --json flag outputs this exact format.

Factory

Use createMailintel() for reusable config, custom overrides, or a shared cache:

import { createMailintel } from 'mailintel';

const lookup = createMailintel({
  timeout: 3000,
  providers: {
    'megacorp.io': {
      provider: 'internal',
      imap: { host: 'imap.megacorp.io', port: 993, secure: true },
      smtp: { host: 'smtp.megacorp.io', port: 465, secure: true },
    },
  },
});

await lookup('[email protected]');  // uses override, no network call
lookup.clearCache();

Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | timeout | number | 5000 | Network request timeout (ms) | | cache | boolean | true | In-memory domain caching | | cacheTtl | number | 1800000 | Cache TTL in ms (30 min) | | mxLookup | boolean \| 'cloudflare' \| 'google' | true | true or 'cloudflare' = Cloudflare DNS, 'google' = Google DNS, false = disabled | | ispdb | boolean | true | Thunderbird ISPDB fallback | | fetch | typeof fetch | globalThis.fetch | Custom fetch (useful for proxies or testing) | | providers | Record<string, ProviderOverride> | - | Domain-to-provider overrides | | mxOverrides | Record<string, ProviderOverride> | - | MX suffix-to-provider overrides |

CLI

npx mailintel [email protected]
[email protected]

  provider      google
  domain        acme-corp.com
  type          business
  confidence    high
  mx            smtp.google.com
  source        mx-lookup

  IMAP  imap.gmail.com:993  SSL
  SMTP  smtp.gmail.com:465  SSL
  Username  [email protected]

Supports multiple emails, domain-only lookups, and JSON output:

mailintel [email protected] [email protected]    # multiple emails
mailintel acme-corp.com                            # domain-only lookup
mailintel [email protected] --json               # machine-readable JSON

CLI options

| Flag | Description | |------|-------------| | --json | Output raw JSON | | --timeout <ms> | Network timeout (default: 5000) | | --resolver <name> | DNS resolver: cloudflare (default) or google | | --no-cache | Disable caching | | --no-ispdb | Skip Thunderbird ISPDB fallback | | -h, --help | Show help | | -v, --version | Show version |

How it works

input
  └── check cache
        ├── hit  → return cached result
        └── miss
              ├── user domain override?  → return (confidence: high, source: override)
              ├── known domain?          → return (confidence: high, source: known-domain)
              └── DNS MX lookup [network]
                    ├── user MX override?   → return (confidence: high, source: mx-lookup)
                    ├── known MX pattern?   → return (confidence: high, source: mx-lookup)
                    └── Thunderbird ISPDB [network]
                          ├── found      → return (confidence: medium, source: mx-lookup)
                          └── not found  → return connection: null (confidence: low)

At most 2 HTTP requests per uncached lookup - one DNS query and one ISPDB fetch. Known domains resolve instantly with zero network calls.

How it gets the data

Every email domain has MX records in DNS that say which mail server handles its email. A Google Workspace domain points to smtp.google.com, another might point to mx.zoho.com (Zoho).

Mailintel queries these using DNS-over-HTTPS - plain HTTPS requests to public DNS resolvers, not system-level DNS calls. Works in serverless functions, edge runtimes, and anywhere fetch is available. No native modules, no UDP sockets, no special permissions.

| Service | URL | What it returns | |---------|-----|-----------------| | Cloudflare DNS (default) | cloudflare-dns.com/dns-query?name=example.com&type=MX * | MX records - which mail server handles the domain | | Google DNS (alternative) | dns.google/resolve?name=acme-corp.com&type=MX | Same MX records, different resolver | | Thunderbird ISPDB (fallback) | autoconfig.thunderbird.net/v1.1/{domain} | IMAP/SMTP settings from Mozilla's open database |

* Requires an Accept: application/dns-json header. Opening this URL in a browser returns an HTML page, not JSON. Mailintel sets this header automatically.

Rate limits: Cloudflare DNS has no published limits and is free (docs). Google DNS has undisclosed limits and returns HTTP 429 when exceeded (docs). Thunderbird ISPDB is a static file server with no published limits. The built-in cache means you'll rarely hit any of these more than once per domain.

Once the MX server is known, it's matched against ~30 provider patterns. For well-known free domains like gmail.com, the network is skipped entirely - settings come from a built-in map of ~50 known domains.

Result type

interface MailintelResult {
  email: string;                 // input email, or '' for domain-only lookups
  domain: string;
  provider: string | null;       // 'google', 'microsoft', 'zoho', etc.
  providerDisplayName: string | null; // 'Google Workspace', 'Microsoft 365', etc.
  mx: string | null;             // primary MX hostname
  type: 'free' | 'business' | 'unknown';
  isFree: boolean;
  hasMx: boolean;
  connection: {                  // null when status is not 'ok'
    imap: { host: string; port: number; security: 'tls' | 'starttls' | 'none' };
    smtp: { host: string; port: number; security: 'tls' | 'starttls' | 'none' };
    username: string;            // resolved: '[email protected]'
    usernameTemplate: string;    // raw template: '%EMAILADDRESS%'
  } | null;
  status: 'ok' | 'no-mx-records' | 'unknown-provider' | 'lookup-disabled';
  confidence: 'high' | 'medium' | 'low';
  source: 'override' | 'known-domain' | 'mx-lookup' | null;
  raw: { mx, dns, ispdb };      // raw data for debugging
}

Status

| Value | Meaning | |-------|---------| | ok | Connection settings found | | no-mx-records | DNS returned no MX records for this domain | | unknown-provider | Provider not recognized or no IMAP/SMTP settings available for it | | lookup-disabled | MX lookup was disabled and domain is not in the known list |

Username

username is the resolved value you pass directly to the mail server. When the input is a domain (no email), it stays as the raw template since there's no email to resolve.

usernameTemplate is the raw template, useful if you're building a config UI. Templates follow the Thunderbird ISPDB convention:

| Template | Resolves to | Used by | |----------|------------|---------| | %EMAILADDRESS% | [email protected] | Nearly all modern providers | | %EMAILLOCALPART% | user | Some older/self-hosted setups | | %EMAILDOMAIN% | example.com | Rare |

All built-in providers use %EMAILADDRESS%. The ISPDB fallback may return any of the three depending on what Thunderbird's database has for that provider.

Supported providers

Google, Microsoft, Yahoo, Zoho (with EU/IN/AU/JP regional variants), iCloud, Fastmail, ProtonMail, GoDaddy, Titan, OVH, IONOS, Hostinger, Yandex, AOL, Rackspace, DreamHost - plus any provider discoverable via MX records or Thunderbird ISPDB.

Contributing

Missing a provider or found incorrect settings? Open an issue or submit a PR.

License

MIT