Skip to main content

Email verification infrastructure for CI pipelines — OTPs and magic links auto-extracted. No Docker, no regex, no signup.

Project description

zerodrop

PyPI version Python versions license

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 needed

Documentation · GitHub · Status

Install

pip install zerodrop

No dependencies. Python 3.8+.

Zero-Auth Mode (Local Development)

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 link

CI Pipeline Mode (pytest)

from 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"

Email Filtering

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.

OTP Auto-Extraction

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.

Parallel CI Runs

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

ZeroDrop(api_key=None, base_url=BASE_URL)

  • api_key — optional. Omit for free sandbox mode.
  • base_url — override the API base URL.

mail.generate_inbox() -> str

Returns a ready-to-use email address instantly. No network request.

mail.fetch_latest(inbox, filter_=None) -> Optional[ZeroDropEmail]

Returns the latest email or None if inbox is empty.

mail.wait_for_latest(inbox, timeout=10000, poll_interval=2.0, filter_=None) -> ZeroDropEmail

Polls until an email arrives. Raises ZeroDropTimeoutError on timeout.

  • timeout — milliseconds to wait (default: 10000)
  • poll_interval — seconds between polls (default: 2.0)
  • filter_ — optional ZeroDropFilter instance

mail.on_received(inbox, webhook_url) -> dict

Registers a webhook. Requires API key (Workspace tier).

Types

@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 link

Error Handling

from 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 vs Workspace

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

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

zerodrop-0.1.0.tar.gz (6.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

zerodrop-0.1.0-py3-none-any.whl (7.0 kB view details)

Uploaded Python 3

File details

Details for the file zerodrop-0.1.0.tar.gz.

File metadata

  • Download URL: zerodrop-0.1.0.tar.gz
  • Upload date:
  • Size: 6.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.14

File hashes

Hashes for zerodrop-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b1afa0b2726ebdde5a67040fe994fbb8a4d403896cb68d11e3b80af585cb05c9
MD5 081e74ebe45ff7b2b056595fe07b4d3b
BLAKE2b-256 8d805b40ed6f6b0eb6abc600e92db6c60555ead75c76509cb1b2ff57a8907300

See more details on using hashes here.

File details

Details for the file zerodrop-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: zerodrop-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 7.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.14

File hashes

Hashes for zerodrop-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 114c24e087f54bf790cbbef5588d14c0dc6be8881abf4d8c5c5e1f3c905669cf
MD5 c90380ef7d661f0ac53edc2d638c0942
BLAKE2b-256 f2f883955e0a0d17efdc51b92be2419bc8ce28f4a14128ed1c86d2d1f87fce4d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page