Email verification infrastructure for CI pipelines and AI agents.
Send a verification email. Catch it at the edge. Get email.otp and email.magic_link back — auto-extracted, no regex, no Docker, no signup.
email = mail.wait_for_latest(inbox)
email.otp # "123456" — auto-extracted
email.magic_link # "https://..." — no regex neededDocumentation · GitHub · Status
pip install zerodropNo dependencies. Python 3.8+.
from zerodrop import ZeroDrop
mail = ZeroDrop()
inbox = mail.generate_inbox()
# → "swift-x7k29@zerodrop-sandbox.online"
email = mail.wait_for_latest(inbox, timeout=10000)
print(email.subject) # "Reset your password"
print(email.otp) # "123456" — auto-extracted, no regex needed
print(email.magic_link) # "https://..." — auto-extracted verification linkfrom zerodrop import ZeroDrop
mail = ZeroDrop(api_key=os.environ.get("ZERODROP_API_KEY"))
def test_password_reset(page):
inbox = mail.generate_inbox()
page.goto("/forgot-password")
page.fill('[name="email"]', inbox)
page.click('[type="submit"]')
email = mail.wait_for_latest(inbox, timeout=15000)
assert "Reset your password" in email.subject
# No regex — magic_link is auto-extracted at the edge
page.goto(email.magic_link)
assert page.url == "/dashboard"Filter emails by sender, subject, body, or extracted fields:
from zerodrop import ZeroDrop, ZeroDropFilter
mail = ZeroDrop()
# Only match emails from a specific sender
email = mail.wait_for_latest(inbox, filter_=ZeroDropFilter(
from_="noreply@yourapp.com"
))
# Only match emails with an OTP
email = mail.wait_for_latest(inbox, filter_=ZeroDropFilter(
has_otp=True
))
# Combine filters
email = mail.wait_for_latest(inbox, timeout=15000, filter_=ZeroDropFilter(
from_="noreply@yourapp.com",
subject="Verify",
has_magic_link=True
))All string filters are case-insensitive partial matches.
ZeroDrop extracts OTP codes and magic links at the edge before emails reach your test suite. No regex required.
email = mail.wait_for_latest(inbox)
email.otp # "123456" — 4-8 digit verification code
email.magic_link # "https://app.com/verify?token=abc" — verification/reset link
email.body # Full plain-text body (if you need it)Both fields are None if not detected in the email.
generate_inbox() runs locally — no network request, no throttling:
# Safe to run in parallel — generate_inbox() is local
inboxes = [mail.generate_inbox() for _ in range(50)]api_key— optional. Omit for free sandbox mode.base_url— override the API base URL.
Returns a ready-to-use email address instantly. No network request.
Returns the latest email or None if inbox is empty.
Polls until an email arrives. Raises ZeroDropTimeoutError on timeout.
timeout— milliseconds to wait (default: 10000)poll_interval— seconds between polls (default: 2.0)filter_— optionalZeroDropFilterinstance
Registers a webhook. Requires API key (Workspace tier).
@dataclass
class ZeroDropEmail:
id: str
from_: str
to: str
subject: str
body: str
raw_body: str
received_at: datetime
otp: Optional[str] # Auto-extracted OTP code (4-8 digits)
magic_link: Optional[str] # Auto-extracted verification/reset link
@dataclass
class ZeroDropFilter:
from_: Optional[str] = None # Partial match on sender address
subject: Optional[str] = None # Partial match on subject line
body: Optional[str] = None # Partial match on email body
has_otp: Optional[bool] = None # Only match emails with an OTP
has_magic_link: Optional[bool] = None # Only match emails with a magic linkfrom zerodrop import ZeroDrop, ZeroDropTimeoutError
try:
email = mail.wait_for_latest(inbox, timeout=10000)
except ZeroDropTimeoutError:
print("No email received — check your app is sending correctly")| Free | Workspace | |
|---|---|---|
| Inbox generation | ✓ | ✓ |
| OTP auto-extraction | ✓ | ✓ |
| Magic link extraction | ✓ | ✓ |
| Email filtering | ✓ | ✓ |
| Email retention | 30 min | Extended |
| Custom domains | ✗ | ✓ |
| API key | ✗ | ✓ |
| Webhooks | ✗ | ✓ |
| AI spam filter | On | Off |
Get a Workspace at zerodrop.dev
MIT