Skip to main content

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 script usage and integration into larger automation/test suites.


Features

  • Fully asynchronous core using httpx.AsyncClient.
  • Optional synchronous wrapper for blocking workflows.
  • Automatic XSRF token management (fetch, decode, refresh) via XsrfManager.
  • Async-aware initialization helpers (metaclasses / factories) so classes can expose __ainit__.
  • Async-safe singletons (AsyncSingletonMeta) where appropriate (HTTP client).
  • Configurable via YAML (config.yaml) with optional proxy support.
  • Clear, Google-style docstrings and type annotations.

Requirements

  • Python 3.11+ (works on 3.13).

  • Dependencies (typical):

    • httpx
    • PyYAML
    • pytest / pytest-asyncio for tests

Installation

pip install email-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; rv:89.0) Gecko/20100101 Firefox/89.0"
GMAIL_CONFIG:
  - dotGmail
  - plusGmail
PROXY: null

Notes

  • PROXY: null sets config.PROXY to None. Do not use the literal string "None"httpx will reject that as an invalid proxy URL.
  • Keep credentials / secrets out of the YAML in public repos.

Quickstart — Asynchronous (recommended)

Save the example below as examples/async_example.py.

# Copyright (C) 2025 unelected
#
# This file is part of account_generator.
#
# account_generator is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# account_generator is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with account_generator. If not, see
# <https://www.gnu.org/licenses/>.

"""
Example usage of the asynchronous AsyncEmailGenerator.

This script demonstrates:
  1. Creating the asynchronous AsyncEmailGenerator (awaitable constructor).
  2. Generating a single temporary email address.
  3. Retrieving messages for that address.
  4. Printing results.
"""
import asyncio

from emailnator.asyncio.email_generator import AsyncEmailGenerator


async def generate_email_and_get_messages() -> None:
    """
    Initialize the async generator, produce an email and fetch messages.
    """
    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(generate_email_and_get_messages())

Quickstart — Synchronous wrapper

Save as examples/sync_example.py.

# Copyright (C) 2025 unelected
#
# This file is part of account_generator.
#
# account_generator is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# account_generator is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with account_generator. If not, see
# <https://www.gnu.org/licenses/>.

"""
Synchronous example using EmailGenerator wrapper.

This demonstrates creating the blocking wrapper and using it to generate
an email and retrieve messages in a non-async program.
"""
from emailnator.sync.email_generator import EmailGenerator

def main() -> None:
    gen = EmailGenerator()
    email = gen.generate_email()
    messages = gen.get_messages(email)
    print(f"Email: {email}\nMessages: {messages}")

if __name__ == "__main__":
    main()

Public API overview

  • emailnator.asyncio.email_generator.AsyncEmailGenerator High-level async facade. Use await AsyncEmailGenerator().

  • emailnator.asyncio.generators.Generators Endpoint wrapper for /generate-email. Provides generate_email() and generate_bulk_emails().

  • emailnator.asyncio.message_getter.MessageGetter Fetch and parse messages for a given temporary email address.

  • emailnator.asyncio.builders.AsyncEmailnatorClient HTTP client singleton (uses AsyncSingletonMeta). Exposes get_client(), get_headers(), refresh_token().

  • emailnator.asyncio.builders.helpers.xsrf_token_service.XsrfManager Encapsulates XSRF lifecycle: ensure_token(), refresh(), get_token(), get_headers().

  • emailnator.config.config Loads config.yaml to config object with attributes BASE_URL, TIMEOUT, USE_HTTP2, USER_AGENT, GMAIL_CONFIG, PROXY.


Behavior notes & gotchas

  • Await the constructor if using metaclass-based __ainit__: obj = await ClassName(). If you forget await, you get a coroutine object with no attributes.
  • Proxy value in YAML must be null for no proxy. String "None" will break httpx.
  • Cloudflare / Bot protection: EmailNator may be behind challenges (403/419). Temporary addresses and token flows can be blocked by anti-bot measures — the library attempts to read XSRF-TOKEN cookie, but if the site requires JavaScript challenges, consider using a Playwright-based flow or proper proxies.
  • Event loop management: Avoid calling asyncio.run() inside already-running event loops. For synchronous wrapper, use a dedicated factory that creates its own loop safely.

Error handling & common troubleshooting

  • coroutine object has no attribute '...' — forgot await on constructor.
  • RuntimeWarning: coroutine was never awaited — coroutine was created and not awaited; search for returns of coroutines.
  • ValueError: Unknown scheme for proxy URL "None"config.PROXY is the string "None", fix YAML to null or code to coerce None.
  • HTTP 419 / Page Expired — XSRF token missing or expired; check XsrfManager and cookie extraction.
  • HTTP 403 Cloudflare — site-side bot protection.

Contributing

  • Fork, branch feature/..., implement, add tests, open PR.
  • Keep changes backwards-compatible for public API unless you bump major version.
  • Follow project style: type annotations, Google-style docstrings, tests.

License

This project is licensed under GNU Affero General Public License v3 (AGPL-3.0).


Files to include in the repo

  • README.md (this file)
  • pyproject.toml / setup.cfg with dependencies and dev extras
  • emailnator/config/config.yaml example
  • examples/async_example.py
  • examples/sync_example.py
  • tests/ with unit & async tests

Contact

Open an issue or submit a pull request for help, bug reports, or enhancements.

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

emailnator_wrapper-1.1.2.tar.gz (30.8 kB view details)

Uploaded Source

Built Distribution

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

emailnator_wrapper-1.1.2-py3-none-any.whl (43.5 kB view details)

Uploaded Python 3

File details

Details for the file emailnator_wrapper-1.1.2.tar.gz.

File metadata

  • Download URL: emailnator_wrapper-1.1.2.tar.gz
  • Upload date:
  • Size: 30.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for emailnator_wrapper-1.1.2.tar.gz
Algorithm Hash digest
SHA256 b2e8c4108973d1e167344636e0f8057877e602a95c5c72bf6b6902b40d479f85
MD5 e2e8824d6401e1ff417355804e134f91
BLAKE2b-256 0b419f82b27a16500d4fb0912142143c4dfe2875a994599d307a21182d21d99b

See more details on using hashes here.

File details

Details for the file emailnator_wrapper-1.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for emailnator_wrapper-1.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 1e7ed8d439ec39243f682a4d8fbda23bd345299d8dffa00ad6e6f41df784b72c
MD5 b3a119d7e9f33ddd75f96a77c2dd4bc4
BLAKE2b-256 2293bf275c8e1690882be86cc9579c49f077a67652cb4350361a6f7c267f8e38

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