DEV Community

Dishant Singh
Dishant Singh

Posted on

I Switched From mail.tm to This — Here's What I Got

I used mail.tm for about a year for disposable inbox needs in my test pipelines. Clean REST API, decent uptime, simple enough to integrate. I did not think too hard about switching.

Then I started hitting its limits in quick succession: no OTP extraction (write your own regex), no WebSocket delivery (poll and wait), no CLI (write your own wrapper), no official SDK (use a random community package that was last updated 18 months ago).

Every project that grew beyond basic message fetching required me to build and maintain tooling that should have been provided by the service. Eventually I switched to FreeCustom.Email and those problems went away. This post explains exactly what changed.


The Gap That Kept Growing

The longer I used mail.tm, the more I noticed what was missing — not bugs, but capabilities that simply did not exist:

What I wanted mail.tm FreeCustom.Email
otp extract command ✗ write your own regex ✓ built in
Real-time WebSocket delivery ✗ polling only ✓ < 200ms
Official CLI fceopen source, MIT
Official TypeScript SDK
Official Python SDK
CI/CD first-class support ✗ manual ✓ native
AI agent integration
n8n integration

mail.tm is not broken — it is just a REST API that stopped evolving. In 2026, if you are doing anything beyond basic email retrieval, you will spend more time building workarounds than writing your actual application.


The CLI Is the Biggest Difference

FreeCustom.Email ships fce — the only official CLI for any disposable email service in the world. That is not marketing — I checked. No other provider has one.

Install it:

# macOS / Linux
curl -fsSL freecustom.email/install.sh | sh

# Homebrew
brew tap DishIs/homebrew-tap && brew install fce

# Windows (Scoop)
scoop bucket add fce https://github.com/DishIs/scoop-bucket && scoop install fce

# Windows (Chocolatey)
choco install fce

# npm (all platforms)
npm install -g fcemail@latest

# Go (all platforms)
go install github.com/DishIs/fce-cli@latest
Enter fullscreen mode Exit fullscreen mode

Source and all releases: github.com/DishIs/fce-cli/releases

Login once — it opens your browser, authenticates, and saves your key to the OS keychain automatically:

fce login
# No manual token copying. Key auto-updates with your plan.
Enter fullscreen mode Exit fullscreen mode

Then:

fce dev
Enter fullscreen mode Exit fullscreen mode
  ·  Temporary inbox: dev-fy8x@ditcloud.info
  ✓  Watching for emails...
  ·  Waiting for emails… (press Ctrl+C to stop)

────────────────────────────────────────────────────
  ID    JpW3DImT3
  FROM  noreply@myapp.com
  SUBJ  Your verification code
  TIME  20:19:54
────────────────────────────────────────────────────
Enter fullscreen mode Exit fullscreen mode

Inbox created. WebSocket open. Emails appearing in real time. One command.

With mail.tm, the equivalent required: create an account, get a JWT, store it, poll GET /messages, parse the email body, extract the OTP with regex. That is a script, not a command.


OTP Extraction: mail.tm vs fce

This was my biggest pain point with mail.tm.

With mail.tm, you fetch the full message body and parse it yourself:

// What I was doing with mail.tm
const messages = await fetch('https://api.mail.tm/messages', {
  headers: { Authorization: `Bearer ${jwt}` }
}).then(r => r.json());

const body = messages['hydra:member'][0]?.text ?? '';

// Six patterns because different services format OTPs differently
const otp = body.match(/\b(\d{6})\b/)
  ?? body.match(/code[:\s]+(\d{6})/i)
  ?? body.match(/OTP[:\s]+(\d{4,8})/i)
  ?? body.match(/verification[:\s]+(\d{4,8})/i)
  // ... and it still breaks when templates change
  ?.[1];
Enter fullscreen mode Exit fullscreen mode

With FreeCustom.Email:

fce otp dev-fy8x@ditcloud.info
Enter fullscreen mode Exit fullscreen mode
────────────────────────────────────────────────
  OTP
────────────────────────────────────────────────

  OTP   ·  212342
  From  ·  noreply@myapp.com
  Subj  ·  Your verification code
  Time  ·  20:19:54
Enter fullscreen mode Exit fullscreen mode

Or in code:

const otp = await fce.otp.waitFor(inbox, { timeout: 30_000 });
// → "212342"
Enter fullscreen mode Exit fullscreen mode

The OTP extraction engine handles numeric codes, alphanumeric tokens, magic links, HTML emails, and multi-part MIME — without regex that breaks when a template changes.


Migration from mail.tm

If you are already using mail.tm in a project, migration is maybe an hour of work.

Step 1: Get an FCE account and key

curl -fsSL freecustom.email/install.sh | sh
fce login
# Key saved automatically to keychain
# For CI: export FCE_API_KEY=... (get from dashboard)
Enter fullscreen mode Exit fullscreen mode

Step 2: Replace account creation with inbox registration

Before:

// mail.tm — must create an account with a password, then get a JWT
const { id: accountId } = await fetch('https://api.mail.tm/accounts', {
  method: 'POST',
  body: JSON.stringify({ address: inbox, password: 'SomePass123' }),
}).then(r => r.json());

const { token: jwt } = await fetch('https://api.mail.tm/token', {
  method: 'POST',
  body: JSON.stringify({ address: inbox, password: 'SomePass123' }),
}).then(r => r.json());
Enter fullscreen mode Exit fullscreen mode

After:

// FCE — one call, no password, no JWT management
const fce = new FreecustomEmailClient({ apiKey: process.env.FCE_API_KEY });
await fce.inboxes.register(inbox);
Enter fullscreen mode Exit fullscreen mode

Step 3: Replace polling + regex with OTP extraction

Before:

// Poll and regex
let otp = null;
for (let i = 0; i < 30 && !otp; i++) {
  await sleep(2000);
  const { 'hydra:member': messages } = await fetch('https://api.mail.tm/messages', {
    headers: { Authorization: `Bearer ${jwt}` },
  }).then(r => r.json());
  if (messages.length > 0) {
    const match = messages[0].text.match(/\b(\d{6})\b/);
    otp = match?.[1];
  }
}
Enter fullscreen mode Exit fullscreen mode

After:

const otp = await fce.otp.waitFor(inbox, { timeout: 30_000 });
Enter fullscreen mode Exit fullscreen mode

Step 4: Replace account deletion with inbox removal

Before:

await fetch(`https://api.mail.tm/accounts/${accountId}`, {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${jwt}` },
});
Enter fullscreen mode Exit fullscreen mode

After:

await fce.inboxes.unregister(inbox);
// Or: fce inbox remove inbox@ditmail.info
Enter fullscreen mode Exit fullscreen mode

Real-Time vs Polling

mail.tm has no WebSocket option. You poll GET /messages on a loop, which means:

  • Minimum 2–5 second delay per check
  • Wasted API quota on empty responses
  • CI pipelines that feel slow for no reason

FreeCustom.Email delivers emails via WebSocket on Startup plan+. They appear in your terminal (or SDK callback) in under 200ms:

fce watch test@ditmail.info
Enter fullscreen mode Exit fullscreen mode

In CI tests, this is the difference between a 30-second polling loop and near-instant OTP receipt.


Authentication: JWT Hell vs Bearer Token

This is a minor thing but I noticed it every time. mail.tm requires you to POST credentials to get a JWT, then use that JWT for all subsequent requests. JWTs expire. You have to handle refresh. You are managing a password for a test inbox.

FreeCustom.Email uses a simple Bearer token (fce_your_key). Get it from the dashboard, set it once as FCE_API_KEY, done. Never expires unless you rotate it. No password to manage.


The Automation Ecosystem That mail.tm Has None Of

Beyond the core API, FreeCustom.Email is building something mail.tm has not touched: an automation ecosystem.

Today:

Coming Q2 2026:

  • Native Make (Integromat) modules
  • Native Zapier triggers and actions

Full details: freecustom.email/api/automation


Pricing

Plan Price WebSocket OTP extraction
Free $0
Developer $7/mo
Startup $19/mo
Growth $49/mo
Enterprise $149/mo

Full details: freecustom.email/api/pricing


Quick Decision Guide

Use case Best option
Local dev: watch for emails fce dev
Shell script / CI fce inbox add random + fce otp
Playwright / Vitest freecustom-email npm SDK
pytest / Selenium freecustom-email pip SDK
AI agent automation OpenClaw + fce login
Visual no-code workflow n8n (now) / Make or Zapier (Q2 2026)

Links


If you are currently using mail.tm, Mailinator, or Guerrilla Mail in your projects, I am curious what is holding you back from switching to something with better tooling. Is it the migration effort, pricing, or something the other services do that FCE does not?

Top comments (0)