Metadata-Version: 2.4
Name: emailzeno
Version: 0.1.0
Summary: Official Python client for the EmailZeno bulk SMTP email verification API
Project-URL: Homepage, https://emailzeno.com
Project-URL: Documentation, https://emailzeno.com/docs
Project-URL: Repository, https://github.com/emailzeno/emailzeno-sdks
Project-URL: Changelog, https://github.com/emailzeno/emailzeno-sdks/blob/main/sdks/python/CHANGELOG.md
Author-email: EmailZeno <support@emailzeno.com>
License-Expression: MIT
License-File: LICENSE
Keywords: email validation,email verification,emailzeno,smtp
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx<1.0,>=0.24
Provides-Extra: dev
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest>=7.4; extra == 'dev'
Requires-Dist: respx>=0.20; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Description-Content-Type: text/markdown

# EmailZeno Python SDK

Official Python client for the [EmailZeno](https://emailzeno.com) real-time SMTP email verification API.
Every probe uses `EHLO → MAIL FROM → RCPT TO → QUIT` — no `DATA` is ever sent, so your sender reputation stays clean.

![PyPI](https://img.shields.io/pypi/v/emailzeno) ![Python](https://img.shields.io/pypi/pyversions/emailzeno) ![License](https://img.shields.io/pypi/l/emailzeno)

## Install

```
pip install emailzeno
```

## Quickstart

```python
from emailzeno import EmailZeno

client = EmailZeno(api_key="ec_live_xxx")

result = client.verify("someone@example.com")
print(result.status, result.state, result.quality_score)
```

`result` exposes both EmailZeno fields (`status`, `quality_score`, `signals`, …) and Emailable-compatible
aliases (`state`, `reason`, `score`, …). Use `result.is_deliverable()` for a quick boolean.

## Bulk verification

Bulk is asynchronous: submit returns a **job handle** (not results). Poll for results.

```python
from emailzeno import EmailZeno

client = EmailZeno(api_key="ec_live_xxx")

job = client.verify_bulk(["a@example.com", "b@example.com"])  # list, or a CSV string

# Poll until the job reaches a terminal state (raises on failed/cancelled, bounded by timeout).
status = client.wait_for_job(job.job_id, poll_interval=2.0, timeout=300)

page = client.get_job_results(job.job_id, page=1, per_page=50)
for row in page.items:
    print(row)

# Or fetch the full result set as CSV:
csv_text = client.export_job_results(job.job_id)
```

> A test-mode (`ec_test_`) key returns results inline in the `verify_bulk` response (`job.results`,
> `job.test_mode is True`) instead of a job handle — check `job.test_mode` before polling.

## Error handling

```python
from emailzeno import (
    EmailZeno,
    AuthenticationError,
    InsufficientCreditsError,
    RateLimitError,
    ValidationError,
    ServiceUnavailableError,
    EmailZenoError,
)

client = EmailZeno(api_key="ec_live_xxx")

try:
    result = client.verify("someone@example.com")
except InsufficientCreditsError as e:
    print(f"Need {e.required} credits, have {e.balance}")
except RateLimitError as e:
    print(f"Rate limited, retry after {e.retry_after}s")
except ValidationError as e:
    print(e.errors)
except (AuthenticationError, ServiceUnavailableError, EmailZenoError) as e:
    print(f"Verification failed: {e.message}")
```

Exceptions: `AuthenticationError` (401), `InsufficientCreditsError` (402), `PermissionError` (403),
`ValidationError` (422), `RateLimitError` (429, exposes `retry_after`), `ServiceUnavailableError` (503/504) —
all extend `EmailZenoError`.

> **Retry note:** the SDK auto-retries only idempotent GETs. `verify` / `verify_bulk` / autoresponder pushes
> are never auto-retried (they charge credits / write to third parties) — handle their failures yourself.

## Migrating from Emailable

Change the base URL to `https://app.emailzeno.com/api` and use an `ec_live_` key. The response includes
Emailable-style `state` / `reason` / `score` fields, so most code needs no other change.

## Get an API key

Sign up at [emailzeno.com](https://emailzeno.com) → **API & Usage**. Keys are prefixed `ec_live_`
(production) or `ec_test_` (test mode — synthetic results, no credits used).

## Links

- API docs: https://emailzeno.com/docs
- All SDKs: https://emailzeno.com/docs/sdks
- OpenAPI spec: https://emailzeno.com/openapi.yaml

## License

MIT — see [LICENSE](./LICENSE).
