I’m building Inbox Placement Test, a service that receives test copies of emails and reports where they land across different mailbox providers. A user sends a message from their CRM, application, or email platform, then receives the test results.
The engineering challenge is separating the state of a message from the state of the system observing it. A mistake here can lead to the wrong decision: pausing a healthy sending process, for example, or overlooking a problem with customer notifications.
This article examines the method’s main limitations and what a reliable testing tool needs to account for.
- Successful sending does not tell you the destination folder
An SMTP 250 response after the message data has been transmitted means the receiving server has accepted responsibility for delivery or further relay. It does not confirm inbox placement, let alone that the recipient has read the message. This distinction follows from the SMTP model in RFC 5321, sections 4.2.5 and 6.1. [1]
Inbox placement testing adds a recipient-side observation: where the test copy was found. The result applies to a specific message, mailbox, and observation time. Those conditions need to be recorded alongside the result.
- An unavailable test mailbox is not an undelivered email
Suppose a message is already in the inbox, but the testing service cannot access the mailbox. The Gmail API, for example, documents authentication failures, rate and concurrency limits, and temporary server errors. None of these errors, on its own, tells us what happened to the message. [2]
The result model needs to distinguish three cases: the message was found; it was not found within the observation window while checks were functioning; or the observation could not be completed.
The last case must not automatically become Spam or Not delivered. A result might look like this. This is an illustrative model, not my service’s API schema:
{
"provider": "gmail",
"mailbox_access": "unavailable",
"message_observation": "unknown",
"folder": null,
"category": null,
"error": "auth_expired"
}
For transient errors, Google recommends retries with exponential backoff. [2] A testing system also needs a time limit and a way to preserve partial results: one failed connection should not discard observations already collected from other mailboxes.
Even a functioning check that reports “not found within ten minutes” does not establish permanent non-delivery. Investigating the missing message requires sending logs, not an explanation inferred from a timer.
- Reading a message can change what you are measuring
In IMAP, fetching message content with BODY[...] can implicitly set the \Seen flag. BODY.PEEK[...] retrieves the content without making that change. RFC 9051, section 6.4.5, documents the distinction. [3]
This matters for a testing service. In Exchange Online, Zero-hour Auto Purge can act on messages that have already been delivered. In particular, ZAP for spam applies to unread messages and can move them to Junk Email or quarantine, depending on the configured policy. [4]
Together, these properties imply a practical requirement: the observer should not change a message’s read status unnecessarily. Otherwise, it changes a condition that can affect subsequent processing in this configuration.
Detecting a later move requires observing the same message again. Sending another copy creates a different test. “In the inbox after one minute” does not describe the message’s state two hours later.
- Folders, categories, and threads must not be conflated
In Gmail, Promotions is an inbox category, not spam. A message can have multiple labels in the Gmail API, including the system labels INBOX and CATEGORY_PROMOTIONS. Finding INBOX alone is therefore insufficient to conclude that the message reached the Primary category. [5, 6]
There is another detail: a thread’s labels represent the combined labels of its messages. A label associated with the thread is not necessarily present on every message in it. Placement must therefore be determined for the individual message, not inferred from the thread as a whole. [5]
When normalizing results, the service should retain the provider’s original folder or label data. An unknown state is better reported explicitly than forced into the nearest category available in the interface.
- The test needs to represent the production sending process
An email sent from a personal account does not test the delivery path of a CRM notification. A comparable test needs the same sending system, sender, template, links, tracking configuration, and attachment types. Sensitive information should be replaced with synthetic data while preserving the message’s relevant structure.
When a test and a campaign use different outbound IP addresses, their conditions differ. Google explicitly discusses the effects of shared-IP reputation, sending volume, and recipient complaints. A single test message does not reproduce those conditions for an entire campaign. [7]
When comparing tests, it is useful to record the template version and actual outbound IP, where that IP can be reliably identified. A change in the sending pool should not remain an unobserved variable.
Test mailboxes are not a random sample of subscribers, either. Gmail takes users’ movements of messages between categories into account. Ten test addresses do not reproduce the correspondence histories and settings of ten thousand customers. [6]
“Nine out of ten copies reached the inbox” describes the test. It does not establish a 90% inbox placement rate across the customer base. During domain warm-up, repeated checks can help track changes, but they cannot identify a universal point at which a domain is “ready” for any sending volume.
- Diagnostic conclusions need evidence
The destination folder and the reason for filtering are different pieces of information. Finding a message in spam does not prove that a particular word, link, or DNS issue caused the classification. A detected problem provides a hypothesis to investigate, not a complete explanation of the provider’s decision.
Even authentication results require careful interpretation. An arbitrary Authentication-Results header should not be trusted simply because it appears in the message. RFC 8601 requires attention to the source of these assertions and the relevant trust boundary: a header can contain unverified claims. [8]
Inbound and outbound infrastructure must also be distinguished. In my Domain Watch service, for example, PTR and blocklist checks cover a limited subset of IP addresses associated with inbound MX servers. These checks do not identify the outbound IP of a particular message or verify its DKIM signature. Domain monitoring and test sending therefore complement one another; they are not interchangeable. [9]
- The email being tested is untrusted input
If a service fetches links for analysis, it becomes an HTTP client requesting addresses supplied by the sender. Incorrect handling creates a server-side request forgery risk: an attacker may cause the service to request internal resources. OWASP recommends combining address validation with network restrictions and accounting for redirects. [10]
Link checking should therefore be isolated from internal infrastructure. I also consider message and attachment size limits, report access controls, and a defined retention period to be requirements for this kind of service. Notification tests should use synthetic data, not real passwords, payment documents, or active account-recovery links.
What is available in my service
Inbox Placement Test lets users send an email to test addresses at the available providers and receive placement results and diagnostics. The free web test requires no registration and allows up to three tests per sender address and ten per IP address per day. A test runs for up to ten minutes; unavailable test mailboxes are reported separately. [11]
REST API and MCP access are available for automation, with authentication, quotas, and separate access terms. The project’s Telegram bot is @InboxPlacementBot. Free domain monitoring checks email-related configuration approximately every six hours. [9, 11, 12]
Around 100 tests have been run so far. I would appreciate tests from your CRMs and applications, particularly reports of unclear results or integration problems.
Conclusion
The quality of an inbox placement testing tool depends on whether its observation conditions can be reconstructed and whether a delivery problem can be distinguished from a failure in the measurement system. A useful result needs a reliable status, an observation time, stated limitations, and supporting evidence.
Such a tool provides an additional check for emails sent by CRMs, SaaS applications, and email platforms. It can help detect changes, but it does not replace sending logs or guarantee where every customer’s email will land.
References
RFC 5321 — Simple Mail Transfer Protocol, sections 4.2.5 and 6.1.
Google — Resolve errors in the Gmail API.
RFC 9051 — Internet Message Access Protocol (IMAP) Version 4rev2, section 6.4.5.
Microsoft — Zero-hour auto purge, ZAP for spam.
Google — Manage labels.
Google — Add or remove inbox categories in Gmail.
Google — Email sender guidelines.
RFC 8601 — Message Header Field for Indicating Message Authentication Status, sections 1.1–1.2 and 5.
Live Direct Marketing — Domain Watch.
OWASP — Server-Side Request Forgery Prevention Cheat Sheet.
Live Direct Marketing — Inbox Placement Test.
Live Direct Marketing — REST API and MCP.
Author disclosure: I develop the service described in this article. The article discusses measurement requirements; it is not a comparative product study. The architectural examples do not imply that every mechanism discussed is already implemented in my service.
Top comments (0)