Building a Disposable Email Generator with the Cleanbox API
Disposable email addresses are useful for one-time signups, testing, and privacy. Services like Guerrilla Mail and 10MinuteMail provide throwaway inboxes, but they are public and often blocked by websites.
With the Cleanbox API, you can build your own private disposable email system: aliases on your domain (or @cleanbox.me), with real spam filtering, that you fully control. In this guide, we build a Node.js service that creates temporary aliases, monitors them for incoming messages, and cleans up after a configurable TTL.
What we are building
- An HTTP endpoint that creates a random alias and returns the address
- A polling mechanism that checks for incoming messages
- Automatic cleanup: alias is deleted after 1 hour (configurable)
- A simple web interface to view received messages
Prerequisites
- Node.js 18+
- A Cleanbox account with API access and at least one connected mailbox
- Your API key and mailbox UUID
Step 1: API client
// cleanbox.js
const API_BASE = "https://api.cleanbox.app/v1";
const API_KEY = process.env.CLEANBOX_API_KEY;
async function api(method, path, body = null) {
const options = {
method,
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json"
}
};
if (body) options.body = JSON.stringify(body);
const res = await fetch(`${API_BASE}${path}`, options);
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(`API ${res.status}: ${err?.error?.message || res.statusText}`);
}
const contentType = res.headers.get("content-type");
if (contentType?.includes("application/json")) {
return res.json();
}
return res;
}
module.exports = { api };
Step 2: Create a temporary alias
// disposable.js
const { api } = require("./cleanbox");
const MAILBOX_UUID = process.env.CLEANBOX_MAILBOX_UUID;
const TTL_MS = 60 * 60 * 1000; // 1 hour
// In-memory store of active disposable aliases
const aliases = new Map();
async function createDisposable(label = "Disposable") {
// Create a random alias via the API
const data = await api("POST", "/aliases/random", {
mailbox: MAILBOX_UUID,
label: `[Disposable] ${label}`
});
const alias = {
uuid: data.alias.uuid,
address: data.alias.address,
created_at: Date.now(),
expires_at: Date.now() + TTL_MS,
messages: []
};
aliases.set(alias.uuid, alias);
console.log(`Created disposable: ${alias.address} (expires in ${TTL_MS / 60000}m)`);
return alias;
}
The POST /v1/aliases/random endpoint generates a random alias name on @cleanbox.me. We label it with "[Disposable]" so it is easy to identify in the dashboard.
Step 3: Poll for messages
async function checkMessages(aliasUuid) {
const alias = aliases.get(aliasUuid);
if (!alias) return [];
const data = await api("GET", `/messages?address=${aliasUuid}&status=delivered&per_page=50`);
// Filter to only new messages
const knownUuids = new Set(alias.messages.map(m => m.uuid));
const newMessages = data.data.filter(m => !knownUuids.has(m.uuid));
for (const msg of newMessages) {
// Fetch full message view (HTML + plain text)
const view = await api("GET", `/messages/${msg.uuid}/view`);
alias.messages.push({
uuid: msg.uuid,
from: msg.from_address,
from_name: msg.from_name,
subject: msg.subject,
received_at: msg.received_at,
html: view.html ? Buffer.from(view.html, "base64").toString() : null,
text: view.text || null
});
}
return newMessages;
}
We use GET /v1/messages filtered by the alias UUID and status "delivered". For each new message, we fetch the rendered HTML/text via GET /v1/messages/{uuid}/view which returns base64-encoded content.
Step 4: Cleanup expired aliases
async function cleanup() {
const now = Date.now();
for (const [uuid, alias] of aliases) {
if (now > alias.expires_at) {
try {
// Delete the alias via the API
await api("DELETE", `/addresses/${uuid}`);
aliases.delete(uuid);
console.log(`Deleted expired alias: ${alias.address}`);
} catch (err) {
console.error(`Failed to delete ${alias.address}:`, err.message);
}
}
}
}
// Run cleanup every minute
setInterval(cleanup, 60 * 1000);
The DELETE /v1/addresses/{uuid} endpoint permanently removes the alias. After deletion, emails sent to that address will bounce.
Step 5: HTTP server
const http = require("http");
const server = http.createServer(async (req, res) => {
res.setHeader("Content-Type", "application/json");
// POST /create - Create a new disposable alias
if (req.method === "POST" && req.url === "/create") {
try {
const alias = await createDisposable();
res.end(JSON.stringify({
address: alias.address,
uuid: alias.uuid,
expires_at: new Date(alias.expires_at).toISOString()
}));
} catch (err) {
res.statusCode = 500;
res.end(JSON.stringify({ error: err.message }));
}
return;
}
// GET /inbox/:uuid - Get messages for an alias
if (req.method === "GET" && req.url.startsWith("/inbox/")) {
const uuid = req.url.replace("/inbox/", "");
const alias = aliases.get(uuid);
if (!alias) {
res.statusCode = 404;
res.end(JSON.stringify({ error: "Alias not found or expired" }));
return;
}
// Check for new messages
await checkMessages(uuid);
res.end(JSON.stringify({
address: alias.address,
expires_in: Math.max(0, Math.round((alias.expires_at - Date.now()) / 1000)),
messages: alias.messages.map(m => ({
from: m.from,
from_name: m.from_name,
subject: m.subject,
received_at: m.received_at,
has_html: !!m.html
}))
}));
return;
}
res.statusCode = 404;
res.end(JSON.stringify({ error: "Not found" }));
});
server.listen(3000, () => console.log("Disposable email service on :3000"));
Using it
# Create a disposable alias
curl -X POST http://localhost:3000/create
# {"address":"k7x2m9p4qr@cleanbox.me","uuid":"...","expires_at":"..."}
# Check the inbox (poll this periodically)
curl http://localhost:3000/inbox/UUID_HERE
# {"address":"...","expires_in":3420,"messages":[...]}
Real-world use cases
- SaaS onboarding testing: Create a disposable alias, sign up for your own service, verify the welcome email arrives, check the content, delete the alias
- E2E test suites: Integrate into Playwright/Cypress tests to verify email-dependent flows (password reset, verification, invitations)
- Privacy-first signups: Give users the ability to create temporary aliases for one-time registrations through your platform
- Webhook receivers: Create an alias that receives webhook-style notifications, process them via the API, and clean up
Since these are real Cleanbox aliases with spam filtering, they are not blocked by services that reject known disposable email domains.