emailnator-wrapper
Asynchronous and synchronous API wrapper for EmailNator.
Provides a small, well-typed SDK to generate temporary Gmail-style addresses and read incoming messages. Designed for both standalone scripts and integration into automation or testing pipelines.
🚀 Features
✅ Fully asynchronous core using httpx.AsyncClient
✅ Synchronous wrapper for blocking workflows
✅ Automatic XSRF token management via XsrfManager
✅ Async-safe singleton HTTP client (AsyncSingletonMeta)
✅ YAML-based configurable setup with optional proxy
✅ Google-style docstrings and complete type hints
✅ Thoroughly tested with pytest (tests/sync, tests/asyncio)
📚 Documentation: ReadTheDocs
🧩 Requirements
-
Python 3.9+ (tested on 3.13)
-
Dependencies:
httpxPyYAML- (for tests)
pytest,pytest-asyncio
💾 Installation
pip install emailnator-wrapper
⚙️ Configuration
emailnator/config/config.yaml (example):
BASE_URL: https://www.emailnator.com
TIMEOUT: 15
USE_HTTP2: true
USER_AGENT: "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
GMAIL_CONFIG:
- dotGmail
- plusGmail
PROXY: null
Notes:
- Use
null(not"None") to disable proxies. - Never store credentials or secrets in YAML files.
🚀 Quickstart — Asynchronous (recommended)
examples/async_example.py
import asyncio
from emailnator.asyncio.email_generator import AsyncEmailGenerator
async def main():
generator = await AsyncEmailGenerator()
email = await generator.generate_email()
messages = await generator.get_messages(email)
print(f"Email: {email}\nMessages: {messages}")
if __name__ == "__main__":
asyncio.run(main())
⚡ Quickstart — Synchronous Wrapper
examples/sync_example.py
from emailnator.sync.email_generator import EmailGenerator
def main():
gen = EmailGenerator()
email = gen.generate_email()
messages = gen.get_messages(email)
print(f"Email: {email}\nMessages: {messages}")
if __name__ == "__main__":
main()
📚 Public API Overview
| Component | Description |
|---|---|
AsyncEmailGenerator |
High-level async interface. Awaitable constructor. |
Generators |
Wraps /generate-email endpoint (bulk + single). |
MessageGetter |
Retrieves and parses inbox messages. |
AsyncEmailnatorClient |
Shared async HTTP client singleton. |
XsrfManager |
Manages XSRF lifecycle and headers. |
config |
Loads YAML into structured config attributes. |
🧩 Behavior Notes
- Always
awaitthe constructor if using async metaclass (await AsyncEmailGenerator()). - YAML
PROXY: nullmeans no proxy — don’t use"None". - Possible HTTP issues (
403,419) may stem from bot protection — consider rotating proxies. - Avoid using
asyncio.run()inside an already running loop.
🧪 Tests
Tests are divided into two categories:
tests/
├── asyncio/
│ ├── test_generators.py
│ ├── test_message_getter.py
│ └── test_email_generator.py
└── sync/
├── test_generators_sync.py
└── test_email_generator_sync.py
Run all tests
pytest -v
Run only async tests
pytest tests/asyncio -v
Run only sync tests
pytest tests/sync -v
All tests use pytest-asyncio and can be executed locally or in CI (GitHub Actions workflow provided).
📘 Documentation
Full API documentation is available on ReadTheDocs: -> https://emailnator-wrapper.readthedocs.io/en/latest/
You’ll find:
- Installation guide
- API references (async & sync layers)
- Architecture overview
- Examples & testing guide
⚠️ Troubleshooting
| Issue | Cause / Fix |
|---|---|
coroutine object has no attribute |
Forgot to await async constructor. |
RuntimeWarning: coroutine was never awaited |
Created coroutine but didn’t await it. |
ValueError: Unknown scheme for proxy URL "None" |
Fix YAML: use null instead of "None". |
| HTTP 419 / “Page Expired” | Missing or expired XSRF token — refresh it. |
| HTTP 403 | Cloudflare or bot protection triggered — use proxy. |
🤝 Contributing
- Fork the repository.
- Create a feature branch (
feature/my-change). - Add or update tests under
tests/. - Open a Pull Request.
✅ Follow code style: type hints, async-safe patterns, Google-style docstrings. ✅ Keep public API backward-compatible when possible.
📄 License
Licensed under the GNU Affero General Public License v3 (AGPL-3.0). See LICENSE for full details.
🌐 Project Links
| Resource | URL |
|---|---|
| 📘 Documentation | emailnator-wrapper.readthedocs.io |
| 🐍 PyPI | pypi.org/project/emailnator-wrapper |
Metadata
Release files for emailnator-wrapper 2.1.0
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 |
|---|---|---|---|---|
| emailnator_wrapper-2.1.0.tar.gz | 34.3 kB | Without provenance | Details for emailnator_wrapper-2.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| emailnator_wrapper-2.1.0-py3-none-any.whl | Python 3 | none | any | Details for emailnator_wrapper-2.1.0-py3-none-any.whl |
Total release size: 80.6 kB
Release files / emailnator_wrapper-2.1.0.tar.gz
| Download URL | emailnator_wrapper-2.1.0.tar.gz |
|---|---|
| Size | 34.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
214acb4d738bf16cf415e7850c2ef19a1f431312e63ca7e72ec55e657b7b857c
|
|
BLAKE2b-256 checksum How to use checksums |
b1f74bfc18d777eb9241a09840f25510929748437d5f97b85c10176f389ddb94
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / emailnator_wrapper-2.1.0-py3-none-any.whl
| Download URL | emailnator_wrapper-2.1.0-py3-none-any.whl |
|---|---|
| Size | 46.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2924496eb2133ef099ba3e74beecd20bd99f7ed67bb79b0a013c01c7c6e52802
|
|
BLAKE2b-256 checksum How to use checksums |
e79e976fded55e57b7a74de6c9fe08c0305d4674bcea58137f0e2b798ff26457
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Security for emailnator-wrapper 2.1.0
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.