Transactional email versus marketing email, and why the split matters
Teams usually discover this distinction after a marketing campaign drags their password reset mail into the spam folder. The two categories look similar from inside your codebase, and they are treated as entirely different things by mailbox providers and by law.
4 min read
The actual difference
Not tone, not template, not which team wrote it. The test is consent.
Transactional mail is a response to something a specific person did. They signed up, so they get a verification link. They ordered, so they get a receipt. They asked to reset a password, so they get a reset link. The recipient initiated it, they are expecting it, and withholding it would break the product.
Marketing mail is something you decided to send. A product announcement, a newsletter, a re-engagement campaign, a discount. The recipient may have consented to receive mail in general, but they did not trigger this particular message.
| Transactional | Marketing | |
|---|---|---|
| Triggered by | The recipient's action | Your decision |
| Consent | Implied by the action | Explicit opt-in required in many jurisdictions |
| Unsubscribe link | Not required, and often wrong to include | Required, and must be honoured promptly |
| Expected volume | One at a time, as events happen | Bursts to a list |
| Engagement | High. People open receipts and codes | Lower, and it varies enormously |
| Cost of non-delivery | The product is broken | A campaign underperforms |
Where it gets ambiguous
Real messages sit on the line. The safe rule: if a message contains anything promotional, treat the whole message as marketing.
| Message | Classification | Why |
|---|---|---|
| Password reset | Transactional | They asked for it seconds ago |
| Order receipt | Transactional | Direct result of a purchase |
| Receipt with "you may also like" | Marketing | The promotional block converts it |
| Trial ending in three days | Transactional, usually | Tied to their account state, not a campaign |
| Trial ending, with an upgrade discount | Marketing | The offer is the point |
| Monthly usage summary | Marketing | You chose the schedule, not them |
| Security alert about a new sign-in | Transactional | Safety-critical and event-driven |
| "We miss you, come back" | Marketing | Nothing they did triggered it |
Getting this wrong in the promotional direction risks a complaint and, in some jurisdictions, a fine. Getting it wrong in the other direction, treating marketing as transactional to skip the unsubscribe link, is worse: it is the specific behaviour that gets a sending account reviewed and suspended.
Why mixing them costs you deliverability
Mailbox providers build reputation for the domain and the sending infrastructure, not for the individual message. That reputation is driven mostly by engagement: opens, replies, deletions without reading, and above all complaints.
Transactional mail has excellent engagement. People open a verification code within a minute. Marketing mail, even good marketing mail, has ordinary engagement and attracts complaints, because the spam button is how most people unsubscribe.
Send both from acme.com and you average the two together. The complaints from a campaign sent to fifty thousand people become part of the reputation your password reset mail depends on. The campaign does not care much whether it lands in Promotions. The reset link does.
Separate at the subdomain
The fix is to give each stream its own reputation, which means its own subdomain with its own DKIM key.
mail.acme.com transactional: receipts, verification, resets, alerts
news.acme.com marketing: campaigns, newsletters, announcements
acme.com your corporate domain, publishing DMARC policy for bothPublish the authentication entries under each subdomain separately. Publish DMARC at the organisational domain, and use the sp tag if you want subdomains governed by a different policy than the parent.
_dmarc.acme.com. TXT "v=DMARC1; p=reject; sp=reject; rua=mailto:dmarc@acme.com"Now a campaign that attracts complaints damages news.acme.com and leaves mail.acme.com alone. This separation is also why some providers refuse to carry bulk marketing mail at all: they are protecting the reputation of the infrastructure your transactional mail shares.
Separate in your code too
The classification should be a property of the message, decided once, not inferred at the call site by whoever is writing the feature.
type Stream = 'transactional' | 'marketing';
const FROM: Record<Stream, string> = {
transactional: 'Acme <hello@mail.acme.com>',
marketing: 'Acme <news@news.acme.com>'
};
export async function send(stream: Stream, input: {
to: string;
subject: string;
html: string;
text: string;
}) {
if (stream === 'marketing' && !(await hasOptedIn(input.to))) return { skipped: true };
if (stream === 'marketing' && !input.html.includes('unsubscribe')) {
throw new Error('marketing mail needs an unsubscribe link');
}
const res = await fetch('https://emails.sh/v1/emails', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.EMAILSSH_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
from: FROM[stream],
to: [input.to],
subject: input.subject,
html: input.html,
text: input.text,
tags: { stream },
headers:
stream === 'marketing'
? { 'List-Unsubscribe': '<https://acme.com/unsubscribe>', 'List-Unsubscribe-Post': 'List-Unsubscribe=One-Click' }
: undefined
})
});
if (!res.ok) throw new Error(`send failed: ${res.status}`);
return res.json();
}Two things worth stealing from that. The opt-in check runs for marketing and not for transactional, so a marketing send to someone who unsubscribed cannot happen by accident. And List-Unsubscribe with one-click support is required by the major mailbox providers for bulk senders, so build it in rather than adding it under pressure later.
Suppression lists are not shared
A user who unsubscribes from your newsletter must still receive their password reset. If you keep one suppression list and apply it to everything, you will lock someone out of their account because they did not want a monthly digest. Keep marketing opt-out separate from hard bounces and complaints, which do apply to both. That distinction is the subject of bounces, complaints, and suppression lists.
Questions
- Can I put an unsubscribe link in a transactional email?
- Avoid it. If a user unsubscribes from receipts and you honour it, they stop receiving proof of payment. If you do not honour it, the link is a lie. Keep transactional mail free of unsubscribe controls and make the marketing preference separate.
- Does adding a promotion to a receipt make it marketing?
- Yes, in most jurisdictions and in the eyes of most mailbox providers. The safest rule is that any promotional content converts the whole message, so keep the upsell out of the receipt and send it separately.
- Do I need a separate subdomain for marketing mail?
- If you send meaningful campaign volume, yes. Reputation attaches to the sending domain, so a campaign that attracts complaints will otherwise degrade the placement of your verification and reset mail.
- Which stream does a trial expiry notice belong to?
- Transactional if it states a fact about their account, marketing if it carries an offer. The same underlying event can produce either, so classify the message rather than the trigger.
Give your agent an address it can answer from.
Create an inbox