🧪 FreeCustom.Email — Auth Flow Testing & OTP Debugging SDK
Test, debug, and automate signup, OTP, and email-based authentication flows — with real-time observability.
FreeCustom.Email is an API-first platform for developers and QA teams to:
- ✅ Create inboxes programmatically
- ✅ Receive emails in real-time
- ✅ Extract OTPs and verification links automatically
- ✅ Debug full auth flows with timeline + latency insights
⚡ Why this exists
Testing auth flows is painful:
- ❌ Flaky email delivery
- ❌ Polling delays
- ❌ OTP parsing issues
- ❌ No visibility into failures
FreeCustom.Email solves this by giving you: 👉 real-time auth flow debugging.
📦 Installation
pip install freecustom-email
🚀 Quick Start (Auth Flow Testing)
import asyncio
from freecustom_email import FreeCustomEmail
async def main():
client = FreeCustomEmail(api_key="fce_your_api_key_here")
email = "test@ditube.info"
# 1. Create inbox (pass `is_testing=True` for zero-latency testing mode)
await client.inboxes.register(email, is_testing=True)
# 2. Start test run (NEW - Groups events in your timeline)
await client.inboxes.start_test(email, "signup-test-1")
# 3. Trigger your app (e.g. using httpx or playwright)
# await httpx.post("https://yourapp.com/api/send-otp", json={"email": email})
# 4. Wait for OTP
otp = await client.otp.wait_for(email)
print(f"OTP: {otp}")
# 5. Debug the full flow
timeline = await client.inboxes.get_timeline(email, "signup-test-1")
print(timeline)
if __name__ == "__main__":
asyncio.run(main())
🔥 Debug Your Auth Flow
Timeline (see what actually happened)
timeline = await client.inboxes.get_timeline(email)
print(timeline)
# [
# { "type": "smtp_rcpt_received", "time": 820 },
# { "type": "email_received", "time": 830 },
# { "type": "otp_extracted", "time": 835 },
# { "type": "websocket_sent", "time": 840 }
# ]
Insights (why your test failed)
insights = await client.inboxes.get_insights(email)
print(insights)
# [
# { "type": "slow_delivery", "message": "Email took >3s" },
# { "type": "multiple_detected", "message": "Multiple emails detected" }
# ]
Test Runs (group your flows)
await client.inboxes.start_test(email, "signup-test-1")
timeline = await client.inboxes.get_timeline(email, "signup-test-1")
⚡ Real-time Debugging (WebSocket)
import asyncio
from freecustom_email import FreeCustomEmail
async def main():
client = FreeCustomEmail(api_key="fce_...")
ws = client.realtime(mailbox="test@ditube.info")
@ws.on("email")
async def on_email(email):
print(f"Flow update! OTP: {email.otp}")
await ws.connect()
await ws.wait()
asyncio.run(main())
🧪 Full Playwright Example
import pytest
from playwright.async_api import Page
from freecustom_email import FreeCustomEmail
import os
client = FreeCustomEmail(api_key=os.getenv("FCE_API_KEY"))
@pytest.mark.asyncio
async def test_signup_flow(page: Page):
email = "test@ditube.info"
await client.inboxes.register(email, is_testing=True)
await client.inboxes.start_test(email, "e2e-signup")
await page.goto("https://yourapp.com/signup")
await page.fill("#email", email)
await page.click("button[type='submit']")
# Automatically waits for the email and extracts the code
otp = await client.otp.wait_for(email)
await page.fill("#otp", otp)
await page.click("#verify")
# Debugging: View exactly how long delivery took
timeline = await client.inboxes.get_timeline(email, "e2e-signup")
print("Delivery Timeline:", timeline)
🔁 Old vs New Mental Model
| Old (Temp Mail) | New (FreeCustom.Email) |
|---|---|
| receive emails | test auth flows |
| read inbox | debug flows |
| parse OTP manually | auto extract + analyze |
| polling | real-time events |
📊 Plans (Updated Meaning)
| Plan | What you get |
|---|---|
| Free | basic inbox |
| Startup | real-time emails |
| Growth | OTP + debugging |
| Enterprise | full observability |
🔥 Most Important Methods (for devs)
await client.inboxes.start_test(email, test_id)await client.otp.wait_for(email)await client.inboxes.get_timeline(email, test_id)await client.inboxes.get_insights(email)
Metadata
Release files for freecustom-email 1.0.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| freecustom_email-1.0.5.tar.gz | 14.8 kB | Without provenance | Details for freecustom_email-1.0.5.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| freecustom_email-1.0.5-py3-none-any.whl | Python 3 | none | any | Details for freecustom_email-1.0.5-py3-none-any.whl |
Total release size: 34.7 kB
Release files / freecustom_email-1.0.5.tar.gz
| Download URL | freecustom_email-1.0.5.tar.gz |
|---|---|
| Size | 14.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9e05ad330cb027db6d9e90e18b34f203e85414f848a5b431a19d6e8b48bf4bc0
|
|
BLAKE2b-256 checksum How to use checksums |
58d404e55d7fcee09e7c38abcb2a32bbcf9052224dfd5ff97d6c24b3be26a9ad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / freecustom_email-1.0.5-py3-none-any.whl
| Download URL | freecustom_email-1.0.5-py3-none-any.whl |
|---|---|
| Size | 20.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9f57670c955aa86893ef79103b5c68c191e7cbaad7ade548ab77624a01e1e3e9
|
|
BLAKE2b-256 checksum How to use checksums |
58433cf286b418b9466ea24f4b63b162a21a7971cf7c0ee34188c8312c2de191
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Security for freecustom-email 1.0.5
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.