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

emdash-plugin-anymail

v0.1.0

Published

One EmDash email plugin, any HTTP email provider — Resend, Maileroo, Mailgun, Postmark. Free-plan friendly (no SMTP, just fetch).

Downloads

41

Readme

emdash-plugin-anymail

One EmDash email plugin, any HTTP email provider.

EmDash needs an email:deliver provider before it can send recovery links, team invites, magic-link logins, or anything a plugin passes to ctx.email.send(). anymail is that provider — it talks to a transactional email HTTP API, so it works on hosts that block outbound SMTP, including the Cloudflare Workers free plan. No SMTP, no extra bindings — just fetch.

| Provider | Auth | Body | Notes | |----------|------|------|-------| | Resend | Bearer token | JSON | | | Maileroo | X-API-Key | JSON | Sending API v2 | | Mailgun | HTTP Basic | multipart | needs a sending domain; set the EU endpoint for EU accounts | | Postmark | Server token | JSON | uses the outbound message stream |

Adding another is ~25 lines — see src/core/providers/.

Install

npm add emdash-plugin-anymail
// astro.config.mjs
import { d1 } from "@emdash-cms/cloudflare";
import emdash from "emdash/astro";
import anymail from "emdash-plugin-anymail";

export default defineConfig({
  integrations: [
    emdash({
      database: d1({ binding: "DB" }),
      plugins: [anymail()],
    }),
  ],
});

Configure

Every field can be set either in the admin or as an ANYMAIL_* environment variable. When both are set, the env var wins.

| Field | Admin (Settings → Plugins → anymail) | Env var | |-------|-------------------------------------|---------| | Provider | Provider dropdown | ANYMAIL_PROVIDER (resend | maileroo | mailgun | postmark) | | API key | API key (secret) | ANYMAIL_API_KEY | | From address | From address | ANYMAIL_FROM | | From name | From name | ANYMAIL_FROM_NAME | | Sending domain (Mailgun) | Sending domain | ANYMAIL_DOMAIN | | Endpoint override | API endpoint override | ANYMAIL_ENDPOINT | | Retries | Retries | ANYMAIL_RETRIES |

Put the API key in a real secret store, not the admin field. EmDash 0.36 stores secret-type plugin settings in the database in plaintext (encryption-at-rest isn't shipped yet), so they land in D1 backups and exports. On Cloudflare: npx wrangler secret put ANYMAIL_API_KEY. In a container: set it in the environment. The admin field stays available for local dev and for hosts without a secret store.

A minimal Cloudflare setup — provider + key as secrets, the rest in the admin:

npx wrangler secret put ANYMAIL_API_KEY
echo 'ANYMAIL_API_KEY = "re_dev_..."' >> .dev.vars   # local dev
// wrangler.jsonc — non-secret defaults are fine as plain vars
"vars": { "ANYMAIL_PROVIDER": "resend", "ANYMAIL_FROM": "[email protected]" }

EmDash auto-selects anymail as the email transport once it's the only provider installed; otherwise pick it under Settings → Email.

Verify your sender domain first. Every provider requires SPF/DKIM DNS records for the domain you send From. Do that in the provider's dashboard before going live or mail will bounce or land in spam.

Standalone sender — emdash-plugin-anymail/core

The provider layer has no EmDash dependency. Use it directly from a Worker route, an API handler, a contact form — anywhere with fetch:

import { deliver } from "emdash-plugin-anymail/core";

await deliver(
  {
    from: "Support <[email protected]>",
    to: "[email protected]",
    replyTo: "[email protected]",
    subject: "We got your message",
    text: "Thanks — we'll reply within a day.",
  },
  {
    provider: "resend",
    config: { apiKey: env.RESEND_API_KEY },
    // fetch, logger, retries are all optional
  },
);

deliver() returns { provider, status, id? } on success, throws AnymailConfigError for bad input/config, and AnymailError (with .status and .responseBody) when a provider rejects the send. Transient failures (429, 5xx, network) are retried with exponential backoff, honouring Retry-After.

How it fits EmDash

EmDash system email ─┐
ctx.email.send() ────┼─▶ email:deliver hook ─▶ anymail ─▶ deliver() ─▶ provider HTTP API
                     ┘        (this plugin)      core

The plugin runs in-process (native format). It does not need Worker Loaders or the paid plan. It declares hooks.email-transport:register (required, or EmDash drops the hook) and network:request.

Development

npm install
npm test          # vitest — provider request shapes + retry logic
npm run typecheck
npm run build     # tsup → dist/ (ESM + d.ts), dual entry: "." and "./core"

Releases: bump version in package.json and src/version.ts, tag, and publish a GitHub Release — the publish workflow pushes to npm with provenance.

License

MIT © Stephan Craane