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

@wraps.dev/email-check

v1.0.1

Published

Email deliverability auditing library. Checks SPF, DKIM, DMARC, MX, blacklists, TLS, and domain age. Zero dependencies — pure Node.js built-ins.

Readme

@wraps.dev/email-check

Email deliverability auditing library. Checks SPF, DKIM, DMARC, MX, blacklists, TLS, and domain age — gives you a letter grade and actionable findings.

Zero dependencies. Pure Node.js built-ins.

Install

npm install @wraps.dev/email-check

Usage

import { runEmailCheck } from "@wraps.dev/email-check";

const result = await runEmailCheck("yourdomain.com");

console.log(result.score.grade);   // "A", "B", "C", "D", or "F"
console.log(result.score.score);   // 0–100
console.log(result.spf.valid);     // true/false
console.log(result.dkim.found);    // true/false
console.log(result.dmarc.policy);  // "reject" | "quarantine" | "none" | null

Options

const result = await runEmailCheck("yourdomain.com", {
  quick: true,           // Fewer DKIM selectors, top blacklists only
  skipBlacklists: false, // Set true if port 25 is blocked in your env
  skipTls: false,        // Set true to skip MX STARTTLS checks
  dkimSelector: "s1",   // Check a specific DKIM selector
  verbose: true,         // Check all selectors, not just first match
});

Individual checks

Every check is exported individually if you only need one:

import {
  checkSpf,
  checkDkim,
  checkDmarc,
  checkMx,
  checkMxTls,
  checkBlacklist,
  checkDomainAge,
  calculateScore,
} from "@wraps.dev/email-check";

const spf = await checkSpf("yourdomain.com");
console.log(spf.record);       // "v=spf1 include:_spf.google.com ~all"
console.log(spf.lookupCount);  // DNS lookup count (RFC limit: 10)

const dkim = await checkDkim("yourdomain.com");
console.log(dkim.selectors);   // Array of found selectors with key details

const dmarc = await checkDmarc("yourdomain.com");
console.log(dmarc.policy);     // "reject" | "quarantine" | "none" | null
console.log(dmarc.pct);        // Policy percentage (100 = fully enforced)

Grading

Grades are determined by the auth triad (SPF + DKIM + DMARC). Secondary factors move your score within the grade band.

| Grade | Requirement | Score | |-------|-------------|-------| | A | SPF + DKIM + DMARC enforcing (quarantine/reject) | 90–100 | | B | All three present, DMARC not yet enforcing | 80–89 | | C | Missing one of the three | 65–79 | | D | Missing two | 35–64 | | F | Missing all three, +all SPF, or Spamhaus-listed | 0–34 |

Bonuses (MTA-STS, BIMI, clean blacklists, MX redundancy) and deductions (weak DKIM key, no DMARC reporting, new domain) adjust the score within the band.

What gets checked

| Check | What it detects | |-------|----------------| | SPF | Record existence, syntax, -all/~all/+all, lookup count (RFC 7208 limit: 10), duplicate records | | DKIM | Auto-discovers ~100 common selectors; validates key type, size, and flags | | DMARC | Policy (none/quarantine/reject), pct, alignment, reporting URIs | | MX | Records, IP resolution, PTR records, IPv6 | | MX TLS | STARTTLS support on port 25 | | Blacklists | Domain and IP checked against major DNSBLs (Spamhaus, Barracuda, SORBS, etc.) | | Domain age | Registration date via RDAP — new domains score lower |

Result shape

type EmailCheckResult = {
  domain: string;
  checkedAt: string;   // ISO timestamp
  duration: number;    // ms

  spf: SpfResult;
  dkim: DkimResult;
  dmarc: DmarcResult;
  mx: MxResult;
  mxTls: MxTlsResult;
  blacklist: BlacklistResult;
  domainAge: DomainAgeResult;
  reverseDns: ReverseDnsResult;
  ipv6: Ipv6Result;
  mtaSts: MtaStsResult;
  tlsRpt: TlsRptResult;
  dnssec: DnssecResult;
  caa: CaaResult;
  bimi: BimiResult;

  score: {
    score: number;         // 0–100
    grade: "A"|"B"|"C"|"D"|"F";
    deductions: Deduction[];
    bonuses: Bonus[];
  };
};

Full TypeScript types are exported from the package.

Exit codes

Use getExitCode(grade) to map grades to process exit codes:

import { runEmailCheck, getExitCode } from "@wraps.dev/email-check";

const result = await runEmailCheck("yourdomain.com");
process.exit(getExitCode(result.score.grade));
// A/B → 0, C/D → 1, F → 2

Requirements

Node.js 20+. No external dependencies.

License

MIT — wraps.dev