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:
ConfigurationErrorAuthenticationErrorAuthorizationErrorValidationErrorNotFoundErrorRateLimitErrorAPIErrorConnectionErrorTimeoutErrorVerificationTimeoutError
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
Release history Release notifications | RSS feed
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 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69e11c90c16b3bef96d23a0d224f72ab5a6fc1534f6a416d9621cb004bd3f8b1
|
|
| MD5 |
9d9e66d71c817a338914f7805c37ba5e
|
|
| BLAKE2b-256 |
611b6fcba51e7ec961dc31470a4c28796f569777fd57e27242fe9eaf4a7390c5
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a7830c607f7c6c8455793de1beae98c2ec61268539d1a368cc074c6d14a9cbd
|
|
| MD5 |
1864f1e8cceea76b76e0191646bce5d7
|
|
| BLAKE2b-256 |
935b106a1a262dcdc7d5c30615f3d84f629e32808f473a5ce113c5ddf4df4505
|