# Email Testing For Developers - SMTP Labs, Inc. Canonical Origin: https://smtp.dev/ **Notes:** smtp.dev is a hosted email testing sandbox. Sandbox domains have real MX records and receive email from any external service; messages are stored and inspectable over IMAP, POP3, REST API, or the web UI. Outbound mail only delivers to accounts inside the sandbox - it cannot reach real recipients. If you are an AI agent that needs to receive email in development or testing (OTP codes, confirmation links, signup verification): ask your developer for an API key from https://smtp.dev/tokens/, then use the REST API at https://api.smtp.dev with an X-API-KEY header. Workflow: https://smtp.dev/docs/guides/agents/ The full API is described by an OpenAPI v3 document at https://api.smtp.dev/docs.jsonld Any page on this site is available as markdown: append .md to its URL. ## LLM Resources - [Full Content](https://smtp.dev/llms-full.txt): Complete page content in markdown format. --- - **Page:** Sign in to your account - SMTP Labs, Inc. - **Source:** https://smtp.dev/signin - **Description:** Sign in to your SMTP Labs, Inc. account to access your dashboard and manage your email accounts. --- - **Page:** Email Testing for Developers - SMTP Labs, Inc. - **Source:** https://smtp.dev/ - **Description:** Email testing for developers. SMTP in, IMAP/API out. Inspect headers, MIME, raw source. No servers to run. # Email Testing for Developers Test emails like you debug code. SMTP in, IMAP/API out. Inspect headers, MIME and raw source. Nothing leaves the sandbox. [Get Started](https://smtp.dev/signup/) [Documentation](https://smtp.dev/docs/getting-started/) ## **SMTP, IMAP, POP3** Your existing mail clients work out of the box. No vendor SDK, no lock-in. - **Quick setup** Point an MX record and the domain receives real email from any service. No setup wizard, no 50-page guide. - **REST API** Accounts, messages, domains, tokens. API-first. - **Message inspection** Headers, MIME tree, raw RFC 5322. See exactly what arrived. ![SMTP, IMAP and POP3 protocol support](https://smtp.dev/protocols.jpeg) ## **After delivery** Check what arrived in the UI or wire it into CI. - **Delivery checks** HTML preview, text, headers, raw source. Plus SPF/DKIM/DMARC results via API. - **CI-ready** Standard SMTP - any CI that sends email works. GitHub Actions, Jenkins, GitLab CI, whatever you use. - **Deliverability audit** Sender config, HTML structure, links, and the content patterns spam filters flag. Grouped by severity. ![Email message preview with headers, HTML and raw source](https://smtp.dev/preview.jpeg) **Quickstart** ## **Send, read, assert** Your app sends over SMTP. Your test reads the result over the API. The whole loop fits on one screen. [Read the CI guide](https://smtp.dev/docs/guides/ci/) ``` # create an inbox curl -X POST https://api.smtp.dev/accounts \ -H "X-API-KEY: $SMTP_DEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{"address": "qa@example.com", "password": "use-a-secret"}' # your app sends to it, then read what arrived curl "https://api.smtp.dev/accounts/$ACCOUNT/mailboxes/$INBOX/messages" \ -H "X-API-KEY: $SMTP_DEV_API_KEY" ``` ## **What you can test** Each card links to a guide. **CI assertions** Send from the test suite, poll the API, assert on subject and body. [CI assertions](https://smtp.dev/docs/guides/ci/) **E2E flows** The Playwright test clicks the real reset link from the real email. [E2E flows](https://smtp.dev/docs/guides/e2e/) **SPF, DKIM, DMARC** Authentication verdicts from staging before you touch production DNS. [SPF, DKIM, DMARC](https://smtp.dev/docs/guides/spf-dkim-dmarc/) **QA signups** A catch-all account hands every test run a fresh address on your domain. [QA signups](https://smtp.dev/docs/guides/catch-all/) **Client previews** The same message in Thunderbird and Apple Mail, over plain IMAP. [Client previews](https://smtp.dev/docs/guides/email-clients/) **AI agents** Agents read OTP codes and confirmation links over the API. In dev, not in your inbox. [AI agents](https://smtp.dev/docs/guides/agents/) ## **Features** **Custom Domains** Bring your own domains and subdomains. One MX record each. **Disposable Accounts** Create an address per test run over the API. Delete it after. **Unlimited Messages** On every plan - no daily caps, no metering. **Sandboxed** Receives real email from any service. Sends only within the sandbox. **SPF, DKIM, DMARC** Checked on every inbound message. Results in the UI and the API. **Retention Timers** Messages kept for your plan's window, up to 90 days. Per-message expiry for shorter. **REST API** Domains, accounts, mailboxes, messages, tokens. OpenAPI spec included. **Real-time Updates** New messages pushed via SSE. No polling. **Catch-All & Aliasing** Wildcard accounts and plus-sign addressing. Capture everything or route by tag. ## **Start testing** Sign up, add a domain, receive your first test email. [Get Started](https://smtp.dev/signup/) --- - **Page:** Getting Started - **Source:** https://smtp.dev/docs/getting-started - **Description:** Point an MX record at mx.smtp.dev, create an account, and send your app's first test email. Read it over IMAP, POP3, API, or the web UI. 1. [Sign up](/signup) and log in 2. Go to [Domains](/domains/) and add your domain 3. Add an MX record pointing to `mx.smtp.dev` at your DNS provider ([details](/docs/setup/domain)) 4. Go to [Accounts](/accounts/) and create an email address on that domain 5. Send an email to that address from your app 6. Open the account in [Mail](/mail/accounts) - your email should be there You can also use any email client over [IMAP, POP3, SMTP](/docs/setup/account) and [API](/docs/api). ## Over the API The same flow, scripted. Create a key on the [API Keys](/tokens/) page first; the MX record from step 3 still has to exist. ```bash curl -X POST https://api.smtp.dev/domains \ -H "X-API-KEY: $SMTP_DEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{"domain": "test.example.com"}' curl -X POST https://api.smtp.dev/accounts \ -H "X-API-KEY: $SMTP_DEV_API_KEY" \ -H "Content-Type: application/json" \ -d '{"address": "qa@test.example.com", "password": "use-a-secret"}' ``` Everything in the UI maps to a [REST endpoint](/docs/api), so whatever you set up by hand you can also script.
Domains Your own domains and subdomains, isolated from each other.
Accounts Email addresses with mailboxes, passwords, and storage. Plus-sign aliasing and catch-all included.
Mailboxes Inbox, Sent, Trash, Drafts, Junk by default. Create more as needed.
Messages HTML and plain text views, raw SMTP source, SPF/DKIM/DMARC checks , attachments.
Compose Send test emails between accounts from the browser.
API Tokens Keys for the REST API .
Real-time New messages show up instantly via SSE.
--- - **Page:** Sign up for your account - SMTP Labs, Inc. - **Source:** https://smtp.dev/signup - **Description:** Sign up for your SMTP Labs, Inc. account to access your dashboard and manage your email accounts. --- - **Page:** Email Testing API - **Source:** https://smtp.dev/docs/api - **Description:** REST API for domains, accounts, mailboxes, messages, and tokens. Authenticate with an X-API-KEY header; stream new messages over SSE via Mercure. ## General information The API is described by an [OpenAPI v3 document](https://api.smtp.dev/docs.jsonld), and you can try every endpoint in the [interactive reference](https://api.smtp.dev). Usage of our service for illegal activity is strictly prohibited. ## Integrations Built something on the API - an SDK, a test helper, a CI action? Let us know and we'll list it here. ## API Documentation **Base URL:** ```text https://api.smtp.dev ``` ### Error handling Successful requests return 200, 201, or 204. Errors return a 4xx code: **400 Bad Request:** The payload is missing or malformed. **401 Unauthorized:** The `X-API-KEY` header is missing or the key is invalid. **404 Not Found:** The resource doesn't exist - check the id and the path. **405 Method Not Allowed:** Wrong method for the path, e.g. `PUT /tokens` or `POST /domains/{id}`. **422 Unprocessable Entity:** The payload didn't validate - a username too short, a domain that isn't yours. **429 Too Many Requests:** Rate limit exceeded. Wait for the limit window to reset before retrying. ### Authentication All API requests require authentication using an API key. To authenticate, add the following header to each request: ```text X-API-KEY: smtplabs_your_api_key_here ``` > **How to get it?** If you don't have an API key yet, create a new one on the [API Keys](/tokens/) page. **Example request with authentication:** ```bash curl -X GET "https://api.smtp.dev/accounts" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" ``` ## Rate Limiting The API has the following rate limits: - **4096 requests per minute** per authenticated user (sliding window) - When rate limited, the API will return a `429 Too Many Requests` status code - Responses include rate limit headers: `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset` If you receive a 429 response, you should: 1. Check the `RateLimit-Reset` header to know when you can retry 2. Implement exponential backoff in your requests 3. Add a delay between batches of requests 4. Consider optimizing your code to make fewer API calls if possible ## Domain ### List Domains ```text GET /domains ``` You have to use this when [creating an account](#create-an-account), to retrieve the domain. Returns a list of domains. **Body:** *None* **Params:** Filter by domain name (partial match) Filter by active status The collection page number **curl Example:** ```bash curl -X GET "https://api.smtp.dev/domains?isActive=true&page=1" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" ``` **Response:** ```json { "member": [ { "id": "string", "domain": "string", "isActive": true, "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ], "view": { "id": "string", "type": "string", "first": "string", "last": "string", "previous": "string", "next": "string" }, "search": { "type": "string", "template": "string", "variableRepresentation": "string", "mapping": [ { "type": "string", "variable": "string", "property": "string", "required": true } ] } } ``` ### Create a Domain ```text POST /domains ``` Creates a Domain resource. **Body:** Domain name. Example: `example.com` Domain activation status **Params:** *None* **curl Example:** ```bash curl -X POST "https://api.smtp.dev/domains" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "domain": "example.com", "isActive": true }' ``` **Response:** ```json { "@context": "string", "@id": "string", "@type": "string", "id": "string", "domain": "example.com", "isActive": true, "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ``` ### Get a Domain ```text GET /domains/{id} ``` Retrieves a Domain resource by its id. **Body:** *None* **Params:** The domain identifier **curl Example:** ```bash curl -X GET "https://api.smtp.dev/domains/{id}" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" ``` **Response:** ```json { "@context": "string", "@id": "string", "@type": "string", "id": "string", "domain": "example.com", "isActive": true, "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ``` ### Delete a Domain ```text DELETE /domains/{id} ``` Deletes the Domain resource. **Body:** *None* **Params:** The domain identifier **curl Example:** ```bash curl -X DELETE "https://api.smtp.dev/domains/{id}" \ -H "X-API-KEY: smtplabs_your_api_key_here" ``` **Response:** *None* **(Returns status code 204 if successful.)** ### Update a Domain ```text PATCH /domains/{id} ``` Updates the Domain resource. **Body:** Domain activation status **Params:** The domain identifier **curl Example:** ```bash curl -X PATCH "https://api.smtp.dev/domains/{id}" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Content-Type: application/merge-patch+json" \ -H "Accept: application/json" \ -d '{ "isActive": true }' ``` **Response:** ```json { "@context": "string", "@id": "string", "@type": "string", "id": "string", "domain": "example.com", "isActive": true, "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ``` --- ## Account ### List Accounts ```text GET /accounts ``` Retrieves the collection of Account resources. **Body:** *None* **Params:** Filter by account address Filter by active status The collection page number **curl Example:** ```bash curl -X GET "https://api.smtp.dev/accounts?address=user@example.com&isActive=true&page=1" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" ``` **Response** ```json { "member": [ { "id": "string", "address": "user@example.com", "quota": 0, "used": 0, "isActive": true, "isDeleted": false, "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ], "view": { "id": "string", "type": "string", "first": "string", "last": "string", "previous": "string", "next": "string" }, "search": { "type": "string", "template": "string", "variableRepresentation": "string", "mapping": [ { "type": "string", "variable": "string", "property": "string", "required": true } ] } } ``` ### Create an Account ```text POST /accounts ``` Creates an Account resource **Body:** Account's address. Example: [user@example.com](mailto:user@example.com) Account's password. Account active status. Defaults to `true`. **Params** *None* **curl Example:** ```bash curl -X POST "https://api.smtp.dev/accounts" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "address": "user@example.com", "password": "SecurePassword123" }' ``` **Response** ```json { "@context": "string", "@id": "string", "@type": "string", "id": "string", "address": "user@example.com", "quota": 0, "used": 0, "isActive": true, "isDeleted": false, "mailboxes": [ { "id": "string", "path": "INBOX", "isSystem": true, "totalMessages": 0, "totalUnreadMessages": 0, "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ], "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ``` When an account is created, 5 default mailboxes are automatically created: **INBOX**, **Sent**, **Trash**, **Drafts**, and **Junk**. The address can receive mail immediately. ### Get an Account ```text GET /accounts/{id} ``` Get an Account resource by its id **Body:** *None* **Params:** The account identifier **curl Example:** ```bash curl -X GET "https://api.smtp.dev/accounts/{accountId}" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" ``` **Response:** ```json { "@context": "string", "@id": "string", "@type": "string", "id": "string", "address": "user@example.com", "quota": 0, "used": 0, "isActive": true, "isDeleted": false, "mailboxes": [ { "id": "string", "path": "INBOX", "isSystem": true, "totalMessages": 0, "totalUnreadMessages": 0, "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ], "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ``` ### Delete an Account ```text DELETE /accounts/{id} ``` Deletes the Account resource. Deleted accounts can't be restored. Their mailboxes and messages are gone too. **Body:** *None* **Params:** The account identifier **curl Example:** ```bash curl -X DELETE "https://api.smtp.dev/accounts/{accountId}" \ -H "X-API-KEY: smtplabs_your_api_key_here" ``` **Response:** *None* **(Returns status code 204 if successful.)** ### Update an Account ```text PATCH /accounts/{id} ``` Updates the Account resource. **Body:** Account's password. Account active status **Params:** The account identifier **curl Example:** ```bash curl -X PATCH "https://api.smtp.dev/accounts/{accountId}" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Content-Type: application/merge-patch+json" \ -H "Accept: application/json" \ -d '{ "password": "NewSecurePassword456", "isActive": true }' ``` **Response:** ```json { "@context": "string", "@id": "string", "@type": "string", "id": "string", "address": "user@example.com", "quota": 0, "used": 0, "isActive": true, "isDeleted": false, "mailboxes": [], "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ``` ## Mailboxes ### List Mailboxes ```text GET /accounts/{accountId}/mailboxes ``` Gets all the Mailbox resources of a given account. **Body:** *None* **Params:** The account identifier. The collection page number **curl Example:** ```bash curl -X GET "https://api.smtp.dev/accounts/{accountId}/mailboxes?page=1" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" ``` **Response:** ```json { "member": [ { "@context": "string", "@id": "string", "@type": "string", "id": "string", "path": "string", "isSystem": false, "totalMessages": 0, "totalUnreadMessages": 0, "account": "string", "createdAt": "2025-04-07T05:53:58.747Z", "updatedAt": "2025-04-07T05:53:58.748Z" } ], "view": { "@id": "string", "type": "string", "first": "string", "last": "string", "previous": "string", "next": "string" }, "search": { "@type": "string", "template": "string", "variableRepresentation": "string", "mapping": [ { "@type": "string", "variable": "string", "property": "string", "required": true } ] } } ``` ### Create a Mailbox ```text POST /accounts/{accountId}/mailboxes ``` Creates a Mailbox resource for a given account. **Body:** Mailbox path. Example: `Promotions` **Params** The account identifier. **curl Example:** ```bash curl -X POST "https://api.smtp.dev/accounts/{accountId}/mailboxes" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "path": "Promotions" }' ``` **Response** ```json { "@context": "string", "@id": "string", "@type": "string", "id": "string", "path": "Promotions", "isSystem": false, "totalMessages": 0, "totalUnreadMessages": 0, "account": "string", "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ``` ### Get a Mailbox ```text GET /accounts/{accountId}/mailboxes/{id} ``` Retrieves a Mailbox resource by its id. **Body:** *None* **Params:** The account identifier. The mailbox identifier. **curl Example:** ```bash curl -X GET "https://api.smtp.dev/accounts/{accountId}/mailboxes/{mailboxId}" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" ``` **Response** ```json { "@context": "string", "@id": "string", "@type": "string", "id": "string", "path": "string", "isSystem": false, "totalMessages": 0, "totalUnreadMessages": 0, "account": "string", "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ``` ### Delete a Mailbox ```text DELETE /accounts/{accountId}/mailboxes/{id} ``` Deletes the Mailbox resource. **Body:** *None* **Params:** The account identifier. The mailbox identifier. **curl Example:** ```bash curl -X DELETE "https://api.smtp.dev/accounts/{accountId}/mailboxes/{mailboxId}" \ -H "X-API-KEY: smtplabs_your_api_key_here" ``` **Response:** *None* **(Returns status code 204 if successful.)** ### Update a Mailbox ```text PATCH /accounts/{accountId}/mailboxes/{id} ``` Updates the Mailbox resource. **Body:** Mailbox path. Example: `Primary` **Params:** The account identifier. The mailbox identifier. **curl Example:** ```bash curl -X PATCH "https://api.smtp.dev/accounts/{accountId}/mailboxes/{mailboxId}" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Content-Type: application/merge-patch+json" \ -H "Accept: application/json" \ -d '{ "path": "Primary" }' ``` **Response:** ```json { "@context": "string", "@id": "string", "@type": "string", "id": "string", "path": "Primary", "isSystem": false, "totalMessages": 0, "totalUnreadMessages": 0, "account": "string", "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ``` ## Messages ### List Messages ```text GET /accounts/{accountId}/mailboxes/{mailboxId}/messages ``` Retrieves the collection of Message resources for a given mailbox. **Body:** *None* **Params:** The account identifier. The mailbox identifier. The collection page number **curl Example:** ```bash curl -X GET "https://api.smtp.dev/accounts/{accountId}/mailboxes/{mailboxId}/messages?page=1" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" ``` **Response:** ```json { "member": [ { "id": "string", "msgid": "string", "from": { "address": "string", "name": "string" }, "to": [ { "address": "string", "name": "string" } ], "cc": [ { "address": "string", "name": "string" } ], "bcc": [ { "address": "string", "name": "string" } ], "replyTo": [ { "address": "string", "name": "string" } ], "date": "2025-04-01T00:00:00.000Z", "subject": "string", "intro": "string", "text": "string", "html": {}, "isRead": false, "isFlagged": false, "isDeleted": false, "hasAttachments": false, "size": 0, "autoDeleteEnabled": false, "expiresAt": null, "flags": [], "verifications": {}, "headers": [], "attachments": [], "downloadUrl": "string", "sourceUrl": "string", "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ], "view": { "id": "string", "type": "string", "first": "string", "last": "string", "previous": "string", "next": "string" } } ``` Messages are ordered by `createdAt` descending (newest first). There are up to 30 messages per page. Use the `view` links (`next`, `previous`) to navigate between pages. ### Get a Message ```text GET /accounts/{accountId}/mailboxes/{mailboxId}/messages/{id} ``` Retrieves a Message resource by its id (this has way more information than a message retrieved with [List Messages](#list-messages)) **Body:** *None* **Params:** The account identifier. The mailbox identifier. The message identifier. **curl Example:** ```bash curl -X GET "https://api.smtp.dev/accounts/{accountId}/mailboxes/{mailboxId}/messages/{id}" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" ``` **Response:** ```json { "id": "string", "msgid": "string", "from": { "address": "string", "name": "string" }, "to": [ { "address": "string", "name": "string" } ], "cc": [ { "address": "string", "name": "string" } ], "bcc": [ { "address": "string", "name": "string" } ], "replyTo": [ { "address": "string", "name": "string" } ], "date": "2025-04-01T00:00:00.000Z", "subject": "string", "intro": "string", "text": "string", "html": {}, "isRead": false, "isFlagged": false, "isDeleted": false, "hasAttachments": false, "size": 0, "autoDeleteEnabled": false, "expiresAt": null, "flags": [], "verifications": {}, "threadId": "string", "headers": [], "attachments": [ { "id": "string", "filename": "string", "contentType": "string", "disposition": "string", "size": 0, "downloadUrl": "string" } ], "downloadUrl": "string", "sourceUrl": "string", "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ``` ### Delete a Message ```text DELETE /accounts/{accountId}/mailboxes/{mailboxId}/messages/{id} ``` Deletes the `Message` resource. **Body:** *None* **Params:** The account identifier. The mailbox identifier. The message identifier. **curl Example:** ```bash curl -X DELETE "https://api.smtp.dev/accounts/{accountId}/mailboxes/{mailboxId}/messages/{id}" \ -H "X-API-KEY: smtplabs_your_api_key_here" ``` **Response:** *None* **(Returns status code 204 if successful.)** ### Update a Message ```text PATCH /accounts/{accountId}/mailboxes/{mailboxId}/messages/{id} ``` Updates the Message resource. For example, mark a message as read or flagged. **Body:** Set to true to mark the message as read Set to true to mark the message as flagged Enable/disable auto-deletion of the message ISO date-time when the message should expire **Params:** The account identifier The mailbox identifier The message identifier **curl Example:** ```bash curl -X PATCH "https://api.smtp.dev/accounts/{accountId}/mailboxes/{mailboxId}/messages/{id}" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Content-Type: application/merge-patch+json" \ -H "Accept: application/json" \ -d '{ "isRead": true, "isFlagged": true, "autoDeleteEnabled": true, "expiresAt": "2025-05-01T00:00:00.000Z" }' ``` **Response:** The response is the full updated Message object (same schema as [Get a Message](#get-a-message)). ### Get a Message Source ```text GET /accounts/{accountId}/mailboxes/{mailboxId}/messages/{id}/source ``` Gets a Message's Source resource: the raw message as it arrived over SMTP - headers, MIME boundaries, encoded body parts. **Body:** *None* **Params:** The account identifier. The mailbox identifier. The message identifier. **curl Example:** ```bash curl -X GET "https://api.smtp.dev/accounts/{accountId}/mailboxes/{mailboxId}/messages/{id}/source" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" ``` **Response:** ```json { "@context": "string", "@id": "string", "@type": "string", "raw": "string" } ``` The `raw` field contains the full RFC 822 message source. You can also use the [Download a Message](#download-a-message) endpoint to download it as a `.eml` file. ### Download a Message Attachment ```text GET /accounts/{accountId}/mailboxes/{mailboxId}/messages/{id}/attachment/{attachmentId} ``` Gets a Message's attachment. **Body:** *None* **Params:** The account identifier. The mailbox identifier. The message identifier. The attachment identifier. **curl Example:** ```bash curl -X GET "https://api.smtp.dev/accounts/{accountId}/mailboxes/{mailboxId}/messages/{id}/attachment/{attachmentId}" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" \ -o welcome.pdf ``` **Response:** Binary file content (saved to the specified output file). For JSON metadata about the attachment: ```bash curl -X GET "https://api.smtp.dev/accounts/{accountId}/mailboxes/{mailboxId}/messages/{id}" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" ``` ```json { "id": "string", "filename": "string", "contentType": "string", "disposition": "string", "transferEncoding": "string", "related": true, "size": 0, "downloadUrl": "string" } ``` ### Download a Message ```text GET /accounts/{accountId}/mailboxes/{mailboxId}/messages/{id}/download ``` Downloads a Message resource. **Body:** *None* **Params:** The account identifier. The mailbox identifier. The message identifier. **curl Example:** ```bash curl -X GET "https://api.smtp.dev/accounts/{accountId}/mailboxes/{mailboxId}/messages/{id}/download" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -o message.eml ``` **Response:** Binary file content (saved to the specified output file). **(Returns status code 200 if successful.)** ### Move a Message ```text PUT /accounts/{accountId}/mailboxes/{mailboxId}/messages/{id}/move ``` Moves a Message resource to a different mailbox. **Body:** The target mailbox identifier **Params** The account identifier. The mailbox identifier. The message identifier. **curl Example:** ```bash curl -X PUT "https://api.smtp.dev/accounts/{accountId}/mailboxes/{mailboxId}/messages/{id}/move" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "mailbox": "{mailboxId}" }' ``` **Response:** The response is the full Message object in its new mailbox (same schema as [Get a Message](#get-a-message)). ### Send a Message ```text POST /accounts/{accountId}/messages/send ``` Sends an email message from the specified account. The `from` address is automatically set to the account's address, regardless of what you provide in the request body. **Body:** Sender information. Must contain `address` (string) and optionally `name` (string). The `address` will be overwritten with the account's address. Array of recipient objects, each with `address` (string, required) and `name` (string, optional). At least one recipient is required. Array of CC recipient objects, each with `address` and `name`. Array of BCC recipient objects, each with `address` and `name`. Array of Reply-To recipient objects, each with `address` and `name`. Email subject line. Plain text body of the email. HTML body of the email. Array of custom header objects, each with `name` (string) and `value` (string). Array of attachment objects. See below. **Attachment object:** Base64-encoded file content. Attachment filename. MIME type. Example: `application/pdf`, `image/png`. Either `attachment` (default) or `inline`. Content-ID for inline attachments. At least one of `text`, `html`, or `attachments` must be provided. **Params:** The account identifier. **curl Example:** ```bash curl -X POST "https://api.smtp.dev/accounts/{accountId}/messages/send" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "from": { "address": "user@example.com", "name": "John Doe" }, "to": [ { "address": "recipient@example.com", "name": "Jane Doe" } ], "subject": "Hello from smtp.dev", "text": "This is a test email.", "html": "

This is a test email.

" }' ``` **Response:** *None* **(Returns status code 204 if successful.)** ### Handling Attachments Attachment downloads are raw binary - write them to disk as-is. Use `contentType` to decide how to open the file, and `disposition` to tell inline images apart from regular attachments. ## Tokens ### List Tokens ```text GET /tokens ``` Retrieves the collection of Token resources. **Body:** *None* **Params:** Filter by token name (partial match) The collection page number **curl Example:** ```bash curl -X GET "https://api.smtp.dev/tokens?page=1" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" ``` **Response:** ```json { "member": [ { "id": "string", "name": "My API Token", "description": "Used for automated testing", "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ] } ``` ### Create a Token ```text POST /tokens ``` Creates a new API token. **Body:** A name for the token to identify its purpose Optional description of what the token is used for **Params:** *None* **curl Example:** ```bash curl -X POST "https://api.smtp.dev/tokens" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "name": "Integration Token", "description": "Used for automated testing" }' ``` **Response:** ```json { "id": "string", "token": "smtplabs_abcdef123456", "name": "My API Token", "description": "Used for automated testing", "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ``` The `token` field is **only returned once** when the token is created. It cannot be retrieved again. Save the token value immediately as it will only be shown once and cannot be retrieved again. ### Get a Token ```text GET /tokens/{id} ``` Retrieves a Token resource by its id. **Body:** *None* **Params:** The token identifier **curl Example:** ```bash curl -X GET "https://api.smtp.dev/tokens/{id}" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" ``` **Response:** ```json { "id": "string", "name": "My API Token", "description": "Used for automated testing", "createdAt": "2025-04-01T00:00:00.000Z", "updatedAt": "2025-04-01T00:00:00.000Z" } ``` ### Delete a Token ```text DELETE /tokens/{id} ``` Deletes the Token resource. **Body:** *None* **Params:** The token identifier **curl Example:** ```bash curl -X DELETE "https://api.smtp.dev/tokens/{id}" \ -H "X-API-KEY: smtplabs_your_api_key_here" ``` **Response:** *None* **(Returns status code 204 if successful.)** ## Real-time Updates ### Mercure for Server-Sent Events (SSE) Instead of traditional webhooks, we use [Mercure](https://mercure.rocks/) to provide real-time updates via Server-Sent Events (SSE). SSE is a standard technology that allows servers to push updates to web clients over HTTP, maintaining a single connection. This is more efficient than polling the API for updates. ### Getting a Mercure Token Before subscribing to real-time updates, you need to obtain a Mercure token: ```text GET /mercure/token ``` **curl Example:** ```bash curl -X GET "https://api.smtp.dev/mercure/token" \ -H "X-API-KEY: smtplabs_your_api_key_here" \ -H "Accept: application/json" ``` **Response:** ```json { "token": "eyJhbGciOiJIUzI1NiJ9..." } ``` ### Listening for New Messages To listen for real-time updates about new messages: #### Base URL: ```text https://mercure.smtp.dev/.well-known/mercure ``` #### Topic: ```text /accounts/{id}{+path} ``` #### Example implementation (JavaScript): The standard `EventSource` API does not support custom headers. Use a library like [`@microsoft/fetch-event-source`](https://github.com/Azure/fetch-event-source) instead: ```javascript import { fetchEventSource } from '@microsoft/fetch-event-source' const tokenResponse = await fetch('https://api.smtp.dev/mercure/token', { headers: { 'X-API-KEY': 'smtplabs_your_api_key_here' } }) const { token } = await tokenResponse.json() const mercureUrl = new URL('https://mercure.smtp.dev/.well-known/mercure') // e.g. /accounts/6789abcdef012345{+path} mercureUrl.searchParams.append('topic', `/accounts/${accountId}{+path}`) await fetchEventSource(mercureUrl.toString(), { headers: { Authorization: `Bearer ${token}` }, onmessage(event) { const data = JSON.parse(event.data) if (data['@type'] === 'Message') { // new message received } } }) ``` You'll receive updates with `Account`, `Mailbox`, or `Message` types depending on what changed. ## Questions and suggestions If you have any questions or suggestions, please contact us. ## Tech stack Our stack includes [API-Platform](https://api-platform.com/), [Mercure](https://mercure.rocks/), [Nuxt.js](https://nuxt.com), [Haraka](https://haraka.github.io), [Caddy](https://caddyserver.com/), [MongoDB](https://www.mongodb.com/), [Node.js](https://nodejs.org), [RockyLinux](https://rockylinux.org) --- - **Page:** Pricing - SMTP Labs, Inc. - **Source:** https://smtp.dev/pricing - **Description:** Pick a plan. Upgrade or downgrade any time. # **Pricing** Pick a plan. Upgrade or downgrade any time. **Lite** Free, with limits. **$0** ** ****/month** - 1 domain - 50 accounts - Messages kept for 7 days - SMTP, IMAP, POP3, API - Email audit [Sign up](https://smtp.dev/signup/) **Pro** More of everything. **$7** ** ****/month** - 5 domains - 25,000 accounts - Messages kept for 30 days - SMTP, IMAP, POP3, API - Email audit - Catch-all & aliasing [Sign up](https://smtp.dev/signup/) **Max** No limits. **$20** ** ****/month** - Unlimited domains - Unlimited accounts - Messages kept for 90 days - SMTP, IMAP, POP3, API - Email audit - Catch-all & aliasing [Sign up](https://smtp.dev/signup/) ## **FAQ** --- - **Page:** Terms of Service - **Source:** https://smtp.dev/legal/terms - **Description:** Terms of Service for SMTP Labs, Inc. The website located at [smtp.dev](https://smtp.dev) (the "**Site**") is a copyrighted work belonging to SMTP Labs, Inc. ("**Company**", "**us**", "**our**", and "**we**"). Certain features of the Site may be subject to additional guidelines, terms, or rules, which will be posted on the Site in connection with such features. All such additional terms, guidelines, and rules are incorporated by reference into these Terms. "**Service**" refers to the email infrastructure services provided by the Company through the Site, including inbound SMTP, IMAP, POP3, email account hosting, domain management, and related APIs. The Service does not support sending outbound email to external recipients. These Terms of Service (these "**Terms**") set forth the legally binding terms and conditions that govern your use of the Site and the Service. By accessing or using the Site, you are accepting these Terms (on behalf of yourself or the entity that you represent), and you represent and warrant that you have the right, authority, and capacity to enter into these Terms (on behalf of yourself or the entity that you represent). You may not access or use the Site or accept the Terms if you are not at least 18 years old. If you do not agree with all of the provisions of these Terms, do not access and/or use the Site. **PLEASE BE AWARE THAT SECTION 12.2 CONTAINS PROVISIONS GOVERNING HOW TO RESOLVE DISPUTES BETWEEN YOU AND COMPANY. AMONG OTHER THINGS, SECTION 12.2 INCLUDES AN AGREEMENT TO ARBITRATE WHICH REQUIRES, WITH LIMITED EXCEPTIONS, THAT ALL DISPUTES BETWEEN YOU AND US SHALL BE RESOLVED BY BINDING AND FINAL ARBITRATION. SECTION 12.2 ALSO CONTAINS A CLASS ACTION AND JURY TRIAL WAIVER. PLEASE READ SECTION 12.2 CAREFULLY.** **UNLESS YOU OPT OUT OF THE AGREEMENT TO ARBITRATE WITHIN 30 DAYS: (1) YOU WILL ONLY BE PERMITTED TO PURSUE DISPUTES OR CLAIMS AND SEEK RELIEF AGAINST US ON AN INDIVIDUAL BASIS, NOT AS A PLAINTIFF OR CLASS MEMBER IN ANY CLASS OR REPRESENTATIVE ACTION OR PROCEEDING AND YOU WAIVE YOUR RIGHT TO PARTICIPATE IN A CLASS ACTION LAWSUIT OR CLASS-WIDE ARBITRATION; AND (2) YOU ARE WAIVING YOUR RIGHT TO PURSUE DISPUTES OR CLAIMS AND SEEK RELIEF IN A COURT OF LAW AND TO HAVE A JURY TRIAL.** ## 1. Accounts ### 1.1 Account Creation In order to use certain features of the Site, you must register for an account ("**Account**") through our third-party authentication provider and provide certain information about yourself as prompted by the account registration process. You represent and warrant that: (a) all required registration information you submit is truthful and accurate; (b) you will maintain the accuracy of such information. You may deactivate your Account at any time by contacting us at [legal@smtp.dev](mailto:legal@smtp.dev). Company may suspend or terminate your Account in accordance with Section 10. ### 1.2 Account Responsibilities You are responsible for maintaining the security of your Account and are fully responsible for all activities that occur under your Account. You agree to immediately notify Company of any unauthorized use, or suspected unauthorized use of your Account or any other breach of security. Company cannot and will not be liable for any loss or damage arising from your failure to comply with the above requirements. ## 2. Access to the Site ### 2.1 License Subject to these Terms, Company grants you a non-transferable, non-exclusive, revocable, limited license to use and access the Site and the Service solely for your own personal or internal business use. ### 2.2 Certain Restrictions The rights granted to you in these Terms are subject to the following restrictions: (a) you shall not license, sell, rent, lease, transfer, assign, distribute, host, or otherwise commercially exploit the Site, whether in whole or in part, or any content displayed on the Site; (b) you shall not modify, make derivative works of, disassemble, reverse compile or reverse engineer any part of the Site; (c) you shall not access the Site in order to build a similar or competitive website, product, or service; and (d) except as expressly stated herein, no part of the Site may be copied, reproduced, distributed, republished, downloaded, displayed, posted or transmitted in any form or by any means. Unless otherwise indicated, any future release, update, or other addition to functionality of the Site shall be subject to these Terms. All copyright and other proprietary notices on the Site (or on any content displayed on the Site) must be retained on all copies thereof. ### 2.3 Modification Company reserves the right, at any time, to modify, suspend, or discontinue the Site (in whole or in part) with or without notice to you. You agree that Company will not be liable to you or to any third party for any modification, suspension, or discontinuation of the Site or any part thereof. ### 2.4 No Support or Maintenance You acknowledge and agree that Company will have no obligation to provide you with any support or maintenance in connection with the Site, except as may be included in a paid subscription plan. ### 2.5 Ownership Excluding any User Content that you may provide (defined below), you acknowledge that all the intellectual property rights, including copyrights, patents, trademarks, and trade secrets, in the Site and its content are owned by Company or Company's suppliers. Neither these Terms (nor your access to the Site) transfers to you or any third party any rights, title or interest in or to such intellectual property rights, except for the limited access rights expressly set forth in Section 2.1. Company and its suppliers reserve all rights not granted in these Terms. There are no implied licenses granted under these Terms. ### 2.6 Feedback If you provide Company with any feedback or suggestions regarding the Site ("**Feedback**"), you hereby assign to Company all rights in such Feedback and agree that Company shall have the right to use and fully exploit such Feedback and related information in any manner it deems appropriate. Company will treat any Feedback you provide to Company as non-confidential and non-proprietary. You agree that you will not submit to Company any information or ideas that you consider to be confidential or proprietary. ## 3. User Content ### 3.1 User Content "**User Content**" means any and all information and content that a user submits to, or uses with, the Site, including but not limited to domain configurations, mailbox settings, and API key usage. For clarity, inbound email messages sent by third parties to your email accounts are not your User Content — they are processed by the Company solely to provide the Service and are subject to the provisions in Section 8. You are solely responsible for your User Content. You assume all risks associated with use of your User Content, including any reliance on its accuracy, completeness or usefulness by others, or any disclosure of your User Content that personally identifies you or any third party. You hereby represent and warrant that your User Content does not violate our Acceptable Use Policy (defined in Section 3.3). Company is not obligated to backup any User Content, and your User Content may be deleted at any time without prior notice. You are solely responsible for creating and maintaining your own backup copies of your User Content if you desire. ### 3.2 License You hereby grant (and you represent and warrant that you have the right to grant) to Company a nonexclusive, royalty-free and fully paid, worldwide license to store, process, and display your User Content, and to grant sublicenses to our sub-processors, solely as necessary to provide and operate the Service. This license terminates when your User Content is deleted from our active systems, subject to the data retention provisions described in our [Privacy Policy](/legal/privacy). You retain all ownership rights in your User Content. ### 3.3 Acceptable Use Policy The following terms constitute our "**Acceptable Use Policy**": You agree not to use the Site or Service to collect, upload, transmit, display, or distribute any User Content (i) that violates any third-party right, including any copyright, trademark, patent, trade secret, moral right, privacy right, right of publicity, or any other intellectual property or proprietary right, (ii) that is unlawful, harassing, abusive, tortious, threatening, harmful, invasive of another's privacy, vulgar, defamatory, false, intentionally misleading, trade libelous, pornographic, obscene, patently offensive, promotes racism, bigotry, hatred, or physical harm of any kind against any group or individual or is otherwise objectionable, (iii) that is harmful to minors in any way, or (iv) that is in violation of any law, regulation, or obligations or restrictions imposed by any third party. In addition, you agree not to: (i) upload, transmit, or distribute to or through the Site any computer viruses, worms, or any software intended to damage or alter a computer system or data; (ii) send through the Site unsolicited or unauthorized advertising, promotional materials, junk mail, spam, chain letters, pyramid schemes, or any other form of duplicative or unsolicited messages, whether commercial or otherwise; (iii) use the Site to harvest, collect, gather or assemble information or data regarding other users, including e-mail addresses, without their consent; (iv) interfere with, disrupt, or create an undue burden on servers or networks connected to the Site, or violate the regulations, policies or procedures of such networks; (v) attempt to gain unauthorized access to the Site (or to other computer systems or networks connected to or used together with the Site), whether through password mining or any other means; (vi) harass or interfere with any other user's use and enjoyment of the Site; or (vii) use software or automated agents or scripts to produce multiple accounts on the Site, or to generate automated searches, requests, or queries to (or to strip, scrape, or mine data from) the Site. ### 3.4 Enforcement We reserve the right (but have no obligation) to review, refuse and/or remove any User Content in our sole discretion, and to investigate and/or take appropriate action against you in our sole discretion if you violate the Acceptable Use Policy or any other provision of these Terms or otherwise create liability for us or any other person. Such action may include removing or modifying your User Content, terminating your Account in accordance with Section 10, and/or reporting you to law enforcement authorities. ## 4. Indemnification You agree to indemnify and hold Company (and its officers, employees, and agents) harmless, including costs and attorneys' fees, from any claim or demand made by any third party due to or arising out of (a) your use of the Site, (b) your violation of these Terms, (c) your violation of applicable laws or regulations or (d) your User Content. Company reserves the right, at your expense, to assume the exclusive defense and control of any matter for which you are required to indemnify us, and you agree to cooperate with our defense of these claims. You agree not to settle any matter without the prior written consent of Company. Company will use reasonable efforts to notify you of any such claim, action or proceeding upon becoming aware of it. ## 5. Third-Party Links ### 5.1 Third-Party Links The Site may contain links to third-party websites and services (collectively, "**Third-Party Links**"). Such Third-Party Links are not under the control of Company, and Company is not responsible for any Third-Party Links. Company provides access to these Third-Party Links only as a convenience to you, and does not review, approve, monitor, endorse, warrant, or make any representations with respect to Third-Party Links. You use all Third-Party Links at your own risk, and should apply a suitable level of caution and discretion in doing so. When you click on any of the Third-Party Links, the applicable third party's terms and policies apply, including the third party's privacy and data gathering practices. ### 5.2 Release You hereby release and forever discharge Company (and our officers, employees, agents, successors, and assigns) from, and hereby waive and relinquish, each and every past, present and future dispute, claim, controversy, demand, right, obligation, liability, action and cause of action of every kind and nature (including personal injuries, death, and property damage), that has arisen or arises directly or indirectly out of, or that relates directly or indirectly to, the Site or Service (including any Third-Party Links). IF YOU ARE A CALIFORNIA RESIDENT, YOU HEREBY WAIVE CALIFORNIA CIVIL CODE SECTION 1542 IN CONNECTION WITH THE FOREGOING, WHICH STATES: "A GENERAL RELEASE DOES NOT EXTEND TO CLAIMS WHICH THE CREDITOR OR RELEASING PARTY DOES NOT KNOW OR SUSPECT TO EXIST IN HIS OR HER FAVOR AT THE TIME OF EXECUTING THE RELEASE, WHICH IF KNOWN BY HIM OR HER MUST HAVE MATERIALLY AFFECTED HIS OR HER SETTLEMENT WITH THE DEBTOR OR RELEASED PARTY." ## 6. Disclaimers THE SITE AND SERVICE ARE PROVIDED ON AN "AS-IS" AND "AS AVAILABLE" BASIS, AND COMPANY (AND OUR SUPPLIERS) EXPRESSLY DISCLAIM ANY AND ALL WARRANTIES AND CONDITIONS OF ANY KIND, WHETHER EXPRESS, IMPLIED, OR STATUTORY, INCLUDING ALL WARRANTIES OR CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, QUIET ENJOYMENT, ACCURACY, OR NON-INFRINGEMENT. WE (AND OUR SUPPLIERS) MAKE NO WARRANTY THAT THE SITE WILL MEET YOUR REQUIREMENTS, WILL BE AVAILABLE ON AN UNINTERRUPTED, TIMELY, SECURE, OR ERROR-FREE BASIS, OR WILL BE ACCURATE, RELIABLE, FREE OF VIRUSES OR OTHER HARMFUL CODE, COMPLETE, LEGAL, OR SAFE. IF APPLICABLE LAW REQUIRES ANY WARRANTIES WITH RESPECT TO THE SITE, ALL SUCH WARRANTIES ARE LIMITED IN DURATION TO 90 DAYS FROM THE DATE OF FIRST USE. WITHOUT LIMITING THE FOREGOING, COMPANY DOES NOT WARRANT OR GUARANTEE THAT: (A) THE SERVICE WILL BE AVAILABLE AT ANY PARTICULAR TIME OR LOCATION; (B) EMAIL MESSAGES WILL BE DELIVERED, RECEIVED, OR STORED WITHOUT DELAY, LOSS, OR CORRUPTION; (C) ANY DEFECTS OR ERRORS IN THE SERVICE WILL BE CORRECTED; OR (D) THE SERVICE WILL BE FREE FROM INTERRUPTION, INCLUDING SCHEDULED OR UNSCHEDULED DOWNTIME. YOU ACKNOWLEDGE THAT THE SERVICE MAY BE SUBJECT TO PERIODS OF UNAVAILABILITY DUE TO MAINTENANCE, INFRASTRUCTURE FAILURES, THIRD-PARTY SERVICE OUTAGES, OR OTHER CAUSES BEYOND OUR CONTROL, AND COMPANY SHALL HAVE NO LIABILITY FOR ANY SUCH UNAVAILABILITY. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT APPLY TO YOU. SOME JURISDICTIONS DO NOT ALLOW LIMITATIONS ON HOW LONG AN IMPLIED WARRANTY LASTS, SO THE ABOVE LIMITATION MAY NOT APPLY TO YOU. ## 7. Limitation on Liability TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL COMPANY (OR OUR SUPPLIERS) BE LIABLE TO YOU OR ANY THIRD PARTY FOR ANY LOST PROFITS, LOST DATA, COSTS OF PROCUREMENT OF SUBSTITUTE PRODUCTS, OR ANY INDIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL OR PUNITIVE DAMAGES ARISING FROM OR RELATING TO THESE TERMS OR YOUR USE OF, OR INABILITY TO USE, THE SITE OR SERVICE, EVEN IF COMPANY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. ACCESS TO, AND USE OF, THE SITE AND SERVICE IS AT YOUR OWN DISCRETION AND RISK, AND YOU WILL BE SOLELY RESPONSIBLE FOR ANY DAMAGE TO YOUR DEVICE OR COMPUTER SYSTEM, OR LOSS OF DATA RESULTING THEREFROM. TO THE MAXIMUM EXTENT PERMITTED BY LAW, NOTWITHSTANDING ANYTHING TO THE CONTRARY CONTAINED HEREIN, OUR LIABILITY TO YOU FOR ANY DAMAGES ARISING FROM OR RELATED TO THESE TERMS (FOR ANY CAUSE WHATSOEVER AND REGARDLESS OF THE FORM OF THE ACTION), WILL AT ALL TIMES BE LIMITED TO THE GREATER OF (A) FIFTY US DOLLARS OR (B) THE AMOUNTS YOU HAVE PAID TO COMPANY IN THE TWELVE (12) MONTHS PRECEDING THE CLAIM. THE EXISTENCE OF MORE THAN ONE CLAIM WILL NOT ENLARGE THIS LIMIT. YOU AGREE THAT OUR SUPPLIERS WILL HAVE NO LIABILITY OF ANY KIND ARISING FROM OR RELATING TO THESE TERMS. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OR EXCLUSION OF LIABILITY FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE LIMITATION OR EXCLUSION MAY NOT APPLY TO YOU. ## 8. Inbound Email Content THE SERVICE RECEIVES INBOUND EMAIL FROM THIRD-PARTY SENDERS OVER WHOM COMPANY HAS NO CONTROL. COMPANY IS NOT RESPONSIBLE FOR THE CONTENT, ACCURACY, LEGALITY, OR APPROPRIATENESS OF ANY INBOUND EMAIL MESSAGES, ATTACHMENTS, OR METADATA RECEIVED THROUGH THE SERVICE. COMPANY DOES NOT SCREEN, MONITOR, ENDORSE, OR VERIFY INBOUND EMAIL CONTENT AND SHALL HAVE NO LIABILITY WHATSOEVER ARISING FROM OR RELATED TO SUCH CONTENT, INCLUDING BUT NOT LIMITED TO ANY CLAIMS OF DEFAMATION, INTELLECTUAL PROPERTY INFRINGEMENT, PRIVACY VIOLATIONS, SPAM, PHISHING, MALWARE, OR OTHER HARMFUL CONTENT. YOU ACKNOWLEDGE THAT COMPANY MAY, IN ITS SOLE DISCRETION AND WITHOUT PRIOR NOTICE, REJECT, FILTER, DELAY, QUARANTINE, OR DELETE ANY INBOUND EMAIL THAT COMPANY REASONABLY BELIEVES MAY: (A) VIOLATE THESE TERMS OR APPLICABLE LAW; (B) CONTAIN MALICIOUS CODE, SPAM, OR PHISHING ATTEMPTS; (C) POSE A RISK TO THE SECURITY, INTEGRITY, OR AVAILABILITY OF THE SERVICE; OR (D) OTHERWISE HARM THE COMPANY, ITS INFRASTRUCTURE, OR ITS USERS. COMPANY SHALL HAVE NO LIABILITY FOR ANY SUCH ACTION OR FAILURE TO TAKE SUCH ACTION. ## 9. Force Majeure Company shall not be liable for any failure or delay in performing its obligations under these Terms where such failure or delay results from any cause beyond Company's reasonable control, including but not limited to acts of God, natural disasters, war, terrorism, riots, embargoes, acts of civil or military authorities, fire, floods, epidemics, infrastructure failures, power outages, internet or telecommunications failures, third-party service provider outages, cyberattacks, or government actions. During any such event, Company's obligations under these Terms shall be suspended for the duration of the event. ## 10. Term and Termination Subject to this Section, these Terms will remain in full force and effect while you use the Site. We may suspend or terminate your rights to use the Site (including your Account) at any time for any reason at our sole discretion, including for any use of the Site in violation of these Terms. Upon termination of your rights under these Terms, your Account and right to access and use the Site will terminate immediately. You understand that any termination of your Account may involve deletion of your User Content associated with your Account from our live databases, subject to the data retention provisions described in our [Privacy Policy](/legal/privacy). Company will not have any liability whatsoever to you for any termination of your rights under these Terms, including for termination of your Account or deletion of your User Content. Even after your rights under these Terms are terminated, the following provisions of these Terms will remain in effect: Sections 2.2 through 2.6, Section 3 and Sections 4 through 12. ## 11. Intellectual Property Company respects the intellectual property of others and asks that users of our Site and Service do the same. If you believe that any content accessible through our Service infringes your intellectual property rights, please contact us at [legal@smtp.dev](mailto:legal@smtp.dev) with a description of the alleged infringement. We will investigate and take appropriate action, which may include removing or disabling access to the content in question and terminating the accounts of repeat infringers. ## 12. General ### 12.1 Changes These Terms are subject to occasional revision, and if we make any substantial changes, we may notify you by prominently posting notice of the changes on our Site. Continued use of our Site following notice of such changes shall indicate your acknowledgement of such changes and agreement to be bound by the terms and conditions of such changes. ### 12.2 Dispute Resolution Please read the following arbitration agreement in this Section (the "**Arbitration Agreement**") carefully. It requires you to arbitrate disputes with Company and limits the manner in which you can seek relief. #### (a) Applicability of Arbitration Agreement You agree that any dispute between you and Company relating in any way to the Site, the Service, or these Terms will be resolved by binding arbitration, rather than in court, except that (1) you and Company may assert individualized claims in small claims court if the claims qualify, remain in such court and advance solely on an individual, non-class basis; and (2) you or Company may seek equitable relief in court for infringement or other misuse of intellectual property rights (such as trademarks, trade dress, domain names, trade secrets, copyrights, and patents). **This Arbitration Agreement shall survive the expiration or termination of these Terms.** Notwithstanding the foregoing, if you are located in the EEA, United Kingdom, or another jurisdiction where mandatory arbitration of consumer disputes is prohibited by law, this Arbitration Agreement shall not apply to you to the extent it conflicts with such mandatory law, and you may bring claims in the courts of your country of residence. #### (b) Informal Dispute Resolution There might be instances when a Dispute arises between you and Company. If that occurs, Company is committed to working with you to reach a reasonable resolution. You and Company agree that good faith informal efforts to resolve Disputes can result in a prompt, low-cost and mutually beneficial outcome. You and Company therefore agree that before either party commences arbitration against the other (or initiates an action in small claims court if a party so elects), we will personally meet and confer telephonically or via videoconference, in a good faith effort to resolve informally any Dispute covered by this Arbitration Agreement ("**Informal Dispute Resolution Conference**"). The party initiating a Dispute must give notice to the other party in writing of its intent to initiate an Informal Dispute Resolution Conference ("**Notice**"), which shall occur within 45 days after the other party receives such Notice, unless an extension is mutually agreed upon by the parties. Notice to Company should be sent by email to [legal@smtp.dev](mailto:legal@smtp.dev). The Notice must include: (1) your name, telephone number, mailing address, e-mail address associated with your account (if you have one); (2) the name, telephone number, mailing address and e-mail address of your counsel, if any; and (3) a description of your Dispute. Engaging in the Informal Dispute Resolution Conference is a condition precedent and requirement that must be fulfilled before commencing arbitration. The statute of limitations and any filing fee deadlines shall be tolled while the parties engage in the Informal Dispute Resolution Conference process required by this section. #### (c) Arbitration Rules and Forum These Terms evidence a transaction involving interstate commerce; and notwithstanding any other provision herein with respect to the applicable substantive law, the Federal Arbitration Act, 9 U.S.C. § 1 et seq., will govern the interpretation and enforcement of this Arbitration Agreement and any arbitration proceedings. If the Informal Dispute Resolution Process described above does not resolve satisfactorily within 60 days after receipt of your Notice, you and Company agree that either party shall have the right to finally resolve the Dispute through binding arbitration. The arbitration will be conducted by JAMS, an established alternative dispute resolution provider. Disputes involving claims and counterclaims with an amount in controversy under $250,000, not inclusive of attorneys' fees and interest, shall be subject to JAMS' most current version of the Streamlined Arbitration Rules and Procedures; all other claims shall be subject to JAMS's most current version of the Comprehensive Arbitration Rules and Procedures. Unless you and Company otherwise agree, the arbitration will be conducted in the county where you reside. Subject to the JAMS Rules, the arbitrator may direct a limited and reasonable exchange of information between the parties, consistent with the expedited nature of the arbitration. You and Company agree that all materials and documents exchanged during the arbitration proceedings shall be kept confidential and shall not be shared with anyone except the parties' attorneys, accountants, or business advisors, and then subject to the condition that they agree to keep all materials and documents exchanged during the arbitration proceedings confidential. #### (d) Authority of Arbitrator The arbitrator shall have exclusive authority to resolve all disputes subject to arbitration hereunder including, without limitation, any dispute related to the interpretation, applicability, enforceability or formation of this Arbitration Agreement or any portion of the Arbitration Agreement. The arbitrator shall have the authority to grant motions dispositive of all or part of any claim or dispute. The arbitrator shall have the authority to award monetary damages and to grant any non-monetary remedy or relief available to an individual party under applicable law, the arbitral forum's rules, and these Terms. The arbitrator shall issue a written award and statement of decision describing the essential findings and conclusions on which any award (or decision not to render an award) is based, including the calculation of any damages awarded. The arbitrator shall follow the applicable law. The award of the arbitrator is final and binding upon you and us. Judgment on the arbitration award may be entered in any court having jurisdiction. #### (e) Waiver of Jury Trial EXCEPT AS SPECIFIED IN SECTION 12.2(a), YOU AND COMPANY HEREBY WAIVE ANY CONSTITUTIONAL AND STATUTORY RIGHTS TO SUE IN COURT AND HAVE A TRIAL IN FRONT OF A JUDGE OR A JURY. You and Company are instead electing that all covered claims and disputes shall be resolved exclusively by arbitration under this Arbitration Agreement, except as specified in Section 12.2(a) above. An arbitrator can award on an individual basis the same damages and relief as a court and must follow these Terms as a court would. However, there is no judge or jury in arbitration, and court review of an arbitration award is subject to very limited review. #### (f) Waiver of Class or Other Non-Individualized Relief YOU AND COMPANY AGREE THAT EACH OF US MAY BRING CLAIMS AGAINST THE OTHER ONLY ON AN INDIVIDUAL BASIS AND NOT ON A CLASS, REPRESENTATIVE, OR COLLECTIVE BASIS, AND THE PARTIES HEREBY WAIVE ALL RIGHTS TO HAVE ANY DISPUTE BE BROUGHT, HEARD, ADMINISTERED, RESOLVED, OR ARBITRATED ON A CLASS, COLLECTIVE, REPRESENTATIVE, OR MASS ACTION BASIS. ONLY INDIVIDUAL RELIEF IS AVAILABLE, AND DISPUTES OF MORE THAN ONE CUSTOMER OR USER CANNOT BE ARBITRATED OR CONSOLIDATED WITH THOSE OF ANY OTHER CUSTOMER OR USER. #### (g) 30-Day Right to Opt Out You have the right to opt out of the provisions of this Arbitration Agreement by sending a timely written notice of your decision to opt out to [legal@smtp.dev](mailto:legal@smtp.dev), within 30 days after first becoming subject to this Arbitration Agreement. Your notice must include your name and address and a clear statement that you want to opt out of this Arbitration Agreement. If you opt out of this Arbitration Agreement, all other parts of these Terms will continue to apply to you. Opting out of this Arbitration Agreement has no effect on any other arbitration agreements that you may currently have with us, or may enter into in the future with us. #### (h) Invalidity, Expiration Except as provided in the subsection entitled "Waiver of Class or Other Non-Individualized Relief", if any part or parts of this Arbitration Agreement are found under the law to be invalid or unenforceable, then such specific part or parts shall be of no force and effect and shall be severed and the remainder of the Arbitration Agreement shall continue in full force and effect. You further agree that any Dispute that you have with Company as detailed in this Arbitration Agreement must be initiated via arbitration within the applicable statute of limitation for that claim or controversy, or it will be forever time barred. ### 12.3 Electronic Communications The communications between you and Company use electronic means, whether you use the Site or send us emails, or whether Company posts notices on the Site. For contractual purposes, you (a) consent to receive communications from Company in an electronic form; and (b) agree that all terms and conditions, agreements, notices, disclosures, and other communications that Company provides to you electronically satisfy any legal requirement that such communications would satisfy if it were in a hardcopy writing. The foregoing does not affect your non-waivable rights. ### 12.4 Entire Terms These Terms constitute the entire agreement between you and us regarding the use of the Site. Our failure to exercise or enforce any right or provision of these Terms shall not operate as a waiver of such right or provision. The section titles in these Terms are for convenience only and have no legal or contractual effect. The word "including" means "including without limitation". If any provision of these Terms is, for any reason, held to be invalid or unenforceable, the other provisions of these Terms will be unimpaired and the invalid or unenforceable provision will be deemed modified so that it is valid and enforceable to the maximum extent permitted by law. Your relationship to Company is that of an independent contractor, and neither party is an agent or partner of the other. These Terms, and your rights and obligations herein, may not be assigned, subcontracted, delegated, or otherwise transferred by you without Company's prior written consent, and any attempted assignment, subcontract, delegation, or transfer in violation of the foregoing will be null and void. Company may freely assign these Terms. The terms and conditions set forth in these Terms shall be binding upon assignees. ### 12.5 Governing Law These Terms shall be governed by and construed in accordance with the laws of the State of Delaware, United States, without regard to conflict of law principles. For users in the EEA or United Kingdom, nothing in these Terms affects your mandatory statutory rights under applicable local law. ### 12.6 Copyright/Trademark Information Copyright © 2026 SMTP Labs, Inc. All rights reserved. All trademarks, logos and service marks ("**Marks**") displayed on the Site are our property or the property of other third parties. You are not permitted to use these Marks without our prior written consent or the consent of such third party which may own the Marks. ### 12.7 Contact Information SMTP Labs, Inc. Email: [legal@smtp.dev](mailto:legal@smtp.dev) --- - **Page:** Email Testing for Developers - SMTP Labs, Inc. - **Source:** https://smtp.dev/accounts - **Description:** Email testing sandbox for developers. SMTP in, IMAP/API out. Inspect headers, MIME and raw source. Nothing leaves the sandbox. --- - **Page:** Verifying SPF, DKIM, and DMARC in Staging - **Source:** https://smtp.dev/docs/guides/spf-dkim-dmarc - **Description:** Send from staging to a sandbox address and read the SPF, DKIM, and DMARC results on the received message before you change production DNS. Every message that arrives [over MX](/docs/setup/domain) is checked against the sender's SPF record, DKIM signature, and DMARC policy. Send from staging to a sandbox address and you get a verdict on your DNS before any real recipient does. ## Setup ### Add a sandbox domain and point its MX record at mx.smtp.dev [Domain setup](/docs/setup/domain) has the record. ### Create a recipient account e.g. `authcheck@sandbox.example.com` on the [Accounts](/accounts/) page. ### Send to it from your staging infrastructure Through the same provider and DNS your production traffic will use. Authentication checks the path the message took, so it has to actually leave your infrastructure. ## Reading the Results Open the message in [Mail](/mail/accounts) - verification results are shown with the message. Over the API, they're on the [Message resource](/docs/api#get-a-message): ```bash curl "https://api.smtp.dev/accounts/{accountId}/mailboxes/{mailboxId}/messages/{id}" \ -H "X-API-KEY: smtplabs_your_api_key_here" | jq '.verifications' ``` For the underlying headers, fetch the [raw source](/docs/api#get-a-message-source). ## What Each Check Means
Check Passes when
SPF The delivering server's IP is listed in the envelope sender domain's SPF record
DKIM The message signature validates against the public key published in the signer's DNS
DMARC SPF or DKIM passes and the passing domain aligns with the visible From domain
## Common Failures - **SPF fails after adding a provider**: the provider's `include:` is missing from your SPF record, or the record now exceeds the 10-DNS-lookup limit. - **DKIM fails on a fresh setup**: the selector in the signature doesn't match the DNS record name, or the key was rotated and DNS still serves the old one. - **SPF and DKIM pass, DMARC fails**: alignment. The domain that passed isn't the one in `From` - typical when a provider signs with its own domain instead of yours. Mail sent between sandbox accounts through `send.smtp.dev` never crosses your DNS, so it says nothing about your SPF or DKIM. Send from the infrastructure you're validating. --- - **Page:** Privacy Policy - **Source:** https://smtp.dev/legal/privacy - **Description:** Privacy Policy for SMTP Labs, Inc. SMTP Labs, Inc. (the "Company") is committed to maintaining robust privacy protections for its users. Our Privacy Policy ("Privacy Policy") is designed to help you understand how we collect, use and safeguard the information you provide to us and to assist you in making informed decisions when using our Service. For purposes of this Privacy Policy, "Site" refers to the Company's website, which can be accessed at [smtp.dev](https://smtp.dev). "Service" refers to the Company's services accessed via the Site, in which users can receive, test, and manage email through inbound SMTP, IMAP, POP3, email account hosting, domain management, and related APIs. The Service does not support sending outbound email to external recipients. The terms "we," "us," and "our" refer to the Company. "You" refers to you, as a user of our Site or our Service. By accessing our Site or our Service, you acknowledge that you have read and understood this Privacy Policy and our [Terms of Service](/legal/terms). Our processing of your Personal Information is based on the legal bases described in Section III below. ## I. Information We Collect We collect "Automatically Collected Data" and "Personal Information." **Automatically Collected Data** includes information collected through your use of the Site, such as anonymous usage data, general demographic information, referring/exit pages and URLs, platform types, preferences you submit and preferences that are generated based on the data you submit, and number of clicks. Some Automatically Collected Data, such as IP addresses and device identifiers, may be considered personal data under certain privacy laws and will be treated accordingly. **Personal Information** includes your email address and name, which you provide to us through the registration process at the Site via our third-party authentication provider. ### 1. Information collected via Technology To activate the Service you do not need to submit any Personal Information other than your email address. To use the Service thereafter, you do not need to submit further Personal Information. However, in an effort to improve the quality of the Service, we track information provided to us by your browser or by our software application when you view or use the Service, such as the website you came from (known as the "referring URL"), the type of browser you use, the device from which you connected to the Service, the time and date of access, and other information that does not personally identify you. We track this information using cookies, or small text files which include an anonymous unique identifier. Cookies are sent to a user's browser from our servers and are stored on the user's computer hard drive. Sending a cookie to a user's browser enables us to collect Automatically Collected Data about that user and keep a record of the user's preferences when utilizing our services, both on an individual and aggregate basis. The Company may use both persistent and session cookies; persistent cookies remain on your computer after you close your session and until you delete them, while session cookies expire when you close your browser. ### 2. Information you provide us by registering for an account In addition to the information provided automatically by your browser when you visit the Site, to become a subscriber to the Service you will need to create an account. You can create an account by registering with the Service through our third-party authentication provider. By registering, you are authorizing us to collect, store and use your email address and profile information in accordance with this Privacy Policy. ### 3. Children's Privacy The Site and the Service are not directed to anyone under the age of 13. The Site does not knowingly collect or solicit information from anyone under the age of 13, or allow anyone under the age of 13 to sign up for the Service. In the event that we learn that we have gathered personal information from anyone under the age of 13 without the consent of a parent or guardian, we will delete that information as soon as possible. If you believe we have collected such information, please contact us at [legal@smtp.dev](mailto:legal@smtp.dev). ## II. How We Use and Share Information ### Personal Information Except as otherwise stated in this Privacy Policy, we do not sell, trade, rent or otherwise share for marketing purposes your Personal Information with third parties without your consent. We do share Personal Information with vendors who are performing services for the Company, such as cloud hosting, authentication, and payment processing providers. Those vendors use your Personal Information only at our direction and in accordance with our Privacy Policy. In general, the Personal Information you provide to us is used to help us communicate with you. For example, we use Personal Information to contact users in response to questions, provide technical support, and deliver service-related notices through the Site. We may share Personal Information with outside parties if we have a good-faith belief that access, use, preservation or disclosure of the information is reasonably necessary to meet any applicable legal process or enforceable governmental request; to enforce applicable Terms of Service, including investigation of potential violations; address fraud, security or technical concerns; or to protect against harm to the rights, property, or safety of our users or the public as required or permitted by law. ### Automatically Collected Data In general, we use Automatically Collected Data to help us improve the Service and customize the user experience. We also aggregate Automatically Collected Data in order to track trends and analyze use patterns on the Site. We may use and disclose Automatically Collected Data in aggregate and anonymized form (where no individual can be identified) at our discretion. Where Automatically Collected Data constitutes personal data under applicable law, we process it in accordance with the legal bases described in Section III. In the event we undergo a business transaction such as a merger, acquisition by another company, or sale of all or a portion of our assets, your Personal Information may be among the assets transferred. You acknowledge that such transfers may occur and are permitted by this Privacy Policy, and that any acquirer of our assets may continue to process your Personal Information as set forth in this Privacy Policy. If our information practices change at any time in the future, we will post the policy changes to the Site so that you may opt out of the new information practices. We suggest that you check the Site periodically if you are concerned about how your information is used. ## III. Legal Basis for Processing If you are located in the EEA or United Kingdom, we process your Personal Information under the following legal bases: - **Contract performance** — Processing necessary to provide the Service to you, including account registration, email processing, and email account hosting. - **Legitimate interests** — Processing necessary for our legitimate interests, such as fraud prevention, abuse detection, service security, and improving the Service, where those interests are not overridden by your rights. - **Legal obligation** — Processing necessary to comply with applicable laws, such as retaining records for anti-abuse and regulatory purposes. - **Consent** — In limited cases where we request your explicit consent to process your Personal Information for a specific purpose. You may withdraw consent at any time by contacting us at [legal@smtp.dev](mailto:legal@smtp.dev). ## IV. How We Protect Information We implement security measures designed to protect your information from unauthorized access. Your account is protected through our third-party authentication provider, and we urge you to take steps to keep your account secure by logging out after each use. We further protect your information from potential security breaches by implementing certain technological security measures including encryption, firewalls and secure socket layer technology. However, no method of electronic storage or transmission is completely secure, and we cannot guarantee absolute security. Nothing in this section limits any rights you may have under applicable data protection law, including GDPR. ## V. Your Rights Regarding the Use of Your Personal Information We do not send marketing or promotional emails. All communications from us are service-related and delivered through the Site. If you are located in the European Economic Area (EEA), United Kingdom, or other jurisdiction with similar data protection laws, you have additional rights under applicable law, including: - **Right of access** — You may request a copy of the Personal Information we hold about you. - **Right to rectification** — You may request that we correct inaccurate or incomplete Personal Information. - **Right to erasure** — You may request deletion of your Personal Information, subject to the retention requirements described in Section X. - **Right to data portability** — You may request an export of your Personal Information in a structured, commonly used, and machine-readable format. - **Right to restrict processing** — You may request that we limit the processing of your Personal Information under certain circumstances. - **Right to object** — You may object to processing of your Personal Information where we rely on legitimate interests as the legal basis. - **Right to withdraw consent** — Where processing is based on your consent, you may withdraw that consent at any time without affecting the lawfulness of prior processing. You also have the **right to lodge a complaint** with your local data protection supervisory authority if you believe your rights have been violated. To exercise any of these rights, please contact us at [legal@smtp.dev](mailto:legal@smtp.dev). We will respond to your request within 30 days. ## VI. California Privacy Rights If you are a California resident, the California Consumer Privacy Act (CCPA) provides you with additional rights regarding your Personal Information: - **Right to know** — You may request that we disclose the categories and specific pieces of Personal Information we have collected about you, the categories of sources from which it was collected, the business purpose for collecting it, and the categories of third parties with whom we share it. - **Right to delete** — You may request deletion of your Personal Information. We may retain certain records where permitted by CCPA exemptions, including for detecting security incidents, exercising legal rights, and complying with legal obligations, as described in Section X. - **Right to opt-out of sale** — We do not sell your Personal Information to third parties. - **Right to non-discrimination** — We will not discriminate against you for exercising any of your CCPA rights. To exercise these rights, please contact us at [legal@smtp.dev](mailto:legal@smtp.dev). We will verify your identity before processing your request and respond within 45 days. ## VII. Email Data The Service receives and processes inbound email messages on your behalf. We store email metadata (sender, recipient, subject, timestamps), message content, and attachments as necessary to provide the Service. The Service does not send outbound emails to external recipients. We do not read, analyze, or use the content of your emails for advertising or any purpose unrelated to service delivery. ## VIII. Third-Party Sender Data When third parties send email to email accounts hosted on the Service, we receive and store data about those senders, including their email addresses, IP addresses, email content, and message metadata. This data is collected as a necessary part of providing the Service to our users who have configured email accounts to receive such email. We process third-party sender data on the basis of legitimate interests — specifically, to deliver the email service that our users have requested. We do not use sender data for marketing, profiling, or any purpose unrelated to email delivery and service operation. Sender data is subject to the same security measures and retention policies described in this Privacy Policy. If you are a third-party sender and wish to inquire about your data, request access, or request deletion, please contact us at [legal@smtp.dev](mailto:legal@smtp.dev). ## IX. Sub-processors and Hosting We use third-party service providers ("sub-processors") to help us operate and deliver the Service, including cloud hosting, authentication, payment processing, and analytics. These sub-processors may process your Personal Information only as necessary to perform their functions and are contractually obligated to protect your data in accordance with this Privacy Policy. Your data, including email content and account information, is primarily stored and processed in the United States. If you are accessing the Service from outside the United States, your information may be transferred to, stored, and processed in the United States or other countries where our sub-processors operate. We ensure appropriate safeguards are in place for international data transfers in compliance with applicable data protection laws, including Standard Contractual Clauses where required. ## X. Account Deactivation and Data Retention You may request to deactivate your account at any time by contacting us at [legal@smtp.dev](mailto:legal@smtp.dev). Upon deactivation, we will remove your personal profile information (name, email address) within 30 days. However, we retain certain operational records — including email logs, IP addresses, account activity history, and transaction records — for abuse prevention and internal compliance purposes. These records may be retained indefinitely in anonymized or pseudonymized form. Full account deletion is not available due to anti-abuse obligations. ## XI. Data Breach Notification In the event of a data breach that compromises your Personal Information, we will notify the relevant supervisory authorities within 72 hours of becoming aware of the breach where required by GDPR, and notify affected users without undue delay as required by applicable law. We will also place a prominent notice on our Site. The notification will describe the nature of the breach, the types of data affected, the measures we are taking in response, and steps you can take to protect yourself. ## XII. Links to Other Websites As part of the Service, we may provide links to or compatibility with other websites or applications. However, we are not responsible for the privacy practices employed by those websites or the information or content they contain. This Privacy Policy applies solely to information collected by us through the Site and the Service. Therefore, this Privacy Policy does not apply to your use of a third party website accessed by selecting a link on our Site or via our Service. To the extent that you access or use the Service through or on another website or application, then the privacy policy of that other website or application will apply to your access or use of that site or application. We encourage our users to read the privacy statements of other websites before proceeding to use them. ## XIII. Changes to Our Privacy Policy The Company reserves the right to change this policy and our Terms of Service at any time. We will notify you of significant changes to our Privacy Policy by placing a prominent notice on our Site. Significant changes will go into effect 30 days following such notification. Non-material changes or clarifications will take effect immediately. You should periodically check the Site and this privacy page for updates. ## XIV. Our Role and Data Processing With respect to the Personal Information and email data we collect and process through the Service, we act as a data controller. We determine the purposes and means of processing your data in order to provide, secure, and improve the Service. If your use of the Service requires a Data Processing Agreement (DPA) for compliance purposes, please contact us at [legal@smtp.dev](mailto:legal@smtp.dev). ## XV. Governing Law This Privacy Policy shall be governed by and construed in accordance with the laws of the State of Delaware, United States, without regard to conflict of law principles. For users in the EEA or United Kingdom, nothing in this Privacy Policy affects your rights under GDPR or the UK Data Protection Act. ## XVI. Contact Us If you have any questions regarding this Privacy Policy or the practices of this Site, please contact us by sending an email to [legal@smtp.dev](mailto:legal@smtp.dev). --- - **Page:** Previewing Emails in Thunderbird and Apple Mail - **Source:** https://smtp.dev/docs/guides/email-clients - **Description:** Connect a real client over IMAP to see how multipart emails render outside the browser. Host, port, and login settings for any client. The [message view](/docs/features/message) shows what arrived. A real client shows what your users see - its own HTML rendering, image blocking, font substitution. Any IMAP client connects to the sandbox like a normal mail server. ## Settings
Protocol Host Port Security
IMAP imap.smtp.dev 993 SSL
SMTP send.smtp.dev 587 TLS
Username is the full address, password is the account password. [POP3 and the unencrypted fallback](/docs/setup/account) are there too. ## Thunderbird ### Open Account Settings → Account Actions → Add Mail Account ### Enter the account's address and password, then choose Configure manually ### Set incoming to IMAP, imap.smtp.dev, port 993, SSL/TLS ### Set outgoing to send.smtp.dev, port 587, STARTTLS, both usernames the full address ## Apple Mail ### Open Mail → Add Account → Other Mail Account ### Enter the account's address and password ### When prompted for servers, enter imap.smtp.dev as incoming and send.smtp.dev as outgoing ## What to Check - **Both parts of a multipart message**: Thunderbird's View → Message Body As switches between HTML and plain text. - **Images blocked**: clients block remote images by default - the email should still make sense without them. - **Replies**: sending from the client works, but [only to addresses that exist as sandbox accounts](/docs/setup/account#limitations). No client install: [webmail.smtp.dev](https://webmail.smtp.dev) gives the same IMAP view in the browser. --- - **Page:** Email Testing for Developers - SMTP Labs, Inc. - **Source:** https://smtp.dev/changelog - **Description:** Email testing sandbox for developers. SMTP in, IMAP/API out. Inspect headers, MIME and raw source. Nothing leaves the sandbox. --- - **Page:** Testing Password Reset Emails End-to-End - **Source:** https://smtp.dev/docs/guides/e2e - **Description:** A Playwright test that triggers a reset, polls the API for the email, extracts the link, and finishes the flow. Same pattern for signup confirmations. The reset email is the step most E2E suites skip or mock. With the app's outbound mail landing in the sandbox, the test follows the real link instead. Two ways to get the mail there: point the app's SMTP transport at `send.smtp.dev` with a sandbox account's credentials (shown in the [CI guide](/docs/guides/ci)), or let the app send through its normal provider to an address on a [domain whose MX points at the sandbox](/docs/setup/domain). ## The Test `inboxOf` and `waitForMessage` are the polling helpers from the [CI guide](/docs/guides/ci). ```ts import { expect, test } from '@playwright/test' test('password reset', async ({ page }) => { const address = 'reset-user@example.com' await page.goto('/forgot-password') await page.getByLabel('Email').fill(address) await page.getByRole('button', { name: 'Send reset link' }).click() const message = await waitForMessage( await inboxOf(address), m => m.subject === 'Reset your password', ) const body = message.text || (message.html ?? []).join('') const link = body.match(/https?:\/\/\S*reset\S*/)?.[0] expect(link).toBeTruthy() await page.goto(link) await page.getByLabel('New password').fill('correct-horse-battery') await page.getByRole('button', { name: 'Set password' }).click() await expect(page).toHaveURL(/signin/) }) ``` The message's `text` field is the plain text part; `html` is an array of HTML parts. If your template only wraps the URL in a button, match the `href` instead: `body.match(/href="([^"]+)"/)?.[1]`. ## Keeping It Stable - **One address per worker.** `reset+worker1@example.com` [delivers to](/docs/features/account#plus-sign-aliasing) `reset@example.com` with the alias intact in `to`, so parallel workers never read each other's mail. Match on recipient and subject, not arrival order. - **Poll tight.** One-second intervals across a few workers sit nowhere near the [4096 requests per minute limit](/docs/api#rate-limiting). - **Or skip polling.** [Subscribe over SSE](/docs/api#real-time-updates) and resolve when a `Message` event for the account arrives. --- - **Page:** Testing Email in CI with GitHub Actions - **Source:** https://smtp.dev/docs/guides/ci - **Description:** Send from your test suite through send.smtp.dev, poll the REST API for the message, and assert on subject and body. Works on any CI. Your code sends over plain SMTP, your test reads the result over the [API](/docs/api). `send.smtp.dev` delivers only to accounts in your sandbox, so test emails can't reach anyone real. ## One-Time Setup ### Create a sender and a receiver account On the [Accounts](/accounts/) page or via the [API](/docs/api#create-an-account) - e.g. `ci@example.com` and `user@example.com`. ### Create an API token On the [API Keys](/tokens/) page. The token is shown once. ### Store the secrets in your repository `SMTP_DEV_API_KEY` (the token) and `SMTP_DEV_PASSWORD` (the sender account's password) under Settings → Secrets and variables → Actions. ## The Test Point your app's SMTP transport at the sandbox. With nodemailer: ```js import nodemailer from 'nodemailer' const transport = nodemailer.createTransport({ host: 'send.smtp.dev', port: 587, requireTLS: true, auth: { user: 'ci@example.com', pass: process.env.SMTP_DEV_PASSWORD }, }) ``` Then assert on what arrived: ```js import assert from 'node:assert' import { test } from 'node:test' const API = 'https://api.smtp.dev' const headers = { 'X-API-KEY': process.env.SMTP_DEV_API_KEY } async function api(path) { const res = await fetch(API + path, { headers }) assert.ok(res.ok, `${path} returned ${res.status}`) return res.json() } async function inboxOf(address) { const { member } = await api(`/accounts?address=${encodeURIComponent(address)}`) const account = member.find(a => a.address === address) const { id, mailboxes } = await api(`/accounts/${account.id}`) return { accountId: id, mailboxId: mailboxes.find(m => m.path === 'INBOX').id } } async function waitForMessage({ accountId, mailboxId }, match, timeout = 30_000) { const deadline = Date.now() + timeout while (Date.now() < deadline) { const { member } = await api(`/accounts/${accountId}/mailboxes/${mailboxId}/messages`) const found = member.find(match) if (found) return api(`/accounts/${accountId}/mailboxes/${mailboxId}/messages/${found.id}`) await new Promise(resolve => setTimeout(resolve, 2000)) } throw new Error(`no matching message after ${timeout}ms`) } test('welcome email', async () => { const subject = `Welcome ${Date.now()}` await transport.sendMail({ from: 'ci@example.com', to: 'user@example.com', subject, text: 'Confirm your address: https://example.com/confirm/abc123', }) const inbox = await inboxOf('user@example.com') const message = await waitForMessage(inbox, m => m.subject === subject) assert.equal(message.from.address, 'ci@example.com') assert.match(message.text, /\/confirm\//) }) ``` Put a unique value in the subject (a timestamp, the commit SHA). Parallel runs share the inbox, and [List Messages](/docs/api#list-messages) returns 30 messages per page, newest first. ## The Workflow ```yaml name: email-tests on: push jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: node-version: 24 - run: npm ci - run: npm test env: SMTP_DEV_API_KEY: ${{ secrets.SMTP_DEV_API_KEY }} SMTP_DEV_PASSWORD: ${{ secrets.SMTP_DEV_PASSWORD }} ``` Nothing here is GitHub-specific. Jenkins, GitLab CI, CircleCI: same two env vars, same SMTP host, same API. Messages stay for your plan's retention window, or [until you delete them](/docs/features/message#message-expiry). Unique subjects keep old runs out of the way; [delete messages](/docs/api#delete-a-message) after each test if you'd rather keep inboxes empty. --- - **Page:** Test Inboxes for AI Agents - **Source:** https://smtp.dev/docs/guides/agents - **Description:** Give an agent a fresh address per run, read OTP codes and confirmation links over the REST API, and keep agent mail out of real inboxes. An agent that exercises your signup flow needs to receive real email: the verification code, the confirmation link, the welcome message. In development that mail shouldn't land in your inbox, and the agent shouldn't be anywhere near production mailboxes. A sandbox domain gives every run its own address, and the API gives the agent a way to read what arrived. ## Setup ### Create a catch-all account on a dev domain Username `*` on e.g. `dev.example.com` - [how catch-all works](/docs/features/account#catch-all-addresses). Every address on the domain is now deliverable without creating accounts. ### Create an API token for the agent On the [API Keys](/tokens/) page. The agent authenticates every request with the `X-API-KEY` header. ## A Fresh Address per Run Derive the address from the run, same as the [QA pattern](/docs/guides/catch-all): ```js const address = `agent-${crypto.randomUUID()}@dev.example.com` ``` The agent signs up with it, and the mail lands in the catch-all's INBOX. ## Reading the OTP `inboxOf` and `waitForMessage` are the polling helpers from the [CI guide](/docs/guides/ci). The catch-all holds mail for the whole domain, so match on the recipient: ```js const inbox = await inboxOf('*@dev.example.com') const message = await waitForMessage( inbox, m => m.to.some(t => t.address === address), ) const otp = message.text.match(/\b\d{6}\b/)?.[0] const link = message.text.match(/https?:\/\/\S*confirm\S*/)?.[0] ``` For a long-running agent, skip polling: [subscribe over SSE](/docs/api#real-time-updates) and hold one connection instead of hammering the list endpoint. ## For the Agent Itself The docs are agent-readable. `https://smtp.dev/llms.txt` indexes the site, and any docs page serves markdown when you append `.md` to its URL. The full API surface is in the [OpenAPI document](https://api.smtp.dev/docs.jsonld). ## Boundaries Receiving is unrestricted: sandbox domains have real MX records, so any service the agent signs up for can deliver to them. Outbound is the opposite - mail from the sandbox only delivers to accounts inside it. An agent with sandbox credentials can read everything on your test domain and email nobody else, which is exactly the blast radius you want while it's under development. --- - **Page:** Email Testing for Developers - SMTP Labs, Inc. - **Source:** https://smtp.dev/dashboard - **Description:** Email testing sandbox for developers. SMTP in, IMAP/API out. Inspect headers, MIME and raw source. Nothing leaves the sandbox. --- - **Page:** Catch-All Inboxes for QA - **Source:** https://smtp.dev/docs/guides/catch-all - **Description:** A * account catches mail for every address on your domain that has no account of its own. A fresh address per test, no setup per address. Signup flows need a new email address every run. Instead of creating an account per test user, [create one catch-all account](/docs/features/account#catch-all-addresses): username `*`, your domain, one password. Now any address on the domain is deliverable. Exact matches still win - mail for `support@qa.example.com` goes to the `support` account if it exists, everything else lands in the catch-all. ## Generating Addresses Derive the local part from the test, so every run is isolated and traceable: ```js const address = `qa-${crypto.randomUUID()}@qa.example.com` ``` Or keep one real account and use [plus aliases](/docs/features/account#plus-sign-aliasing) - `qa+run42@qa.example.com` delivers to `qa@qa.example.com`, and the full alias stays in the `To` header. ## Finding the Message Everything arrives in the catch-all's INBOX, so filter by recipient. Get the account and mailbox ids once: ```bash curl -G "https://api.smtp.dev/accounts" \ --data-urlencode "address=*@qa.example.com" \ -H "X-API-KEY: smtplabs_your_api_key_here" curl "https://api.smtp.dev/accounts/{accountId}/mailboxes" \ -H "X-API-KEY: smtplabs_your_api_key_here" ``` Then match on the `To` header: ```js const { member } = await api(`/accounts/${accountId}/mailboxes/${inboxId}/messages`) const message = member.find(m => m.to.some(t => t.address === address)) ``` The polling helper from the [CI guide](/docs/guides/ci) works here too - pass a different `match`. [List Messages](/docs/api#list-messages) returns 30 messages per page, newest first. A busy catch-all fills pages fast - match on something unique and poll right after the action that triggers the email. --- - **Page:** Domain Setup - **Source:** https://smtp.dev/docs/setup/domain - **Description:** Setting up MX records for inbound email delivery ## MX Record After adding your domain to our system, you'll need to point it to our mail servers: ### Required DNS Record
Type Name Value TTL
MX @ mx.smtp.dev 3600
### Setup Instructions #### **Log in to your domain/DNS provider's website** #### **Find the DNS settings or Domain management section** #### **Create a new MX record with exactly the values shown above** ### Please Note DNS changes don't propagate instantly - it could take anywhere from a few minutes to 24+ hours depending on your DNS provider. If you've just updated MX records, expect spotty email delivery until propagation completes. Some providers like Cloudflare are pretty quick (usually a few minutes). ## Using Subdomains Subdomains work the same way as root domains. ### Subdomain Email Setup
Type Name Value TTL
MX test mx.smtp.dev 3600
MX support mx.smtp.dev 3600
In this example, both `test.example.com` and `support.example.com` would be configured to receive email. ### Why Use Subdomains? - Keep your root domain on its real email provider while `test.example.com` receives in the sandbox - Separate concerns per subdomain (notifications, support, billing) - Test email configurations without touching your main domain's reputation Each subdomain must be added separately before configuring its MX records. For example, to use `support.example.com` and `billing.example.com`, you need to add both domains individually in your dashboard. ### Setting Up a Subdomain Let's say you want emails to arrive at `help@support.example.com`: #### **Add the subdomain in dashboard** Go to the [Domains](/domains/) section of your dashboard and add `support.example.com` as a new domain #### **Configure DNS for the subdomain** Add an MX record for your subdomain:
Type Name Value TTL
MX support mx.smtp.dev 3600
#### **Create a new Account** Create a new account and select the `support.example.com` as the domain name #### **Wait for DNS propagation** Once DNS propagation completes, you can receive emails at any address `@support.example.com`
### Troubleshooting If emails aren't arriving after updating your MX records: #### **Verify your DNS configuration** Check your MX setup using [Google's DNS Toolbox](https://toolbox.googleapps.com/apps/dig/#MX/) by entering your domain name. This tool will confirm if your MX record is correctly configured and visible across the internet. #### **Ensure single MX record configuration** Your domain should have only one MX record pointing to `mx.smtp.dev`. Multiple or competing MX records will interfere with proper mail delivery. Remove any existing MX records from previous email providers before adding ours. If problems persist, please contact our support team for additional assistance. --- - **Page:** Plus-Sign Aliasing and Catch-All Addresses - **Source:** https://smtp.dev/docs/features/account - **Description:** Tag test emails with plus-sign aliases, capture every address on a domain with a catch-all account, and track each account's storage quota. ## Plus-Sign Aliasing Any email sent to `user+anything@yourdomain.com` delivers to `user@yourdomain.com`. This works automatically, no configuration needed. ### Examples ```text john@example.com # The actual account john+shopping@example.com # Delivers to john@example.com john+github@example.com # Delivers to john@example.com john+test-run-42@example.com # Delivers to john@example.com ``` The part after `+` is ignored for delivery but preserved in the `To` header, so you can filter or search by it. ## Catch-All Addresses A catch-all account captures every email sent to your domain that doesn't match an existing account. ### Setup #### Go to the [Accounts](/accounts/) page #### Create a new account with `*` as the username #### Select your domain and set a password #### Any email to an address that doesn't have its own account will land here ### How It Works Say your domain is `example.com` and you have one regular account (`support@example.com`) plus a catch-all (`*@example.com`): - `support@example.com` -> delivered to the **support** account (exact match wins) - `sales@example.com` -> delivered to the **catch-all** - `anything-at-all@example.com` -> delivered to the **catch-all** ## Storage Quota Each account has a storage quota. The accounts list shows how much space is used. If an account fills up, incoming messages will be rejected until you delete old messages. --- - **Page:** Default and Custom Mailboxes - **Source:** https://smtp.dev/docs/features/mailbox - **Description:** Every account starts with Inbox, Sent, Drafts, Trash, and Junk. Create custom mailboxes to sort messages by test run, environment, or client. ## Default Mailboxes Every new account starts with five mailboxes: - **Inbox**: incoming messages - **Sent**: copies of what you send - **Drafts**: unsent messages - **Trash**: deleted messages - **Junk**: spam These can't be deleted. All incoming emails go to the Inbox. The other folders exist for IMAP client compatibility. ## Custom Mailboxes Create additional mailboxes to organize messages by test run, environment, or client. To create a mailbox, open an account in the [Mail](/mail/accounts) section and use the mailbox sidebar, or through the [API](/docs/api). ## Renaming Open a mailbox's context menu in the sidebar to rename it. --- - **Page:** Email Testing for Developers - SMTP Labs, Inc. - **Source:** https://smtp.dev/tokens - **Description:** Email testing sandbox for developers. SMTP in, IMAP/API out. Inspect headers, MIME and raw source. Nothing leaves the sandbox. --- - **Page:** Email Testing for Developers - SMTP Labs, Inc. - **Source:** https://smtp.dev/domains - **Description:** Email testing sandbox for developers. SMTP in, IMAP/API out. Inspect headers, MIME and raw source. Nothing leaves the sandbox. --- - **Page:** IMAP, POP3, and SMTP Connection Settings - **Source:** https://smtp.dev/docs/setup/account - **Description:** Host, port, and security settings for IMAP, POP3, and SMTP. Which protocol to pick, and webmail access without installing a client. ## Connection Settings
Protocol Host Port Security
IMAP imap.smtp.dev 993 SSL
IMAP imap.smtp.dev 143 None
POP3 pop.smtp.dev 995 SSL
SMTP send.smtp.dev 587 TLS
Your username is your full email address (e.g. `user@example.com`) and the password is the one you set when creating the account. Port 143 is an unencrypted fallback for environments where SSL connections are blocked. Use port 993 when possible. ### Which Protocol to Use - **IMAP**: best for most cases. Messages stay on the server, accessible from multiple clients. Use this to test how your app's emails look in Thunderbird, Apple Mail, etc. - **POP3**: downloads messages to your client and can remove them from the server. Pick this for offline access or to test POP3-specific behavior. - **SMTP**: for sending test emails between accounts from a client or application. ## Webmail You can also access your emails through [webmail.smtp.dev](https://webmail.smtp.dev) without installing anything. Direct login link with credentials pre-filled: ```text https://webmail.smtp.dev/?_task=login&_action=auth&_user=user@example.com&_pass=yourpassword ``` ## Limitations You can only send to addresses that exist as accounts in your system. Receiving has no restrictions. --- - **Page:** Inspecting and Composing Messages - **Source:** https://smtp.dev/docs/features/message - **Description:** HTML, plain text, and raw source views. SPF/DKIM/DMARC results on received messages, deliverability audits, and a composer for test emails. ## Viewing Messages Click a message in your mailbox to open it. By default you see the rendered HTML version - the same thing a recipient's email client would display. ### HTML vs Plain Text Use the view switcher in the toolbar to toggle between HTML and plain text. If your emails are multipart, check that both versions render correctly. ### Email Verification Received messages show SPF, DKIM, and DMARC verification results. Instead of digging through raw headers, the platform checks these and tells you whether authentication passed or failed. ### Raw Source The full SMTP source of a message: headers, MIME boundaries, encoded body parts. Open it from the message toolbar. When the verification summary isn't enough and you need the full picture, the source has everything. ### Audit Runs the message through deliverability checks - sender configuration, subject line, HTML structure, links, images, and content patterns that spam filters look for. Open it from the toolbar. Results are grouped by severity: **Needs Attention**, **Review**, and **Passed**. Expand any check to see the detail. ### Attachments Inline attachments render directly in the message view. File attachments can be downloaded individually. You can also download the entire message as a file. ## Composing Emails Send test emails between your accounts directly from the web interface. Open any account in [Mail](/mail/accounts) and click **Compose**. The editor supports: - **Formatting**: bold, italic, underline, strikethrough, blockquotes, lists, links, horizontal rules - **Recipients**: To, CC, BCC, and Reply-To fields - **Attachments**: files from your computer - **HTML / Text**: rich text or plain text You can only send to email addresses that exist as accounts in your system. This is by design - nothing leaves the sandbox. ## Managing Messages ### Read / Unread Messages are marked as read when you open them. You can toggle read status from the toolbar, or select multiple messages and change their status in bulk. ### Flagging Flag messages to mark them as important. Works on single messages or in bulk from the message list. ### Moving Move messages between mailboxes using the move action in the toolbar. Pick a target mailbox from the dropdown. ### Bulk Actions Select messages using the checkboxes in the message list. The toolbar updates to show bulk actions: delete, mark as read / unread, and flag / unflag. ### Message Expiry Individual messages can have their own expiry timer. Once the time runs out, the message gets deleted. ### Printing Print a message from the toolbar. Opens your browser's print dialog with the message content.