All tests are end-to-end against real provider APIs. There are no mocks or stubs. This ensures each implementation actually works with the live service, not just a recorded response.
The trade-off: tests depend on network availability and provider uptime. See Handling Rate Limits below.
Every test follows this sequence:
- Generate — create a temporary email address.
- Send (Optional) — deliver a test message to that address via the Resend API (requires
RESEND_API_KEY). - Poll — call
get_inbox(orwait_for_email) to check for the test message (relaxed if no email was sent). - Read — fetch message details and verify content (if available).
- Delete — call
delete_emailto clean up.
Each step has a retry/backoff wrapper to account for provider latency.
cd python/
uv sync
uv run pytest tests/ --verbosecd go/
go test -v -run E2Ecd javascript/
npm install
npm testcd java/
mvn testcd php/
composer install
./vendor/bin/phpunitcd rust/
cargo test -- --nocapturecd csharp/TempMail.Tests/
dotnet test- No external CLI tools (like
swaks) are required. - The E2E tests send test emails via the Resend API and require a valid
RESEND_API_KEYenvironment variable. - If
RESEND_API_KEYis not present, the test suites will gracefully skip the actual email sending and inbox check steps (assertions on inbox contents are relaxed, and tests still pass successfully by validating the remaining actions like generating and deleting). - To enable the full testing loop:
- Sign up on resend.com.
- Create an API key.
- Place it in a
.envfile under the directory of the language wrapper you are testing, e.g.RESEND_API_KEY=re_1234567890.
Provider APIs may rate-limit or throttle requests. Tests handle this by:
- Retry with backoff — failed API calls are retried 3 times with exponential delay (1s, 3s, 5s).
- Polling intervals —
wait_for_emailuses a configurable interval (default 5 seconds) to avoid hammering the inbox endpoint. - Send delay — tests wait 10 seconds after sending a message via Resend before first polling the inbox.
- Sequential execution — provider tests run one at a time (not parallel) within each language to avoid hitting rate caps.
If a provider is down during a test run, that provider's tests will fail. Re-run after the provider recovers. There is no skip mechanism by design — a failing test means the integration is broken and should be investigated.
When adding a new provider test:
- Follow the generate → send → poll → read → delete flow.
- Use the existing retry/backoff helpers in the language's test suite.
- Test both success and error paths (unknown message ID, deleted email, etc.).
- Keep test timeouts reasonable: 60 seconds for
wait_for_email, 30 seconds for retry loops.
When adding a new language:
- Port the full test suite (all 16 providers) from the reference implementation.
- Use the language-native test framework (pytest, testing, Jest, JUnit, PHPUnit, cargo test, xUnit).
- Ensure tests can run from a single command (see above).
E2E tests require network access. In CI:
- Provide
RESEND_API_KEYas a secret or environment variable to enable full delivery testing. - Allow sufficient timeouts (provider responses can take 10-30 seconds).
- Run language test suites sequentially to avoid cross-language rate limit collisions.