Why Emails From Your AI-Built App Go to Spam
If mail from your AI-built app lands in spam, the send is working and the receiver does not trust it. A header-first diagnostic order for SPF, DKIM, DMARC and reputation.
Why Emails From Your AI-Built App Go to Spam
Password resets landing in spam is almost never a code problem, which is why asking an AI to "fix the email sending" rarely helps. The send is working. The receiving mail server is choosing not to trust it, and it makes that choice using three DNS records and a reputation history your domain does not have yet. Here is the order to check things in, fastest first.
Start by reading the headers, not the code
Send yourself a test message at a Gmail address, open it, and use "Show original". You want three lines:
spf=pass (google.com: domain of bounce@yourapp.com designates 1.2.3.4 as permitted sender)
dkim=pass header.i=@yourapp.com header.s=s1
dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=yourapp.comAny of those reading fail or none tells you exactly which of the next three sections to read. If all three say pass and mail still lands in spam, skip to the reputation section, because your DNS is fine and the problem is behavioural.
SPF: does this server have permission to send as you
SPF is a TXT record on your domain listing who may send mail for it. It breaks in a specific way for AI-built apps: the app gets wired to a sending provider, the provider's include is added, and then a second provider is added later for marketing mail and someone publishes a second SPF record. Two SPF records is a permanent fail, not a merge. There must be exactly one, with both includes inside it.
v=spf1 include:_spf.provider-one.com include:_spf.provider-two.com ~allThe other common break is the ten lookup limit. Each include costs a lookup, and nested includes count. Past ten, SPF returns permerror and receivers treat it as a fail.
DKIM: is the message signed and unmodified
DKIM publishes a public key at a selector on your domain and signs each message with the private half. The failure here is usually that the provider generated keys and printed the CNAME records, and whoever set up the app pasted them into the wrong zone, or pasted them at the apex instead of the selector subdomain. Verify by looking up the selector directly rather than trusting the provider dashboard's green tick, which often only checks that the record exists rather than that it resolves publicly.
dig +short s1._domainkey.yourapp.com CNAME
dig +short s1._domainkey.yourapp.com TXTDMARC: the record almost nobody adds
This is the one most AI-built apps are missing outright, and since 2024 the large mailbox providers have expected it for bulk senders. Start in monitor mode so nothing you send gets rejected while you are still learning what your own domain sends:
_dmarc.yourapp.com TXT "v=DMARC1; p=none; rua=mailto:dmarc@yourapp.com"Leave it on p=none for a couple of weeks and actually read the aggregate reports. They will show you sources sending as your domain that you forgot about, which is usually a billing provider or a help desk tool. Only tighten to quarantine once those are all passing.
Reputation: the part DNS cannot fix
A domain that has never sent mail has no reputation, and a domain that sends its first 5,000 messages in one afternoon builds a bad one. Three habits matter more than any record:
Separate your transactional and marketing sending onto different subdomains, so a bad campaign cannot poison password resets.
Never send to an address that has bounced hard. Repeatedly hitting dead addresses is one of the strongest negative signals there is.
Put a real unsubscribe header on anything that is not strictly transactional, and honour it immediately.
Sending from a subdomain such as mail.yourapp.com rather than the apex is also worth doing early, because it isolates the reputation of your app's mail from whatever else the domain is used for. If you have not moved off a platform subdomain yet, do that first: moving the app onto your own domain has to happen before any of this is meaningful.
The order to work through it
Symptom in headers | Most likely cause | Fix |
|---|---|---|
spf=fail | Two SPF records, or the provider's include missing | Merge into one record with both includes |
spf=permerror | More than ten DNS lookups | Flatten or drop unused includes |
dkim=fail or absent | Selector records in the wrong zone | Look up the selector with dig, not the dashboard |
dmarc=fail, SPF and DKIM pass | Alignment: the From domain differs from the signing domain | Match the envelope and header From domains |
All three pass, still spam | Reputation or content | Warm up slowly, split subdomains, clean the list |
Frequently asked questions
Why do my emails go to spam only on Gmail?
Gmail weighs domain reputation and engagement more heavily than most receivers, so a new domain with no history is filtered there first. It is usually the earliest warning rather than a Gmail-specific bug.
Do I need DMARC if SPF and DKIM already pass?
Yes, for anything approaching bulk volume. The large providers have expected a DMARC record from bulk senders since 2024, and monitor mode costs you nothing operationally.
Will changing DNS fix it immediately?
The records propagate in minutes to hours, but reputation does not reset. If you have already sent a burst of mail that got marked as spam, expect days of consistent good sending before placement improves.
Should transactional email go from a subdomain?
Yes. It isolates password resets and receipts from marketing sending, so one bad campaign cannot stop people logging in.
How do I test all this before launch?
Send to addresses at several providers and read the headers on each, rather than checking one inbox. It fits naturally into the pre-launch testing pass, and if you have not set sending up at all yet, start with wiring up email sending in the first place. The wider build context is in the full guide to building an app with AI.
How did this land?
About the author

Developer Advocate
Steve builds something with Swarmz every week and writes up what worked, what broke, and what he'd do differently. Tutorials and hands-on guides are his lane.


