Skip to main content

Official typed Python client for the NullMail temporary email Pro API

Project description

NullMail for Python

The official typed Python client for the NullMail Pro API. Create temporary inboxes, list received messages, open full messages, and wait for verification codes or verification URLs from synchronous or asynchronous applications.

NullMail is receive-only and intended for legitimate privacy-conscious development and testing.

Requirements

  • Python 3.9 or newer
  • A NullMail Pro API key

Installation

pip install nullmail

The lightweight CLI is implemented with Python's standard library and can be installed using:

pip install "nullmail[cli]"

Authentication

Pass the API key directly:

from nullmail import NullMail

client = NullMail(api_key="YOUR_NULLMAIL_API_KEY")

For applications and the CLI, prefer the NULLMAIL_API_KEY environment variable.

Linux and macOS:

export NULLMAIL_API_KEY="your_api_key"

Windows PowerShell:

$env:NULLMAIL_API_KEY="your_api_key"

Then initialize without arguments:

client = NullMail()

The library never places the key in URLs and redacts it from exceptions. Do not commit API keys to source control.

API origin

Version 0.1.0 uses the production NullMail API at https://www.nullmail.xyz by default. Self-hosted deployments can set another HTTPS origin explicitly:

client = NullMail(base_url="https://your-nullmail.example.com")

or:

export NULLMAIL_BASE_URL="https://your-nullmail.example.com"

HTTP is rejected for every host except localhost, 127.0.0.1, and ::1. TLS verification is always enabled and redirects are not followed, preventing credentials from being forwarded to a different host.

Create an inbox

from nullmail import NullMail

with NullMail() as client:
    inbox = client.create_inbox("build-test")
    print(inbox.email)

Allow the server to generate the username:

inbox = client.create_inbox()

Inbox creation is not automatically retried because the endpoint does not currently accept an idempotency key.

List messages

inbox = client.get_inbox("build-test@web-library.net")

for message in inbox.messages:
    print(message.subject)
    print(message.sender)
    print(message.preview)
    print(message.verification.code)
    print(message.verification.url)

Verification values may be None when they are not present in the provider's message preview.

Read a full message

message = client.get_message(
    message_id="MESSAGE_ID",
    email="build-test@web-library.net",
)

print(message.subject)
print(message.text)
print(message.html)
print(message.verification.code)
print(message.verification.url)

The email address is an optional lookup hint. Full HTML email content is untrusted; do not render it without isolation and sanitization.

Wait for a verification email

verification = client.wait_for_verification(
    email="build-test@web-library.net",
    subject_contains="Verify",
    sender_contains="example.com",
    timeout=120,
    interval=3,
)

print(verification.code)
print(verification.url)

The helper processes each message at most once, opens the full message when its summary lacks verification details, and raises VerificationTimeoutError when the deadline is reached.

Async usage

import asyncio

from nullmail import AsyncNullMail


async def main() -> None:
    async with AsyncNullMail() as client:
        inbox = await client.create_inbox("build-test")
        verification = await client.wait_for_verification(inbox.email, timeout=120)
        print(verification.code)


asyncio.run(main())

Refresh an inbox

inbox = client.refresh_inbox("build-test@web-library.net")

Refresh requests are safely retryable but remain subject to the server's plan cooldown.

Error handling

from nullmail import AuthenticationError, RateLimitError

try:
    inbox = client.create_inbox("build-test")
except AuthenticationError:
    print("The API key is invalid or revoked.")
except RateLimitError as error:
    print("Retry after:", error.retry_after)

The public hierarchy includes:

  • ConfigurationError
  • AuthenticationError
  • AuthorizationError
  • ValidationError
  • NotFoundError
  • RateLimitError
  • APIError
  • ConnectionError
  • TimeoutError
  • VerificationTimeoutError

API errors preserve safe status_code, request_id, error_code, and details attributes.

Configuration

client = NullMail(
    api_key="...",
    base_url="https://your-nullmail.example.com",
    timeout=15,
    max_retries=3,
)

Retries apply to temporary connection failures and HTTP 429, 500, 502, 503, and 504 responses for safe operations. The client uses exponential backoff and respects Retry-After.

CLI

The CLI reads the key only from NULLMAIL_API_KEY; it deliberately has no API-key argument.

nullmail create build-test
nullmail inbox build-test@web-library.net
nullmail message MESSAGE_ID --email build-test@web-library.net
nullmail wait build-test@web-library.net --subject Verify --timeout 120

Use --base-url or NULLMAIL_BASE_URL to target a self-hosted NullMail deployment.

Security recommendations

  • Store API keys in a secret manager or environment variable.
  • Never log client request headers or complete received email bodies.
  • Treat sender names, subjects, message bodies, attachments, and verification URLs as untrusted.
  • Validate a verification URL's destination before opening it.
  • Revoke API keys that may have been exposed.
  • Use HTTPS in every deployed environment.

Development

python -m venv .venv
.venv\Scripts\Activate.ps1  # Windows PowerShell
python -m pip install -e ".[dev]"
python -m pytest
python -m ruff check .
python -m ruff format --check .
python -m mypy nullmail

Tests use httpx.MockTransport and never call the live NullMail API.

Build and validate distributions:

python -m build
python -m twine check dist/*

License

MIT. See LICENSE.

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

nullmail-0.1.0.tar.gz (18.4 kB view details)

Uploaded Source

Built Distribution

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

nullmail-0.1.0-py3-none-any.whl (19.6 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for nullmail-0.1.0.tar.gz
Algorithm Hash digest
SHA256 69e11c90c16b3bef96d23a0d224f72ab5a6fc1534f6a416d9621cb004bd3f8b1
MD5 9d9e66d71c817a338914f7805c37ba5e
BLAKE2b-256 611b6fcba51e7ec961dc31470a4c28796f569777fd57e27242fe9eaf4a7390c5

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for nullmail-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8a7830c607f7c6c8455793de1beae98c2ec61268539d1a368cc074c6d14a9cbd
MD5 1864f1e8cceea76b76e0191646bce5d7
BLAKE2b-256 935b106a1a262dcdc7d5c30615f3d84f629e32808f473a5ce113c5ddf4df4505

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