Email API for Developers: Disposable Inboxes, SMTP Credentials & Webhooks
Developers need email for things that have nothing to do with communication. Automated test suites need to send and receive messages. Staging environments need isolated inboxes that don't leak to production users. SaaS products need to give each customer a real email address. Temp mail platforms need a backend that actually works.
All of these require programmatic control over email — creating inboxes, sending messages, reading responses, reacting to delivery events. This guide covers how to build each of these use cases using standard protocols and affordable infrastructure.
Why Developers Need an Email API
The word "API" in the context of email usually means one of two things: a proprietary REST API for sending and receiving (like SendGrid or Mailgun), or standard protocols — IMAP and SMTP — that every programming language already has libraries for.
Proprietary APIs are fine for transactional sending. You call an endpoint, pass a payload, and the service delivers the email. But when you need to receive email, read email, organize email, or give users their own inbox, proprietary sending APIs aren't enough. You need the full email stack.
The use cases that drive developers to seek an email API typically fall into four categories:
- Testing and QA: Verifying that your application sends the right emails, with the right content, to the right addresses
- Staging isolation: Making sure development and staging environments don't leak email to production users
- Per-user inboxes: Giving each user in your application their own email address for receiving and sending
- Building email products: Creating temp mail services, privacy tools, or email-based platforms
Each of these has different requirements, but they all share the same foundation: you need real inboxes with real credentials that you can interact with programmatically.
Three Approaches to Email in Development
Every team eventually lands on one of three strategies for handling email outside production.
1. Real Email Accounts
The simplest approach: create Gmail or Outlook accounts and hardcode them into your tests and staging environment.
This works until it doesn't. Gmail rate-limits programmatic access. Google requires OAuth2 for IMAP connections — you can't just pass a username and password. Shared credentials get rotated and break CI. Test emails leak to real inboxes. A developer accidentally sends 500 test notifications to a client's address from staging. The cost of "simple" compounds fast.
There's also the account management overhead. Creating a new Gmail account for each test environment means managing 2FA, app passwords, and Google's increasingly aggressive bot detection. It's fragile infrastructure built on a service that wasn't designed for this use case.
2. Email Sandboxes
Tools like Mailtrap intercept outbound email and display it in a dashboard. Your app thinks it's sending real email, but nothing actually gets delivered.
Sandboxes are useful for reviewing HTML templates and catching accidental sends. But they can't test real delivery. You can't verify that an email actually arrives in an inbox, gets parsed correctly by an IMAP client, or triggers a webhook. For end-to-end testing, sandboxes are incomplete.
There's also the protocol gap. Sandboxes give you SMTP (for sending) but not IMAP (for reading). Your tests can assert that an email was captured by the sandbox, but they can't test the full retrieval flow that your production code uses. Read more about this tradeoff in our SMTP testing guide.
3. On-Demand Real Inboxes
The third approach is creating real email inboxes programmatically — inboxes with actual IMAP and SMTP credentials that send and receive real email. This gives you full end-to-end coverage without the risks of using personal accounts.
This is what Reusable.Email's managed inboxes provide. Each managed inbox is a full email account with IMAP, SMTP, and POP3 access. You create it, use it in your tests or product, and it works with any email library in any language.
The key advantage is protocol compatibility. Because managed inboxes use standard IMAP and SMTP, your test code and your production code use the same libraries, the same connection patterns, and the same error handling. There's no test-only abstraction layer that hides real-world behavior.
Reusable.Email for Developers
A managed inbox on Reusable.Email costs $3 one-time — not monthly, not per-seat, not usage-based. That $3 gets you:
- IMAP access at
imap.reusable.email:993(SSL/TLS) - SMTP access at
smtp.reusable.email:587(STARTTLS) - POP3 access for clients that prefer it
- 365-day email retention
- Custom folders, spam filtering, forwarding, send/reply
- Works with Apple Mail, Thunderbird, Outlook, or any standard library
For teams building products on top of email, the whitelabel tier ($30/month) adds a REST API, webhooks for email events, an admin panel, and zero Reusable.Email branding. More on that in the white-label email service guide.
Use Case 1: Email Testing and QA
Automated tests that involve email typically need to:
- Create a fresh inbox for the test run
- Trigger an action that sends email (signup, password reset, notification)
- Read the inbox and assert on the email content
- Clean up
With managed inboxes, each test suite (or even each test) gets its own real inbox. Since the inbox supports standard IMAP, you read messages using any IMAP library — no proprietary SDK required.
The testing workflow looks like this: your CI pipeline starts, your test code connects to a managed inbox via IMAP, your application under test sends an email (password reset, welcome email, notification), and your test code polls the IMAP inbox until the email arrives. Then you parse the email, assert on its content (correct subject, correct body, correct links), and move on. If the email doesn't arrive within a timeout, the test fails — which is exactly what should happen if your email pipeline is broken.
The cost model makes this practical. Ten permanent test inboxes cost $30 total, once. Compare that to Mailtrap's $15-35/month or Mailinator's per-seat pricing. Over a year, the difference is significant.
For a detailed implementation walkthrough with Python and Node.js code, see How to Build an Email Testing Environment with a Disposable Email API.
Use Case 2: Staging Environments
Staging environments need email that behaves like production but stays isolated. The requirements:
- Outbound email from staging should never reach real users
- Developers need to inspect what was sent
- Ideally, you can test the full send-receive loop
A managed inbox per staging environment solves this. Configure your staging app to send via smtp.reusable.email:587 with that inbox's credentials. Outbound email goes to a real inbox you control. You can read it via IMAP, forward it, or just check the web interface.
Because the SMTP credentials are scoped to a specific managed inbox, there's no risk of staging email leaking to production addresses. The inbox is isolated by design.
A typical setup for a team running multiple environments:
dev@reusable.email— local development, shared across the teamstaging@reusable.email— staging environment, checked before deploysqa@reusable.email— QA testing, used by the testing teamci@reusable.email— CI pipeline, used in automated tests
Four inboxes, $12 total, permanent. Each environment's email is completely isolated from the others.
Use Case 3: Per-User Inboxes in Your SaaS App
Some products need to give users their own email address. Ticketing systems, customer service platforms, CRM tools, project management apps — all of these benefit from letting users receive email directly into the product.
The traditional approach is running your own mail server. Postfix, Dovecot, DNS records, spam filtering, deliverability monitoring, storage management. It's a full-time job.
With Reusable.Email, you create a managed inbox for each user. They get real IMAP/SMTP credentials. Your app connects via IMAP to pull messages in, or uses webhooks (whitelabel tier) to get notified in real time. The user sees email inside your product; you never touch a mail server.
At $3 per inbox, giving 1,000 users their own email address costs $3,000 — once. No monthly scaling costs. Read the full architecture in On-Demand SMTP & IMAP Credentials.
Use Case 4: Building a Temp Mail Product
If you're building a temporary email service, a privacy tool, or any product where disposable inboxes are the core feature, the whitelabel tier is designed for this.
For $30/month you get:
- Unlimited managed inboxes on your domain
- Zero Reusable.Email branding
- Full REST API for inbox creation and management
- Webhooks for real-time email events
- Usage analytics dashboard
- Admin panel for managing accounts and domains
Your users see your brand. The infrastructure is handled. You focus on the product. See the white-label email service guide for the full breakdown.
Protocol Reference: IMAP, SMTP, and POP3
Before diving into code, here's a quick reference for connecting to Reusable.Email managed inboxes.
| Protocol | Host | Port | Encryption | Purpose |
|---|---|---|---|---|
| IMAP | imap.reusable.email |
993 | SSL/TLS | Read email, search, manage folders |
| SMTP | smtp.reusable.email |
587 | STARTTLS | Send email |
| POP3 | pop.reusable.email |
995 | SSL/TLS | Download email (alternative to IMAP) |
Authentication for all protocols uses the inbox's email address as the username and the inbox password. No OAuth2, no app-specific passwords, no API keys. Standard credentials that work with every email library.
IMAP vs POP3: IMAP keeps messages on the server and supports folders, search, and flags. POP3 downloads messages and (by default) removes them from the server. For programmatic access, IMAP is almost always the better choice — it lets you search, filter, and manage state server-side.
IMAP Integration: Reading Emails Programmatically
Every managed inbox supports IMAP at imap.reusable.email:993 with SSL/TLS. Here's how to connect and read messages in Python:
import imaplib
import email
from email.header import decode_header
# Connect to Reusable.Email IMAP server
imap = imaplib.IMAP4_SSL("imap.reusable.email", 993)
imap.login("your-inbox@reusable.email", "your-password")
# Select the inbox
imap.select("INBOX")
# Search for all unseen messages
status, messages = imap.search(None, "UNSEEN")
message_ids = messages[0].split()
for msg_id in message_ids:
# Fetch the email
status, msg_data = imap.fetch(msg_id, "(RFC822)")
raw_email = msg_data[0][1]
# Parse the email
msg = email.message_from_bytes(raw_email)
subject, encoding = decode_header(msg["Subject"])[0]
if isinstance(subject, bytes):
subject = subject.decode(encoding or "utf-8")
sender = msg.get("From")
print(f"From: {sender}")
print(f"Subject: {subject}")
# Get the email body
if msg.is_multipart():
for part in msg.walk():
content_type = part.get_content_type()
if content_type == "text/plain":
body = part.get_payload(decode=True).decode()
print(f"Body: {body}")
break
else:
body = msg.get_payload(decode=True).decode()
print(f"Body: {body}")
imap.logout()
This is standard imaplib — no proprietary SDK, no vendor lock-in. Any IMAP library in any language works the same way.
Waiting for Email in Tests
In automated tests, you often need to wait for an email to arrive. Here's a polling pattern:
import time
def wait_for_email(imap, subject_contains, timeout=30, interval=2):
"""Poll IMAP inbox until an email matching the subject arrives."""
start = time.time()
while time.time() - start < timeout:
imap.select("INBOX")
status, messages = imap.search(None, "UNSEEN")
for msg_id in messages[0].split():
status, msg_data = imap.fetch(msg_id, "(RFC822)")
msg = email.message_from_bytes(msg_data[0][1])
subject = decode_header(msg["Subject"])[0][0]
if isinstance(subject, bytes):
subject = subject.decode()
if subject_contains.lower() in subject.lower():
return msg
time.sleep(interval)
raise TimeoutError(f"No email with '{subject_contains}' in subject after {timeout}s")
For real-time delivery without polling, the whitelabel tier's webhooks push events to your endpoint the moment an email arrives. More on that in How to Receive Emails via API.
SMTP Integration: Sending Emails Programmatically
Every managed inbox also has SMTP access at smtp.reusable.email:587 with STARTTLS. Here's a Node.js example using nodemailer:
const nodemailer = require("nodemailer");
const transporter = nodemailer.createTransport({
host: "smtp.reusable.email",
port: 587,
secure: false, // STARTTLS
auth: {
user: "your-inbox@reusable.email",
pass: "your-password",
},
});
async function sendTestEmail() {
const info = await transporter.sendMail({
from: "your-inbox@reusable.email",
to: "recipient@example.com",
subject: "Test email from staging",
text: "This is a test email sent via Reusable.Email SMTP.",
html: "<p>This is a <b>test email</b> sent via Reusable.Email SMTP.</p>",
});
console.log("Message sent:", info.messageId);
}
sendTestEmail();
Because this is standard SMTP, the same approach works with any language: Python's smtplib, Ruby's Net::SMTP, Go's net/smtp, PHP's PHPMailer, Java's Jakarta Mail.
Python SMTP Example
For completeness, here's the Python equivalent using smtplib:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
def send_email(to_address, subject, text_body, html_body=None):
msg = MIMEMultipart("alternative")
msg["Subject"] = subject
msg["From"] = "your-inbox@reusable.email"
msg["To"] = to_address
msg.attach(MIMEText(text_body, "plain"))
if html_body:
msg.attach(MIMEText(html_body, "html"))
with smtplib.SMTP("smtp.reusable.email", 587) as server:
server.starttls()
server.login("your-inbox@reusable.email", "your-password")
server.send_message(msg)
send_email(
"recipient@example.com",
"Order Confirmation",
"Your order #1234 has been confirmed.",
"<h1>Order Confirmed</h1><p>Your order #1234 has been confirmed.</p>",
)
Sending with Attachments
Adding attachments follows the standard MIME approach:
from email.mime.base import MIMEBase
from email import encoders
def send_with_attachment(to_address, subject, body, file_path):
msg = MIMEMultipart()
msg["Subject"] = subject
msg["From"] = "your-inbox@reusable.email"
msg["To"] = to_address
msg.attach(MIMEText(body, "plain"))
with open(file_path, "rb") as f:
attachment = MIMEBase("application", "octet-stream")
attachment.set_payload(f.read())
encoders.encode_base64(attachment)
attachment.add_header(
"Content-Disposition",
f"attachment; filename={file_path.split('/')[-1]}",
)
msg.attach(attachment)
with smtplib.SMTP("smtp.reusable.email", 587) as server:
server.starttls()
server.login("your-inbox@reusable.email", "your-password")
server.send_message(msg)
Nothing here is Reusable.Email-specific. This is the same code you'd write for any SMTP server. That's the point — no vendor lock-in, no proprietary SDK to learn and maintain.
Webhooks: Real-Time Email Events
The whitelabel tier supports webhooks that notify your application when email events occur. When an email arrives at any managed inbox under your domain, Reusable.Email sends an HTTP POST to your configured endpoint with the message details.
This is the approach for products that need real-time email processing — no polling delay, no persistent IMAP connections, no missed messages.
Typical webhook payload includes:
- Sender, recipient, subject
- Plain text and HTML body
- Attachment metadata
- Delivery timestamp
Your endpoint receives the event, processes it (extract verification codes, route to the right user, trigger application logic), and responds with a 200 status.
For a full comparison of IMAP polling vs webhooks vs API polling, see How to Receive Emails via API.
Security Considerations
When using email credentials in development, testing, and production, standard security practices apply:
Store credentials in environment variables or a secrets manager. Never hardcode inbox passwords in source code. Use your CI platform's secrets management (GitHub Actions secrets, GitLab CI variables, etc.) for automated pipelines.
Use separate inboxes per environment. Don't share the same managed inbox between development, staging, and production. Isolation prevents cross-environment contamination and limits the blast radius of compromised credentials.
Rotate passwords if compromised. If an inbox password is accidentally committed to a public repository, change it immediately through the Reusable.Email interface.
TLS everywhere. Both IMAP (port 993, SSL/TLS) and SMTP (port 587, STARTTLS) use encrypted connections. Your email content and credentials are never transmitted in plaintext.
Pricing Model for Developers
Most email testing and API services charge monthly per-seat fees. Here's how Reusable.Email compares:
| Service | Pricing Model | Cost for 10 Inboxes/Year |
|---|---|---|
| Reusable.Email | $3/inbox one-time | $30 (once) |
| Mailtrap | $15-35/month | $180-420/year |
| Mailinator | Per-seat subscription | $200+/year |
| Mailosaur | Per-seat subscription | $300+/year |
The one-time pricing means your email infrastructure costs are predictable and don't scale with team size or time. A startup and a 50-person team pay the same per inbox.
For teams that need the full API and webhook infrastructure, the whitelabel tier at $30/month includes unlimited managed inboxes — the per-inbox cost drops to zero once you're on that plan.
FAQ
How do I create inboxes programmatically?
On the whitelabel tier, you use the REST API to create managed inboxes. Each inbox gets its own IMAP/SMTP credentials. For smaller-scale use, you can create managed inboxes through the Reusable.Email web interface and use the credentials in your code.
What protocols does Reusable.Email support?
All managed inboxes support IMAP (port 993, SSL/TLS), SMTP (port 587, STARTTLS), and POP3. These are standard protocols that work with any email library or client.
Can I receive emails via webhook?
Yes, on the whitelabel tier. Webhooks send an HTTP POST to your endpoint when email arrives at any managed inbox under your domain. For other tiers, use IMAP polling. See the receive email API guide for implementation details.
How much does it cost to create 100 test inboxes?
$300, once. That's 100 managed inboxes at $3 each. No monthly fees, no renewal. If you need more than ~10 inboxes, the whitelabel tier at $30/month includes unlimited inbox creation via API, which becomes cheaper at scale.
Is there an official API?
The whitelabel tier includes a full REST API for creating and managing inboxes, domains, and accounts. For the standard managed inbox tier, you interact through standard IMAP/SMTP protocols — which are themselves an API that every programming language supports out of the box.
Can I use Reusable.Email with my existing email library?
Yes. Any library that supports IMAP and SMTP works out of the box. That includes Python's imaplib and smtplib, Node.js's nodemailer and imapflow, Ruby's net/imap and net/smtp, Go's net/smtp, PHP's PHPMailer, Java's Jakarta Mail, and many more. No SDK to install.
How long are emails retained?
Managed inboxes retain email for 365 days. After that, messages are automatically deleted. If you need longer retention, pull messages into your own storage via IMAP.
Can I use a custom domain?
Yes. Custom domains ($10/year) let you create inboxes at anything@yourdomain.com. The whitelabel tier includes custom domain support with auto-configured MX, SPF, DKIM, and DMARC.
Conclusion
Email in development doesn't need to be complicated or expensive. Standard protocols — IMAP and SMTP — have been the backbone of email for decades, and they work with every language and framework.
Reusable.Email gives developers real inboxes with real credentials at a one-time cost. No sandbox limitations, no subscription treadmill, no vendor-specific SDKs. For teams building products on email, the whitelabel tier adds the API layer and webhooks needed for production use.
Whether you're writing tests, isolating staging, giving users their own inbox, or building the next temp mail service — the infrastructure is the same: create an inbox, get credentials, connect with standard protocols.