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:
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",
},
})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",
}
)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
- Templates — Use reusable email templates
- API Reference — Full endpoint documentation
- Error Codes — All possible error responses