mailbreeze
v0.2.6
Published
Official JavaScript SDK for MailBreeze email platform
Maintainers
Readme
MailBreeze JavaScript SDK
The official JavaScript/TypeScript SDK for the MailBreeze email platform.
Features
- Full TypeScript support - Complete type definitions for all API methods
- Native
fetch- No required dependencies; auto-falls back to optionalundicion old Node - Universal runtime - Works with Node.js (16+), Bun, and Deno
- Automatic retries - Built-in retry logic with exponential backoff
- ESM & CJS - Dual module support for all environments
Installation
# npm
npm install mailbreeze
# pnpm
pnpm add mailbreeze
# bun
bun add mailbreezeQuick Start
import { MailBreeze } from "mailbreeze";
const mailbreeze = new MailBreeze({
apiKey: "sk_live_xxx",
});
// Send an email
const result = await mailbreeze.emails.send({
from: "[email protected]",
to: "[email protected]",
subject: "Welcome!",
html: "<h1>Welcome to our platform!</h1>",
});
console.log(result.messageId);Configuration
const mailbreeze = new MailBreeze({
// Required
apiKey: "sk_live_xxx",
// Optional
baseUrl: "https://api.mailbreeze.com", // API endpoint
timeout: 30000, // Request timeout in ms (default: 30s)
maxRetries: 3, // Max retry attempts (default: 3)
authStyle: "header", // "header" (X-API-Key) or "bearer"
});Old Node.js / no global fetch
The SDK uses the global fetch, available by default on modern runtimes
(Node.js 20+, Bun, and Deno). On an older Node.js without a global fetch
(16 and 17), the SDK automatically falls back to
undici, declared as an optional
dependency so package managers install it for you. No code changes required.
If undici is not installed (e.g. it was pruned, or installed with
--omit=optional / --no-optional), the first request rejects with a
ConfigurationError (code FETCH_UNAVAILABLE); install it explicitly with
npm install undici, or pass your own fetch (below).
Node.js 16 is the floor for the auto-polyfill:
undici'sfetchrequires a globalAbortController(Node 15+). On Node < 16, install afetchpolyfill yourself and pass it via thefetchoption.
Custom fetch
Supply your own fetch-compatible implementation — useful for proxies, custom agents, or to override the auto-polyfill:
import { fetch } from "undici";
const mailbreeze = new MailBreeze({
apiKey: "sk_live_xxx",
fetch, // any fetch-compatible implementation
});The global fetch is resolved per request, so test mocks or instrumentation
(MSW, OpenTelemetry, nock) that patch globalThis.fetch after the client is
constructed are still honored.
Resources
Emails
Send and manage transactional emails.
// Send an email
const result = await mailbreeze.emails.send({
from: "[email protected]",
to: "[email protected]",
subject: "Hello",
html: "<p>Hello World!</p>",
});
// Send with a template
const result = await mailbreeze.emails.send({
from: "[email protected]",
to: ["[email protected]", "[email protected]"],
templateId: "welcome-template",
variables: { name: "John", plan: "Pro" },
});
// Send with attachments
const result = await mailbreeze.emails.send({
from: "[email protected]",
to: "[email protected]",
subject: "Your Report",
html: "<p>Please find your report attached.</p>",
attachmentIds: ["att_xxx"],
});
// List sent emails
const { data, pagination } = await mailbreeze.emails.list({
status: "delivered",
page: 1,
limit: 20,
});
// Get email details
const email = await mailbreeze.emails.get("msg_xxx");
// Get email statistics
const stats = await mailbreeze.emails.stats();
console.log(stats.successRate); // 100
console.log(stats.total); // Total emails sentAttachments
Handle email attachments using a two-step upload process.
// Step 1: Create upload URL
const upload = await mailbreeze.attachments.createUpload({
fileName: "report.pdf",
contentType: "application/pdf",
fileSize: 1024000,
});
// Step 2: Upload file directly to the presigned URL
await fetch(upload.uploadUrl, {
method: "PUT",
body: fileBuffer,
headers: { "Content-Type": "application/pdf" },
});
// Step 3: Confirm upload
await mailbreeze.attachments.confirm({ attachmentId: upload.attachmentId });
// Step 4: Use in email
await mailbreeze.emails.send({
from: "[email protected]",
to: "[email protected]",
subject: "Your report",
html: "<p>Please find the report attached.</p>",
attachmentIds: [upload.attachmentId],
});Contact Lists
Create and manage contact lists.
// Create a list
const list = await mailbreeze.lists.create({
name: "Newsletter Subscribers",
description: "Weekly newsletter recipients",
customFields: [
{ key: "company", label: "Company", type: "text" },
{ key: "plan", label: "Plan", type: "select", options: ["free", "pro", "enterprise"] },
],
});
// List all lists
const { data } = await mailbreeze.lists.list();
// Get a list
const list = await mailbreeze.lists.get("list_xxx");
// Update a list
const updated = await mailbreeze.lists.update("list_xxx", {
name: "Updated Name",
});
// Delete a list
await mailbreeze.lists.delete("list_xxx");
// Get list statistics
const stats = await mailbreeze.lists.stats("list_xxx");
console.log(stats.activeContacts);Contacts
Manage contacts within a specific list.
// Get contacts resource for a list
const contacts = mailbreeze.contacts("list_xxx");
// Create a contact
const contact = await contacts.create({
email: "[email protected]",
firstName: "John",
lastName: "Doe",
customFields: { company: "Acme Inc" },
});
// List contacts
const { data, pagination } = await contacts.list({
status: "active",
page: 1,
limit: 50,
});
// Get a contact
const contact = await contacts.get("contact_xxx");
// Update a contact
const updated = await contacts.update("contact_xxx", {
firstName: "Jane",
customFields: { plan: "enterprise" },
});
// Suppress a contact (prevents receiving emails)
await contacts.suppress("contact_xxx", "manual");
// Delete a contact
await contacts.delete("contact_xxx");Email Verification
Verify email addresses before sending.
// Verify a single email
const result = await mailbreeze.verification.verify({ email: "[email protected]" });
console.log(result.isValid);
console.log(result.result); // "clean", "dirty", "valid", "invalid", "risky", "unknown"
// Batch verification (async)
const batch = await mailbreeze.verification.batch({
emails: ["[email protected]", "[email protected]", "[email protected]"],
});
// Check batch status (for async batches)
const status = await mailbreeze.verification.get(batch.verificationId);
if (status.status === "completed") {
console.log(status.results);
console.log(status.analytics);
}
// List verification batches
const { data } = await mailbreeze.verification.list({
status: "completed",
page: 1,
});
// Get verification statistics
const stats = await mailbreeze.verification.stats();
console.log(`Verified: ${stats.totalVerified}, Valid: ${stats.totalValid}`);
console.log(`Valid percentage: ${stats.validPercentage}%`);Error Handling
The SDK provides typed error classes for different failure scenarios:
import {
MailBreezeError,
AuthenticationError,
ValidationError,
NotFoundError,
RateLimitError,
ServerError,
ConfigurationError,
} from "mailbreeze";
try {
await mailbreeze.emails.send({
from: "invalid",
to: "[email protected]",
subject: "Test",
});
} catch (error) {
if (error instanceof ValidationError) {
console.log("Validation failed:", error.message);
console.log("Details:", error.details);
} else if (error instanceof AuthenticationError) {
console.log("Invalid API key");
} else if (error instanceof RateLimitError) {
console.log(`Rate limited. Retry after ${error.retryAfter} seconds`);
} else if (error instanceof NotFoundError) {
console.log("Resource not found");
} else if (error instanceof ServerError) {
console.log("Server error:", error.statusCode);
} else if (error instanceof ConfigurationError) {
// Setup error. "INVALID_FETCH" is thrown at construction; "FETCH_UNAVAILABLE"
// is thrown on the first request (after the fetch/polyfill resolution fails).
console.log("Setup error:", error.code, error.message);
} else if (error instanceof MailBreezeError) {
console.log("API error:", error.code, error.message);
}
}Error Properties
All errors extend MailBreezeError and include:
message- Human-readable error messagecode- Machine-readable error codestatusCode- HTTP status code (when applicable)requestId- Unique request ID for debuggingdetails- Additional error details (for validation errors)
Idempotency
Prevent duplicate operations by passing an idempotency key:
const result = await mailbreeze.emails.send({
from: "[email protected]",
to: "[email protected]",
subject: "Order Confirmation",
html: "<p>Thank you for your order!</p>",
idempotencyKey: `order-confirmation-${orderId}`,
});TypeScript
All types are exported for use in your application:
import type {
SendEmailParams,
SendEmailResult,
Email,
Contact,
ContactList,
VerifyEmailResult,
PaginatedList,
} from "mailbreeze";
function sendWelcomeEmail(params: SendEmailParams): Promise<SendEmailResult> {
return mailbreeze.emails.send(params);
}Requirements
- Node.js v20 or higher recommended (or Bun/Deno). Node.js 16/17 are supported
via the optional
undicifetch polyfill — see Old Node.js / no global fetch. - A MailBreeze API key (get one here)
License
MIT
