Send emails reliably, at scale
A production-ready microservice for email delivery with built-in Dead Letter Queue support to handle failures gracefully.
Async Processing
Queue-based delivery ensures non-blocking requests
DLQ support
Failed emails are logged for Inspection and retry
Simple API
Clean REST endpoints with JSON request/response
Available Endpoints
POST/api/v1/send
Send an email message
Request Body
{
"to": "johndoe@example.com",
"subject": "Welcome to m0b mailer",
"html": "<h1>This is a test</h1>",
"appName": "Kayaws"
} Response Body
{
"success": true,
"messageId": "msg_12...xyz",
"retries": 0
}POST/api/v1/send-dlq
Send dead messages after retries for logging
Request Body
{
"to": "johndoe@example.com",
"subject": "Welcome to m0b mailer",
"html": "<h1>This is a test</h1>",
"appName": "Kayaws"
} Response Body
{
"success": "true"
}Basic Usage
Code
Create a reusable helper to send emails with QStash integration
import { Client, PublishToApiResponse } from "@upstash/qstash";
import { MAILER_URL, QSTASH_TOKEN } from "./const";
export interface SendMailOptions {
to: string;
subject: string;
html: string;
appName?: string;
}
const qstash = new Client({
token: QSTASH_TOKEN,
});
export interface MailOptions {
to: string;
subject: string;
html: string;
appName?: string;
}
export interface MailResponseType {
success: boolean;
messageId: string;
retries: number;
}
export default async function sendMail({
to,
subject,
html,
appName,
}: SendMailOptions): Promise<string> {
const res: PublishToApiResponse = (await qstash.publishJSON<MailOptions>({
url: `${MAILER_URL}/api/v1/send`,
failureCallback: `${MAILER_URL}/api/v1/send-dlq`,
body: {
to,
subject,
html,
appName,
},
})) as PublishToApiResponse;
return res.messageId;
}Developed primarily for internal use and not maintained as a public product.
Community contributions are welcome and appreciated.