dahlia/upyo

Upyo is a simple and cross-runtime library for sending email messages using SMTP and various email providers. It works on Node.js, Deno, Bun, and edge functions.

571

stars

416

commits

TypeScript

primary language

Sep 9, 2026

updated

upyo.org/
bun
deno
email
javascript
lettermint
mail
maileroo
mailgun
mailtrap
nodejs
resend
sendgrid
sendmail
ses
smtp
typescript

README

Upyo

Upyo is a cross-runtime email library that provides a unified, type-safe API for sending emails across Node.js, Deno, Bun, and edge functions. Switch between SMTP and HTTP-based providers (Lettermint, Maileroo, Mailgun, Mailtrap, Resend, SendGrid, Amazon SES) without changing your application code, while enjoying full TypeScript support, consistent error handling, and built-in testing capabilities with mock transports across all runtimes.

Here's a quick demo of sending an email using the Mailgun transport:

import { createMessage } from "@upyo/core";
import { MailgunTransport } from "@upyo/mailgun";
import fs from "node:fs/promises";
import process from "node:process";

const message = createMessage({
  from: "sender@example.com",
  to: "recipient@example.net",
  subject: "Hello from Upyo!",
  content: { text: "This is a test email." },
  attachments: [
    new File(
      [await fs.readFile("image.jpg"), "image.jpg", { type: "image/jpeg" }]
    )
  ],
});

const transport = new MailgunTransport({
  apiKey: process.env.MAILGUN_KEY!,
  domain: process.env.MAILGUN_DOMAIN!,
  region: process.env.MAILGUN_REGION as "us" | "eu",
});

const receipt = await transport.send(message);
if (receipt.successful) {
  console.log("Message sent with ID:", receipt.messageId);
} else {
  console.error("Send failed:", receipt.errorMessages.join(", "));
}

Docs

Upyo provides comprehensive documentation to help you get started quickly: https://upyo.org/.

API reference documentation for each package is available on JSR (see below).

Packages

Upyo is a monorepo which contains several packages. The main package is @upyo/core, which provides the shared types and common interfaces for sending email messages. Other packages implement specific transports for sending messages. The following is a list of the available packages:

PackageJSRnpmDescription
@upyo/coreJSRnpmShared types and interfaces for email messages
@upyo/mimeJSRnpmPortable MIME composition and DKIM signing
@upyo/smtpJSRnpmSMTP transport
@upyo/jmapJSRnpmJMAP transport (RFC 8620/8621)
@upyo/lettermintJSRnpmLettermint transport
@upyo/logtapeJSRnpmLogTape observability transport
@upyo/mailerooJSRnpmMaileroo transport
@upyo/mailtrapJSRnpmMailtrap transport
@upyo/mailgunJSRnpmMailgun transport
@upyo/plunkJSRnpmPlunk transport
@upyo/resendJSRnpmResend transport
@upyo/sendgridJSRnpmSendGrid transport
@upyo/sesJSRnpmAmazon SES transport
@upyo/retryJSRnpmRetry and backoff decorator for transports
@upyo/opentelemetryJSRnpmOpenTelemetry observability for Upyo transports
@upyo/mockJSRnpmMock transport for testing

Etymology

The name Upyo (pronounced /oo-pee-oh/) is derived from the Korean word 郵票 (upyo), which means postage stamp. It reflects the library's purpose of sending email messages, similar to how a postage stamp is used to send physical mail.

Contributors

dahlia

409 commits

moreal

1 commits

dahlia/upyo

Upyo is a simple and cross-runtime library for sending email messages using SMTP and various email providers. It works on Node.js, Deno, Bun, and edge functions.

571

stars

416

commits

TypeScript

primary language

Sep 9, 2026

updated

upyo.org/
bun
deno
email
javascript
lettermint
mail
maileroo
mailgun
mailtrap
nodejs
resend
sendgrid
sendmail
ses
smtp
typescript

README

Upyo

Upyo is a cross-runtime email library that provides a unified, type-safe API for sending emails across Node.js, Deno, Bun, and edge functions. Switch between SMTP and HTTP-based providers (Lettermint, Maileroo, Mailgun, Mailtrap, Resend, SendGrid, Amazon SES) without changing your application code, while enjoying full TypeScript support, consistent error handling, and built-in testing capabilities with mock transports across all runtimes.

Here's a quick demo of sending an email using the Mailgun transport:

import { createMessage } from "@upyo/core";
import { MailgunTransport } from "@upyo/mailgun";
import fs from "node:fs/promises";
import process from "node:process";

const message = createMessage({
  from: "sender@example.com",
  to: "recipient@example.net",
  subject: "Hello from Upyo!",
  content: { text: "This is a test email." },
  attachments: [
    new File(
      [await fs.readFile("image.jpg"), "image.jpg", { type: "image/jpeg" }]
    )
  ],
});

const transport = new MailgunTransport({
  apiKey: process.env.MAILGUN_KEY!,
  domain: process.env.MAILGUN_DOMAIN!,
  region: process.env.MAILGUN_REGION as "us" | "eu",
});

const receipt = await transport.send(message);
if (receipt.successful) {
  console.log("Message sent with ID:", receipt.messageId);
} else {
  console.error("Send failed:", receipt.errorMessages.join(", "));
}

Docs

Upyo provides comprehensive documentation to help you get started quickly: https://upyo.org/.

API reference documentation for each package is available on JSR (see below).

Packages

Upyo is a monorepo which contains several packages. The main package is @upyo/core, which provides the shared types and common interfaces for sending email messages. Other packages implement specific transports for sending messages. The following is a list of the available packages:

PackageJSRnpmDescription
@upyo/coreJSRnpmShared types and interfaces for email messages
@upyo/mimeJSRnpmPortable MIME composition and DKIM signing
@upyo/smtpJSRnpmSMTP transport
@upyo/jmapJSRnpmJMAP transport (RFC 8620/8621)
@upyo/lettermintJSRnpmLettermint transport
@upyo/logtapeJSRnpmLogTape observability transport
@upyo/mailerooJSRnpmMaileroo transport
@upyo/mailtrapJSRnpmMailtrap transport
@upyo/mailgunJSRnpmMailgun transport
@upyo/plunkJSRnpmPlunk transport
@upyo/resendJSRnpmResend transport
@upyo/sendgridJSRnpmSendGrid transport
@upyo/sesJSRnpmAmazon SES transport
@upyo/retryJSRnpmRetry and backoff decorator for transports
@upyo/opentelemetryJSRnpmOpenTelemetry observability for Upyo transports
@upyo/mockJSRnpmMock transport for testing

Etymology

The name Upyo (pronounced /oo-pee-oh/) is derived from the Korean word 郵票 (upyo), which means postage stamp. It reflects the library's purpose of sending email messages, similar to how a postage stamp is used to send physical mail.

Contributors

dahlia

409 commits

moreal

1 commits

Languages

TypeScript

99.6%