Key takeaways
- Transactional email is triggered by a specific user action and sent to one recipient. That single property drives every difference in expectations, architecture, and reputation handling.
- A
200response from a send API means accepted for delivery, not delivered. The delivery outcome arrives asynchronously as a webhook, minutes or hours later. - Since February 2024 (Google and Yahoo) and May 2025 (Microsoft), authentication is a hard gate. Unauthenticated bulk mail is rejected at the SMTP layer, not filtered into spam.
- Transactional and marketing mail share a reputation unless you deliberately separate them by subdomain, signing key, and sending infrastructure.
- The reliability of your transactional mail is bounded by the reputation of whoever else sends from the same IPs.
Transactional email is the category of mail your application sends in direct response to something a specific person did or something that happened to their account. Someone signs up, so you send a verification link. Someone buys, so you send a receipt. Someone logs in from an unfamiliar device, so you send a security alert. Every one of these has an audience of exactly one, and every one is expected within seconds.
That single-recipient, event-triggered shape is what separates transactional email from everything else in the inbox, and it is why the engineering problem is different. A marketing campaign that arrives an hour late is a mild annoyance. A password reset that arrives an hour late is a support ticket, an abandoned session, and — if it happens often enough — a churned customer.
This guide covers the whole surface: the definition and the message types, what actually happens between your API call and the recipient mailbox, the authentication rules mailbox providers now enforce as a condition of delivery, how to structure the sending code in your application, and how to tell whether any of it is working.
What counts as transactional email
A message is transactional when it is generated by a specific event tied to a specific person, and when the recipient would reasonably expect it as a consequence of that event. The test is not the content or the tone — it is the trigger. Nobody subscribes to a password reset. They request one, implicitly, by clicking "forgot password."
This matters legally as well as technically. Most anti-spam regimes — CAN-SPAM in the United States, PECR and the UK GDPR in Britain, CASL in Canada — carve out messages whose primary purpose is to facilitate an already-agreed transaction or provide information about an existing relationship. Those carve-outs are narrower than people assume: adding a promotional block to a receipt can move the whole message into the commercial category, taking its consent and unsubscribe obligations with it.
| Category | Examples | Expected latency | Consent model |
|---|---|---|---|
| Authentication | Verification links, password resets, magic links, one-time codes | Under 10 seconds | Requested by the user in the moment |
| Commerce | Order confirmations, receipts, invoices, shipping and refund notices | Seconds to a few minutes | Implied by the purchase |
| Account lifecycle | Welcome mail, invitations, plan changes, expiry and dunning notices | Seconds to minutes | Implied by the account relationship |
| Security and operations | New-device sign-in alerts, permission changes, incident and uptime notices | Immediate | Implied; often mandatory |
| Application events | Comment and mention notifications, task assignments, export-ready alerts | Seconds to minutes | Governed by user notification settings |
The last row is the boundary case. Notification email is transactional in mechanism — one trigger, one recipient — but it is discretionary in a way a receipt is not. Users can and do mark notification mail as spam when the volume outruns their interest, which is exactly why notification preferences belong in your product and why high-volume notification streams are often worth separating from critical mail.
What actually happens between your API call and the inbox
Most delivery problems are diagnosed badly because the sender has an incomplete mental model of the path. There are five distinct stages, and each one fails in a different way with a different remedy.
- 1
Your application calls the send API
You
POSTa JSON body containingfrom,to,subject, and a body. The API authenticates your key, validates the payload, checks that thefromdomain is verified for your account, and checks the recipient against your suppression list. It responds with a message id. This stage fails synchronously and loudly — you get a4xxwith a reason. - 2
The message is queued and composed
Headers are assembled, the DKIM signature is computed over the selected headers and body, the return path is rewritten so bounces come back to the provider rather than your
fromaddress, and tracking is applied if enabled. Nothing about this stage is visible to you except its output. - 3
The mail server opens an SMTP conversation with the recipient
It resolves the recipient domain MX records, connects, negotiates TLS, and offers the message. The receiving server replies with a status code. This is the first point at which the recipient side has an opinion, and it is where hard rejections surface:
550 5.7.26for failed authentication at Gmail,550 5.7.515at Microsoft consumer domains. - 4
The receiving provider decides on placement
Acceptance is not placement. Once a message is accepted, the provider scores it against sender reputation, content, recipient engagement history, and authentication results, then routes it to the inbox, a tab, or the spam folder. No sender can observe this directly — it is the single biggest blind spot in email.
- 5
Events flow back to you
Delivery confirmations, bounces, complaints, and — if you enable tracking — opens and clicks arrive as webhooks. Bounces and complaints are the ones that matter operationally, because they should mutate your suppression list automatically.
The synchronous half: send and record the id
curl -X POST https://api.supersendtx.com/emails \
-H "Authorization: Bearer stx_…" \
-H "Content-Type: application/json" \
-d '{
"from": "receipts@yourdomain.com",
"to": "customer@example.com",
"subject": "Your receipt",
"html": "<p>Thanks for your order.</p>",
"tags": [{ "name": "order_id", "value": "ord_1042" }]
}'
# => { "id": "msg_01J…", "status": "queued" }- · Store the returned id against your own record so webhook events can be reconciled later.
- · Tags let you filter by your own identifiers when you are investigating a specific order.
The sender requirements you must meet in 2026
Between February 2024 and May 2025, the three largest consumer mailbox providers converted a decade of "best practice" into enforced policy. The practical consequence is that authentication is no longer a deliverability optimisation — it is an admission requirement, and failing it produces an SMTP rejection rather than a spam-folder placement.
| Requirement | All senders | Bulk senders (5,000+/day) |
|---|---|---|
| SPF or DKIM passing | Required | Both required |
| DMARC record published | Recommended | Required, minimum p=none |
DMARC alignment (From: domain matches the authenticated domain) | Recommended | Required |
| Valid forward and reverse DNS on sending IPs | Required | Required |
| TLS on the SMTP connection | Required | Required |
| One-click unsubscribe (RFC 8058) on marketing and subscribed mail | Not applicable | Required |
| Spam complaint rate in Google Postmaster Tools | Keep low | Below 0.10%; never reach 0.30% |
Two details in that table trip up teams who believe they are already compliant. The first is alignment: it is not sufficient for SPF to pass. The domain that SPF or DKIM authenticated has to match the domain in the visible From: header, or DMARC fails regardless. The second is that the volume threshold counts messages to that provider, not messages in total — a product with a consumer user base can cross 5,000 daily Gmail messages long before it feels like a "bulk sender."
The one-click unsubscribe requirement applies to marketing and subscribed messages, not to genuine transactional mail. Adding List-Unsubscribe to a password reset is not merely unnecessary; it invites a user to unsubscribe from mail they cannot function without. Send the header where it belongs and leave it off where it does not.
How to structure transactional sending in your application
The naive implementation calls the email API inline, inside the request handler that produced the event. It works until the day the email provider is slow, at which point your checkout endpoint is slow too. Five patterns separate a durable implementation from a fragile one.
1. Send outside the request path
Enqueue a job; do not call the mail API from the handler that serves the user. This decouples your latency from the provider's, gives you a natural retry surface, and means a provider incident degrades email rather than degrading checkout. The exception is genuinely interactive mail — a magic link the user is sitting and waiting for — where an inline call with a short timeout and a queued fallback is defensible.
2. Make retries safe
Any queue that guarantees at-least-once delivery will eventually run your send twice. Without an idempotency key, the customer gets two receipts. With one, the second attempt returns the original message id and sends nothing. Derive the key from the domain event — the order id, the reset token — not from a random value generated at send time, or retries will produce a fresh key each attempt and defeat the mechanism.
Idempotent send from a queue worker
import { SuperSendTX } from 'supersendtx'
const client = new SuperSendTX(process.env.SUPERSENDTX_API_KEY!)
export async function sendReceipt(order: Order) {
return client.emails.send(
{
from: 'receipts@yourdomain.com',
to: order.customerEmail,
subject: `Receipt for order ${order.reference}`,
html: renderReceipt(order),
text: renderReceiptText(order),
tags: [{ name: 'order_id', value: order.id }],
},
{ idempotencyKey: `receipt:${order.id}` },
)
}- · The key is derived from the order, so every retry of the same job reuses it.
- · Always send a text alternative — some clients and most accessibility tooling prefer it.
3. Respect suppression before you send
When an address hard bounces or a recipient files a complaint, sending to it again is actively harmful: repeated delivery attempts to invalid mailboxes are one of the clearest spam signals available to a receiving provider. A suppression list closes that loop automatically, and a good provider enforces it on your behalf at send time rather than trusting you to check.
4. Consume the event stream
Webhooks are how you learn what happened after acceptance. At minimum, subscribe to delivery, bounce, and complaint events, verify the signature on each payload, and write the outcome back against your own record. The payoff is that "did the customer get their receipt?" becomes a database query instead of a support conversation.
5. Keep the content boring and useful
- Always include a plain-text alternative alongside the HTML.
- Put the important action — the link, the code, the amount — in the first screenful, before any imagery.
- Use a
fromaddress on a domain the recipient recognises, and areply-tothat a human actually monitors. - Avoid link shorteners and redirect chains; both are strongly associated with abuse.
- Keep the subject line descriptive rather than urgent.
Reset your passwordoutperformsAction required!!
Measuring transactional email properly
Marketing metrics translate badly to transactional mail. Open rate on a receipt tells you little about health, and click rate on a password reset is a function of how many people forgot their password, not how good your email is. The metrics that indicate whether the system is working are narrower.
Delivery rate
≥ 99%
accepted / attempted
Hard bounce rate
< 1%
invalid recipients
Complaint rate
< 0.1%
never reach 0.3%
Time to inbox
p95 < 30s
trigger to delivered event
Two of those deserve comment. Time to inbox is measured from your domain event, not from your API call — if a message sits in your own queue for four minutes, that is your outage, and measuring only the provider leg hides it. And complaint rate should be tracked per stream: a blended figure across receipts and product announcements will look acceptable right up until the announcements get your receipts filtered.
Beyond your own instrumentation, register every sending domain in Google Postmaster Tools and Microsoft SNDS. These are the only sources that report on reputation and spam rate from the receiving side. Your provider can tell you a message was accepted; only the receiver can tell you what it thought of you.
- Delivery, bounce, and complaint webhooks consumed and persisted
- Alert on hard bounce rate crossing 2% in a rolling hour
- Alert on complaint rate crossing 0.1% in a rolling day
- Google Postmaster Tools registered for every sending subdomain
- Microsoft SNDS registered for your sending IP ranges
- Time-to-delivered tracked from the domain event, not the API call
Why the infrastructure underneath matters
Everything above is within your control. The part that is not is whose reputation your mail inherits. Mailbox providers score the sending IP and the sending domain, and on a shared pool the IP portion of that score is a shared asset — built by every sender on the pool and damaged by any one of them.
This is the uncomfortable arithmetic of transactional email: you can hold a perfect complaint rate, authenticate flawlessly, and still see delivery degrade because an unrelated customer on the same infrastructure ran a bad campaign. The failure is invisible to you, it arrives without warning, and there is no lever on your side to pull.
The mitigations are structural rather than tactical. Send transactional mail from a subdomain with its own DKIM key so domain reputation is scored separately. Choose infrastructure whose other tenants resemble you — a pool that carries only paying transactional senders behaves very differently from one that carries free-tier signups and marketing blasts. And above a certain volume, stop sharing the IP layer at all.
| Concern | Shared pool | Dedicated infrastructure |
|---|---|---|
| IP reputation | Shared with every other tenant | Determined entirely by your own sending |
| Blast radius of a neighbour incident | You absorb it | None — no neighbours |
| Time to trusted | Immediate — inherits the pool | Requires a warmup ramp |
| Volume needed to sustain it | None | Consistent, near-daily sending; roughly 100k/month is the practical floor |
| Allowlisting and security review | Hard — the IP set is not yours | Straightforward — the IPs are yours to name |
That last row is the one enterprise buyers raise first and most providers answer worst. When a customer's security team asks which IP addresses your mail arrives from so they can allowlist it, "a shared range that may change" is not an answer that survives a procurement review.
SuperSend TX is built around this distinction. Production mail runs on a transactional-only pool carrying paying customers exclusively — no free-tier signups, no marketing campaigns, no cold outbound. When you need genuine isolation, Dedicated provisions your own mail servers and IP addresses, which we build, warm through the full ramp, and operate. The API contract is identical either way, so moving between them is a billing change rather than a migration.
Send your first transactional email
Verify a domain, create an API key, and call POST /emails. Sandbox is free for integration work; production runs on a transactional-only network with a path to your own dedicated servers and IPs.
Related reading