A Python wrapper for the Emailnator service providing both synchronous and asynchronous APIs.
Project description
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 |
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file emailnator_wrapper-2.1.0.tar.gz.
File metadata
- Download URL: emailnator_wrapper-2.1.0.tar.gz
- Upload date:
- Size: 34.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
214acb4d738bf16cf415e7850c2ef19a1f431312e63ca7e72ec55e657b7b857c
|
|
| MD5 |
ceb05c28fa7c2702da3b7627a76b79e3
|
|
| BLAKE2b-256 |
b1f74bfc18d777eb9241a09840f25510929748437d5f97b85c10176f389ddb94
|
File details
Details for the file emailnator_wrapper-2.1.0-py3-none-any.whl.
File metadata
- Download URL: emailnator_wrapper-2.1.0-py3-none-any.whl
- Upload date:
- Size: 46.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2924496eb2133ef099ba3e74beecd20bd99f7ed67bb79b0a013c01c7c6e52802
|
|
| MD5 |
1cdf4fbf2a1b2c4d38d07c5b2946d6a5
|
|
| BLAKE2b-256 |
e79e976fded55e57b7a74de6c9fe08c0305d4674bcea58137f0e2b798ff26457
|