Transactional emails are the ones users expect because their own action triggered them: an order confirmation, a login code, the link to reset a password, a payment receipt, an alert about a new sign-in to the account. They behave very differently from newsletters. They are expected, often urgent, and when they don't arrive the user doesn't think «I'm not interested», they think «the service is broken». That is why they deserve dedicated attention.
Why they are different
Compared with promotional campaigns, transactional messages have:
- very high open rates and almost no spam complaints;
- critical timing: a code that arrives after ten minutes has often already expired;
- irregular volumes, driven by user activity rather than a calendar;
- recipients who cannot be excluded: even someone who unsubscribed from the newsletter must get their receipt.
These traits make it the traffic with the best reputation. The main risk is contaminating it with promotional traffic.
Separating the flows
The most important rule is not to mix transactional and promotional mail on the same sending identity. If a campaign generates many complaints or hits spam traps, the reputation damage must not delay password resets.
Separation is built on several levels:
| Level | Example |
|---|---|
| sending subdomain | account.example.com for transactional, news.example.com for campaigns |
| DKIM signature | a separate key and signing domain for each flow |
| Return-Path | a separate return domain, to handle bounces separately |
| IP or pool | if the platform allows it, flows on different pools |
| platform | in some cases, different services for the two kinds of traffic |
To be clear: the main domain's reputation remains linked to its subdomains. Separation reduces how far problems spread; it doesn't eliminate them. The safest way to protect transactional mail is still to run your campaigns well.
Sending from the application without losing messages
Many transactional email problems have nothing to do with spam filters, but with how the application generates the messages.
Don't send inside the user's request
If the application connects to the mail server while the user waits for the page to load, a slowdown at the sending service becomes a slowdown of the site, and a temporary error becomes a lost message. It is better to put the message in a queue and have a separate process send it, one that can retry on failure.
Handling errors and retries
Sending platforms, via SMTP or API, can answer with temporary errors. The process draining the queue should:
- retry temporary errors with increasing delays;
- not retry permanent errors forever;
- log every attempt with an identifier, so you can answer a user who says they received nothing.
Avoid the unconfigured local mail server
A common mistake on small sites is letting the CMS send through the web server's default mail function. Those messages often leave from an IP with no reputation, without DKIM, with a misaligned sender, and end up in spam or rejected. Configuring sending through an authenticated service is almost always the first fix to make.
Content: clear, short, no promotions
A transactional email should do one thing. Some practical pointers:
- a descriptive subject: «Your login code» or «Order 4821 confirmed»;
- a sender consistent with the service name the user knows;
- the key information at the top: the code, the link, the amount;
- a plain-text version alongside the HTML one;
- no intrusive promotional content, which would change the nature of the message in the eyes of filters and, in many cases, of the rules on commercial communications.
For codes and reset links, it helps to state how long they remain valid and to explain what to do if the user didn't make the request.
Monitoring what you can't see
The problem with transactional mail is that nobody complains until it is too late. So it pays to check actively:
- the time between generation and delivery, to spot delays;
- bounces and rejections, split by provider;
- daily volume, with an alert if it drops to zero: that often means the queue is stuck;
- receipt in a few test mailboxes at the main providers.
In my work, the zero-volume alert has caught more failures than any other check: an integration broken by an update doesn't throw errors, it simply stops sending.
In short
- Transactional mail is expected and urgent: a delay is perceived as a service failure.
- It should be separated from campaigns with subdomains, DKIM signatures and, where possible, distinct IPs.
- The application should send through a queue with retries, not during the user's request.
- Content should be short, clear and free of intrusive promotions.
- An alert on zero daily volume catches silent failures.