Mailzeno LogomailzenoDocs

Sending Emails

Mailzeno supports sending transactional emails via the SDK or REST API through your own SMTP server. This guide covers all the options available when composing and sending emails.

Basic email

The simplest way to send an email with the SDK:

send.ts
import { MailZeno } from "@mailzeno/client"

const mz = new Mailzeno(process.env.MAILZENO_API_KEY!)

const result = await mz.emails.send({
smtpId: "your_smtp_id",
from: "you@example.com",
to: "recipient@example.com",
subject: "Order Confirmation",
html: "<h1>Your order has been confirmed</h1>",
})

console.log("Message ID:", result.messageId)

HTML and plain text

You can send both HTML and plain text versions. The plain text version is used as a fallback for email clients that don't support HTML.

await mz.emails.send({
smtpId: "your_smtp_id",
from: "you@example.com",
to: "recipient@example.com",
subject: "Order Confirmation",
html: "<h1>Your order has been confirmed</h1><p>Order #12345</p>",
text: "Your order has been confirmed. Order #12345",
})

Multiple recipients

Send to multiple recipients by passing an array of email addresses:

await mz.emails.send({
smtpId: "your_smtp_id",
from: "you@example.com",
to: ["user1@example.com", "user2@example.com"],
subject: "Team Update",
html: "<p>Here's the latest update...</p>",
})

Using templates

Instead of passing subject and html, you can reference a stored template by key or ID:

// By template key
await mz.emails.send({
smtpId: "your_smtp_id",
from: "you@example.com",
to: "user@example.com",
templateKey: "welcome_email",
variables: {
  name: "Harsh",
  company: "Mailzeno",
},
})

// By template ID (UUID)
await mz.emails.send({
smtpId: "your_smtp_id",
from: "you@example.com",
to: "user@example.com",
templateId: "550e8400-e29b-41d4-a716-446655440000",
variables: {
  name: "Harsh",
},
})
Content rule

You must provide either html + subject OR a templateKey/templateId. Not both. The SDK enforces this at the type level.

Idempotency

Prevent duplicate emails by including an idempotency key. If Mailzeno receives a request with the same key, it recognizes it as a duplicate and prevents re-sending.

await mz.emails.send(
{
  smtpId: "your_smtp_id",
  from: "you@example.com",
  to: "user@example.com",
  subject: "Payment Receipt",
  html: "<h1>Thank you for your payment</h1>",
},
{
  idempotencyKey: "payment-receipt-order-12345",
}
)
Idempotency keys

The SDK sends the idempotency key as an Idempotency-Key HTTP header automatically. Use business-meaningful keys tied to your domain objects (order IDs, user IDs).

Error handling

The SDK throws MailzenoError on failure. Always wrap sends in try/catch:

import { MailZeno } from "@mailzeno/client"

const mz = new Mailzeno(process.env.MAILZENO_API_KEY!)

try {
const result = await mz.emails.send({
  smtpId: "your_smtp_id",
  from: "you@example.com",
  to: "user@example.com",
  subject: "Hello",
  html: "<h1>Hello</h1>",
})
console.log("Email sent:", result.messageId)
} catch (err) {
console.error("Message:", err.message)
console.error("Status:", err.status)       // HTTP status code
console.error("Code:", err.code)           // e.g. "rate_limit_exceeded"
console.error("Request ID:", err.requestId) // for debugging
}

Next steps