You spent weeks on your onboarding flow. A new user signs up, triggers the welcome email, and it lands in Gmail’s spam folder. They never confirm their email. They churn before they start.
It’s a fixable setup problem you can solve without a technical background.
The short answer
Gmail, Outlook, and Apple Mail run every incoming email through three checks before deciding whether it’s legitimate:
- SPF (Sender Policy Framework): is the server that sent this email actually allowed to send on behalf of your domain?
- DKIM (DomainKeys Identified Mail): does the email carry a digital signature proving nobody tampered with it in transit?
- DMARC (Domain-based Message Authentication, Reporting & Conformance): the policy that tells a mail server what to do if SPF or DKIM fail. Let it through, quarantine it, or reject it.
If any of the three is missing or broken, mail filters treat your messages as suspicious, even though you’re not sending spam. Most early-stage products have this partially set up. “Partially” is enough to land you in the spam folder.
What’s actually happening
When you send through Postmark, Resend, Amazon SES, or any transactional email service, that service’s servers send email on behalf of your domain. The receiving mail server checks:
- Is this sender authorized to send for your domain? (SPF check)
- Is there a valid signature on this message? (DKIM check)
- What should we do if those checks fail? (DMARC policy)
If your provider isn’t listed in your SPF record, or DKIM isn’t set up, check 1 or 2 fails. If DMARC is missing or set to p=none (no rejection instruction), the receiving server has no guidance from you, and its own spam filter makes the call. Often unfavorably.
How to find the actual problem
Send yourself a test email and look at what the receiving server decided. In Gmail: open the message, click the three dots, choose “Show original.” Find the Authentication-Results line near the top:
Authentication-Results: mx.google.com;
dkim=pass header.i=@example.com ...
spf=pass (google.com: domain of you@example.com designates 203.0.113.10 as permitted sender)
dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=example.com
If any line says fail, softfail or neutral, that’s your problem. Common patterns:
spf=softfail,spf=failorspf=neutral: your provider’s sending server isn’t listed in your SPF record (which one you see depends on whether your record ends in~all,-allor?all)dkim=fail: DKIM isn’t turned on in your provider’s dashboard, or the DNS record has a typodmarc=fail: SPF and DKIM don’t match the domain in your From: address closely enough to count (see SPF passes, DMARC fails: the alignment trap)
The fix
What you need: access to wherever you manage your domain’s DNS (Cloudflare, Namecheap, GoDaddy, or wherever you bought the domain) and your transactional email provider’s dashboard.
For SPF: In your DNS provider, find the TXT record at your root domain (just example.com, no subdomain). It should include your transactional email provider. Example for Postmark:
v=spf1 include:spf.mtasv.net ~all
For Resend, Amazon SES, or others, your provider’s own setup docs give you the exact include: value to add. If you use more than one provider, they all go on the same line.
For DKIM: Every transactional provider has a DKIM section in its dashboard. You click to generate a key, it gives you a DNS record to paste (usually at a subdomain like pm._domainkey.example.com), you paste it into your DNS provider, and click verify. This is the step most founders skip because nothing forces you to do it: mail still sends without it, it just gets flagged.
For DMARC: add this TXT record at _dmarc.example.com to start monitoring:
v=DMARC1; p=none; rua=mailto:dmarc@example.com
p=none is the safest starting point. (The standard, RFC 9989 §4.10.1, reads a record with a reporting address but no p tag as p=none; without a reporting address the record is ignored. Write p=none out so it’s obvious.) p=none asks receivers to do nothing extra yet, and rua= asks them to report back. Don’t jump straight to p=reject until you’ve confirmed every legitimate sender passes. Moving too fast can block real email you meant to send.
Why “it worked before” isn’t reassuring
Spam placement isn’t a yes/no switch. It’s a score. You might have been borderline before, and a recent change (new provider, new sending volume) pushed you over the line. Or you got lucky, until you didn’t.
Email authentication doesn’t fix every deliverability problem, but it removes the most obvious reason a filter would distrust you. Once SPF, DKIM, and DMARC are correct, you’re competing on content and sender reputation, not on whether your setup looks suspicious.
What breaks it again, later
Someone adds a new email tool, a new sending service, a new marketing platform, and forgets to add it to the SPF record. Nothing errors. No bounce, no notification. A slice of your mail just starts silently landing in spam.
The DMARC record’s rua address is built for exactly this: it collects a daily report from Gmail and Outlook listing every source that sent mail claiming to be from your domain, and whether it passed. Reading that XML by hand isn’t realistic for most people. DMARC Guardian turns it into a dashboard showing which sender broke, so you find out before your users file a support ticket. For the personal version of this story (what it looked like to fix from scratch with zero background), see my emails kept landing in spam.