# Does My Email Work — Full Reference > Free email deliverability scanner. Checks a domain's SPF, DKIM, DMARC, and MX records using public DNS and explains, in plain English, why its emails might be going to spam. No signup, no account, no API key. Built by Valentin Bora, Mach10 ([mach10.pro](https://mach10.pro)). This is the comprehensive, machine-readable reference for [doesmyemail.work](https://doesmyemail.work). It is intended for AI agents and developers. For the short index, see [llms.txt](https://doesmyemail.work/llms.txt). ## Product overview Does My Email Work answers one question: "Will email from this domain actually arrive, or will it land in spam?" It runs a read-only DNS scan of the records that mailbox providers (Gmail, Outlook, Yahoo, Apple) use to decide whether to accept, quarantine, or reject a message, then explains the result in plain English for non-technical site owners. - Read-only: it performs public DNS lookups only. It never sends email, changes records, or needs credentials. - No signup, no account, no API key. - Free public HTTP API, NLWeb `/ask` endpoint, and an MCP server. ## The website-email vs mailbox-email problem The single most common cause of "our email goes to spam" is a misunderstanding about *where* email is sent from. - **Mailbox email** is what a person sends from Gmail, Outlook, or their email client. These providers authenticate outgoing mail automatically, so it usually arrives fine. Because this works, owners assume "email works." - **Website email** is what the site itself sends: contact-form notifications, WooCommerce order confirmations, password resets, account verifications, invoices. These are sent by the web server or a transactional service, often through a *different* path that has no SPF/DKIM/DMARC alignment configured for the domain. The result: the owner's personal email arrives, but the website's transactional email silently lands in spam. The scanner checks the records that govern *both* paths, so the gap becomes visible. See [How email routing works](https://doesmyemail.work/how-email-works/). ## What SPF, DKIM, DMARC, and MX mean - **SPF** (Sender Policy Framework): a DNS TXT record listing which servers are allowed to send email for the domain. If the website's sending server is not listed, receivers may treat the mail as forged. SPF has a hard limit of 10 DNS lookups; exceeding it breaks SPF. Common problems: `permissive_all` (a `+all` that authorizes anyone), `ptr_deprecated` (use of the deprecated `ptr` mechanism), and `multiple_records` (more than one SPF record, which is invalid). - **DKIM** (DomainKeys Identified Mail): a cryptographic signature added to outgoing mail, with the public key published as a DNS TXT record under a *selector* (e.g. `google._domainkey.example.com`). Receivers verify the signature to confirm the message was not altered and really came from the domain. - **DMARC** (Domain-based Message Authentication, Reporting & Conformance): a DNS TXT record at `_dmarc.example.com` that tells receivers what to do when SPF/DKIM fail. A policy of `p=none` only monitors; `p=quarantine` or `p=reject` is *enforced* and actively protects the domain. - **MX** (Mail Exchanger): DNS records naming the servers that *receive* mail for the domain. The scanner also identifies the provider (e.g. Google Workspace, Microsoft 365, Zoho) from the MX host. ## API reference Base URL: `https://doesmyemail.work`. All endpoints are public and require no authentication. Responses are JSON. ### GET /api/v1/dns-scan/{domain} Scan one domain's email authentication records. This path-based form is the **preferred URL style**: the domain is part of the path, so URL-keyed caches treat every domain as a distinct entry. Some fetchers and intermediaries discard query strings when building cache keys, which can silently return another domain's cached result from the `?domain=` form. Path parameters: - `domain` (required): a bare domain, e.g. `example.com` (no protocol, no path). Must match `^[a-z0-9.-]+\.[a-z]{2,20}$`. Example request: ``` GET https://doesmyemail.work/api/v1/dns-scan/sandbox.doesmyemail.work ``` For real domains, replace the domain segment. The response always includes `"domain"` at the top level — verify it matches what you requested before reporting results. The query-string form `GET /api/v1/dns-scan?domain={domain}` remains supported with identical behavior, but prefer the path form. **CORS:** the single-domain GET endpoints send `Access-Control-Allow-Origin: *`, so browser pages can call them directly (rate-limit headers are exposed via `Access-Control-Expose-Headers`). The batch endpoint `POST /api/v1/scan` is same-origin only. **Caching caveat:** Your HTTP client may cache scan results for several minutes regardless of URL style. If the user fixes a DNS record and you re-scan, the result may be stale; allow a few minutes, or use the MCP `scan_domain` tool (POST transport, never URL-cached). **Restricted fetchers:** Some agent HTTP fetch tools only allow URLs that appeared verbatim in prior search/fetch results. They cannot fetch freshly constructed scan URLs. Prefer the MCP `scan_domain` tool (`POST /mcp`), `POST /api/v1/scan` with a JSON body, or ask the user to paste the full scan URL. Never reuse a documentation/sandbox URL and attribute those results to a different domain. Example JSON response (`200`): ```json { "domain": "sandbox.doesmyemail.work", "spf": { "found": true, "value": "v=spf1 include:_spf.google.com ~all", "lookups": 1, "issues": [], "mechanisms": ["include:_spf.google.com", "~all"] }, "dkim": { "found": true, "selector": "google" }, "dmarc": { "found": true, "enforced": true, "value": "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com" }, "mx": { "found": true, "null_mx": false, "receives_mail": true, "records": ["aspmx.l.google.com", "alt1.aspmx.l.google.com"], "provider": "Google Workspace / Gmail" }, "cloudflare": true, "nameservers": ["ns1.example.com", "ns2.example.com"], "provider": "Cloudflare" } ``` If DNS does not respond (e.g. the domain does not exist), the endpoint returns `200` with `{ "error": "dns-failed" }`. ### POST /api/v1/scan Batch scan multiple domains in a single request. Send a JSON body with a list of domains; the response contains one scan result per domain, each matching the `dns-scan` shape above. Example request: ```json { "domains": ["example.com", "another.org"] } ``` ### POST /ask (NLWeb) Ask a plain-English question about a domain's deliverability and receive a structured, conversational answer. Useful when you do not want to parse raw records yourself. Example request: ```json { "query": "Why is email from example.com going to spam?" } ``` ### Error codes - `400 Bad Request`: invalid or missing domain (fails the domain pattern, or shorter than 4 characters). - `422 Unprocessable Entity`: the request body is well-formed JSON but semantically invalid (e.g. empty `domains` array on the batch endpoint). - `429 Too Many Requests`: rate limit exceeded (10 distinct domains per hour per IP). Error body shape: ```json { "error": "rate-limited", "message": "You've scanned 10 domains this hour. Try again later." } ``` ### Rate-limit headers The HTTP API allows **10 distinct domains per hour per IP**. Re-scanning a domain already counted in the current hour does not consume additional quota. When the limit is exceeded, the API responds `429`. Rate-limit state is keyed per IP per hourly bucket. ### Sandbox Use `sandbox.doesmyemail.work` as a sandbox domain for testing client integrations without consuming rate-limit quota against real domains. It returns a representative, stable scan result so you can validate parsing and error handling. ## Authentication There is **no authentication**. No API keys, tokens, accounts, OAuth flows, or registration. Every endpoint is open and anonymous. - The only access control is the per-IP rate limit on the HTTP scan API (10 domains/hour/IP). - The MCP server is stateless and unauthenticated. - Because there is no protected resource, no OAuth/OIDC metadata is published. See [auth.md](https://doesmyemail.work/auth.md). ## MCP server The MCP server lets agents call the scanner as a tool. - **Endpoint**: `POST /mcp` - **Transport**: Streamable HTTP, JSON-RPC 2.0 - **Protocol versions**: `2025-06-18` (default), `2025-03-26`, `2024-11-05` - **Server card**: [/.well-known/mcp/server-card.json](https://doesmyemail.work/.well-known/mcp/server-card.json) Tools: - `scan_domain` — Check a domain's email authentication (SPF, DKIM, DMARC, MX) using public DNS. Input: `{ "domain": "example.com" }`. Returns a plain-text summary plus `structuredContent` matching the `dns-scan` JSON shape. - `get_email_guide` — Returns the plain-English guide to SPF, DKIM, and DMARC for site owners, so an agent can explain results without external lookups. Example `tools/call` request: ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "scan_domain", "arguments": { "domain": "example.com" } } } ``` ## Quickstart: curl ```bash # Scan a single domain (path style, preferred) curl "https://doesmyemail.work/api/v1/dns-scan/example.com" # Call the MCP scan_domain tool curl -X POST "https://doesmyemail.work/mcp" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"scan_domain","arguments":{"domain":"example.com"}}}' ``` ## Quickstart: JavaScript fetch ```js async function scan(domain) { const res = await fetch( `https://doesmyemail.work/api/v1/dns-scan/${encodeURIComponent(domain)}` ); if (res.status === 429) throw new Error("Rate limited: 10 domains/hour/IP"); if (!res.ok) throw new Error(`Scan failed: ${res.status}`); const result = await res.json(); if (result.error) throw new Error(result.error); // e.g. "dns-failed" const problems = []; if (!result.spf.found) problems.push("No SPF record"); if (!result.dkim.found) problems.push("No DKIM detected"); if (!result.dmarc.found) problems.push("No DMARC record"); else if (!result.dmarc.enforced) problems.push("DMARC not enforced (p=none)"); if (!result.mx.found) problems.push("No MX records"); return { provider: result.mx.provider, problems }; } scan("example.com").then(console.log); ``` ## Fix offer When a scan finds authentication issues, Valentin offers a **$59 white-glove DNS fix** (SPF, DKIM, DMARC, MX records published and re-verified), typically within 24–48 hours, with a money-back guarantee if the setup cannot be improved. Checkout is on the scan results page (Wise). For complex multi-sender or WordPress SMTP setups, book a call: https://cal.eu/valentinbora/15-min-with-valentin-email-broken ## Industry guides Vertical-specific explainers (all funnel to the free scanner at https://doesmyemail.work/): - https://doesmyemail.work/for/ — hub - https://doesmyemail.work/for/woocommerce/ - https://doesmyemail.work/for/lms/ - https://doesmyemail.work/for/membership/ - https://doesmyemail.work/for/health-supplements/ - https://doesmyemail.work/for/trades/ - https://doesmyemail.work/for/nonprofits/ - https://doesmyemail.work/for/law-firms/ - https://doesmyemail.work/for/real-estate/ Mach10.pro (`https://mach10.pro`) is the parent consultancy brand; legacy `/email-fix-*` URLs redirect here. ## Links - [Guide: SPF, DKIM & DMARC explained](https://doesmyemail.work/guide/) - [How email routing works](https://doesmyemail.work/how-email-works/) - [Compare](https://doesmyemail.work/compare/) - [Documentation](https://doesmyemail.work/docs/) - [About](https://doesmyemail.work/about/) - [Contact](https://doesmyemail.work/contact/) - [OpenAPI spec](https://doesmyemail.work/.well-known/openapi.json) - [API catalog](https://doesmyemail.work/.well-known/api-catalog) - [MCP server card](https://doesmyemail.work/.well-known/mcp/server-card.json) - [auth.md](https://doesmyemail.work/auth.md) Author: Valentin Bora, independent developer and email deliverability consultant. Company: Mach10 ([mach10.pro](https://mach10.pro)). Contact: valentin@doesmyemail.work.