Transactional Email
Transactional email is mail an application sends in response to a user action — verification links, password resets, contact-form notifications. The transport is trivial: any HTTP API provider (Resend, SES, Postmark) will accept your payload and hand it to the receiving server in seconds. The hard part is trust. Every message you send is judged by receiving-side filters trained on decades of spam and phishing, and their verdict — inbox, junk, quarantine, or silent drop — is invisible to you unless you know where to look. Deliverability is not a transport problem; it is an identity and reputation problem, and most of the work happens in DNS before the first message is ever sent.
Encountered at SFI in July 2026: contact-form notifications from streetfortress.com vanished despite Resend reporting delivered, traced to Microsoft 365's admin quarantine (sfi-website PR #43); the account-lifecycle emails that prompted the re-test were added in PR #36.
Delivered means accepted, not read
A provider's delivered event maps to one thing: the receiving mail server answered 250 OK at the end of the SMTP transaction. That is acceptance for processing, not placement in an inbox. Modern receivers — Microsoft 365's Exchange Online Protection (EOP), Google Workspace — deliberately accept first and classify after, because rejecting at SMTP time leaks information to spammers. Post-acceptance, a message can land in the inbox, the junk folder, an admin quarantine the mailbox owner never sees, or be retroactively removed by Microsoft's zero-hour auto purge (ZAP) after initial delivery.
This splits debugging cleanly in two. The provider's dashboard and events prove the handoff (sent, delivered, bounced); everything after the handoff belongs to the receiving tenant. For Microsoft 365 that means the quarantine review at security.microsoft.com (Email & collaboration → Review → Quarantine) and message trace in the Exchange admin center, which states the exact verdict and action taken. If mail is "delivered" but missing, look there — an empty junk folder tells you nothing, because phish-scored mail skips junk and goes straight to quarantine.
In the SFI incident, both the working and the vanishing emails went through the same code path, the same sender, and the same recipient. The difference was content: the subject "New Contact Form Submission from X" is a stock phishing-lure phrase (fake form-notification credential lures are a whole genre), and EOP quarantined every message carrying it — while "New Interest Registration: X" with a near-identical HTML body sailed through. Filters score the whole message, but generic notification-ese in the subject carries outsized weight.
Sender identity: SPF, DKIM, DMARC
Three DNS records let a receiver verify that a message claiming to be from your domain actually is. They answer different questions and all three matter:
- SPF (TXT on the sending domain) lists the servers allowed to send mail from that domain. The receiver checks the connecting IP against the list. Scope: the envelope sender (Return-Path), not the From header the user sees.
- DKIM (TXT at
<selector>._domainkey.<domain>) publishes a public key; the sending server signs each message, and the receiver verifies the signature. This proves the message content and headers weren't forged or altered in transit. - DMARC (TXT at
_dmarc.<domain>) ties the two to the visible From header — a check called alignment — and tells receivers what to do on failure:p=none(observe only),p=quarantine, orp=reject.
DMARC is the one that closes the loop. Without it, a spammer can pass SPF for their own domain while displaying yours in the From header. p=none is the right starting point while you confirm all legitimate mail streams authenticate, but it's a warning sign if it lingers: it tells receivers "I don't assert anything about mail claiming to be me," which both weakens their ability to trust your legitimate mail and leaves your domain open to spoofing. streetfortress.com is still at p=none — moving to p=quarantine is the known next step.
A dedicated sending subdomain
Convention: application mail is sent from a subdomain (send.streetfortress.com), never the apex. Two reasons. Reputation isolation — receivers track reputation per domain, so a burst of poorly-received application mail can't drag down deliverability of the humans' mailboxes at the apex, and vice versa. Record ownership — the provider fully manages the subdomain's DNS without touching corporate mail. This matters practically because SPF has a hard limit of 10 DNS lookups per evaluation; stacking provider include:s onto an apex record that already includes your mailbox host is a common way to silently break SPF.
The live records for streetfortress.com show the pattern — apex mail identity and application mail identity are completely disjoint:
; Apex — corporate mail (Microsoft 365)
streetfortress.com. MX 10 streetfortress-com.mail.protection.outlook.com.
streetfortress.com. TXT "v=spf1 include:spf.protection.outlook.com -all"
_dmarc.streetfortress.com. TXT "v=DMARC1; p=none;" ; TODO: move to p=quarantine
; Sending subdomain — application mail (Resend)
send.streetfortress.com. MX 10 feedback-smtp.us-east-1.amazonses.com.
send.streetfortress.com. TXT "v=spf1 include:amazonses.com ~all"
resend._domainkey.send.streetfortress.com. TXT "p=MIGfMA0GCSqGSIb3..." ; DKIM public key, provider-issued
Note what the subdomain records reveal: Resend rides on Amazon SES infrastructure, so the SPF include and feedback MX name Amazon, not Resend. Your authentication chain extends to your provider's provider — worth knowing when reading message headers or an SPF failure report. The MX on the sending subdomain exists to receive bounce and complaint feedback, not human replies.
Address conventions: noreply@ and Reply-To
The From address is part of the trust signal. noreply@ addresses are a legacy convention with real costs: replies bounce (bad experience, and some filters treat an undeliverable From as a spam signal), and they suppress the engagement signals — replies, "not junk" clicks — that build sender reputation. Resend flags noreply@ senders with a warning in its configuration for exactly these reasons. SFI still sends from noreply@send.streetfortress.com; the flagged improvement is a deliverable address like hello@send.streetfortress.com, even if it only forwards.
The mitigation in place is a Reply-To override, set at a single choke point through which all outbound mail flows (sveltekit app, src/lib/server/email/send.ts):
export async function sendEmail(input: SendEmailInput): Promise<string | null> {
const from = env.RESEND_EMAIL_FROM || "contact@streetfortress.com";
if (!env.RESEND_API_KEY) {
// Dev degrades to a no-op so local flows work without a real key
console.warn(`[email] RESEND_API_KEY not set — skipping "${input.subject}"`);
return null;
}
const replyTo = input.replyTo || env.RESEND_EMAIL_REPLY_TO || undefined;
const { data, error } = await getResend().emails.send({
from,
to: input.to,
subject: input.subject,
html: input.html,
text: input.text, // always send a plain-text alternative — HTML-only mail scores worse
...(replyTo ? { replyTo } : {}),
});
// ...
}
One choke point means one place where sender identity, the dev no-op, and future headers (List-Unsubscribe) live. User-facing transactional mail leaves Reply-To at the default; ops notifications (contact form, interest registrations) set it to the submitter's address so a plain reply in the support inbox reaches them. Reply-To is uncontroversial to filters in the common case — in the SFI incident, quarantine hit messages regardless of whether Reply-To was internal or external, which is what isolated content as the trigger.
Things That Go Wrong
Delivered but invisible. The headline failure mode, described above: provider says delivered, inbox and junk are empty, the mail is in admin quarantine. Check quarantine and message trace before touching code. Release the quarantined messages and report them as false positives — that feeds the tenant's filter and improves subsequent delivery.
Phish-pattern content. Subjects like "New Contact Form Submission", "Invoice attached", "Action required" pattern-match lure corpora. Name the actual site and the actual person ("New Website Enquiry: Jane") instead of generic notification-ese. Mailto-link "reply" buttons and user-controlled free text raise the score further; keep templates for ops mail simple.
Testing against your own tenant. Sending to your own domain's mailboxes from an external service is the adversarial case for anti-spoofing heuristics — your own tenant is often the strictest receiver you'll encounter. Passing there is a good sign, but confirm with an external mailbox too before concluding a template is clean.
Content fixes that don't hold. Filter models shift. If content-level fixes stop working for tenant-internal notification mail, the durable fix on Microsoft 365 is a mail-flow rule setting SCL to −1 (or a Tenant Allow List entry) for the sending subdomain — safe because that mail is DKIM-signed and DMARC-aligned.
Stacked SPF includes. Adding a provider's include: to an apex record that already serves corporate mail can exceed SPF's 10-lookup limit, failing SPF for all mail from the domain. The sending-subdomain convention avoids the problem entirely.
No plain-text part. HTML-only mail is a spam signal. Always generate a text alternative, even a crude tag-stripped one.
See networking for DNS fundamentals and authentication-authorization for the broader identity-verification picture this rhymes with: SPF/DKIM/DMARC are authentication and policy for domains rather than users.
References
- RFC 7208 — Sender Policy Framework (SPF)
- RFC 6376 — DomainKeys Identified Mail (DKIM)
- RFC 7489 — Domain-based Message Authentication, Reporting, and Conformance (DMARC)
- Resend — Managed Sending Domains and DNS setup
- Microsoft — Quarantined email messages in EOP
- SFI artifacts: sfi-website PR #43 (quarantine incident and fix), PR #36 (account-lifecycle emails)