Cleanbox
Features Helpdesk Blog Pricing Contact
Sign in Start free trial
api developer tutorial

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.

Ready to take control of your inbox?

Start protecting your email with Cleanbox — free plan available, no credit card required.

Get started free