DEV Community

PeekLaunch
PeekLaunch

Posted on AI-assisted

Why Your SaaS Emails Land in Spam (and How to Fix SPF, DKIM and DMARC)

You ship your signup flow. You test it. The welcome email arrives... in the spam folder. Your password reset emails do the same. Users think your app is broken, and some never come back.

This is one of the most common problems in a new SaaS, and it is almost never about your email text. It is about who your email says it is from, and whether the receiving server can prove it. This guide walks through the fix in plain English.

The real reason emails go to spam

Gmail, Outlook and Yahoo ask three simple questions about every email:

  1. Is this server allowed to send for this domain? (SPF)
  2. Was this email signed by the domain, and was it changed on the way? (DKIM)
  3. What does the domain owner want me to do if the first two checks fail? (DMARC)

If you send from a free address like yourapp@gmail.com through some other tool, or from your own domain without these records, the answers are "no", "no" and "no idea". So the email lands in spam, no matter how nice the content is.

Since 2024, Gmail and Yahoo also require bulk senders to have SPF, DKIM and DMARC set up. Even if you only send a few hundred emails a day, it is smart to follow the same rules.

Step 1: Send from your own domain

Stop sending app emails from a free Gmail or Outlook address. Use your own domain, for example hello@yourapp.com or no-reply@yourapp.com.

A good pattern is to use a subdomain for sending, like send.yourapp.com or mail.yourapp.com. This keeps your main domain's reputation safe, and it means you don't have to touch the SPF record that your normal inbox or email forwarding already uses.

Most email APIs (Resend, Postmark, Amazon SES, Mailgun and others) will ask you to add your domain and then show you the exact DNS records to add.

Step 2: Add SPF

SPF is a TXT record that lists who may send email for a domain. It looks like this:

Host:  send.yourapp.com
Type:  TXT
Value: v=spf1 include:amazonses.com ~all
Enter fullscreen mode Exit fullscreen mode

A few rules people often miss:

  • Only one SPF record per host. If you already have one, merge the include: parts into it. Two SPF records on the same host make both invalid.
  • Stay under 10 DNS lookups. Every include: counts. Too many and SPF fails.
  • ~all (soft fail) is a safe start. Move to -all later if you are sure every sender is listed.

Step 3: Add DKIM

DKIM adds a digital signature to every email. Your provider holds the private key, and you publish the public key in DNS. It usually looks like:

Host:  resend._domainkey.yourapp.com
Type:  TXT
Value: p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQ...
Enter fullscreen mode Exit fullscreen mode

The host name part before ._domainkey is called the selector. Copy it exactly from your provider. Don't add your domain twice: many DNS panels add yourapp.com for you, so you would only type resend._domainkey.

Step 4: Add DMARC

DMARC ties SPF and DKIM together and tells receivers what to do when checks fail. Start gentle:

Host:  _dmarc.yourapp.com
Type:  TXT
Value: v=DMARC1; p=none; rua=mailto:dmarc@yourapp.com
Enter fullscreen mode Exit fullscreen mode
  • p=none means "just report, don't block". Good for the first few weeks.
  • rua= is where daily reports go. Use an address you can read, or a free DMARC report tool.
  • Once reports show your real emails pass, move to p=quarantine, and later p=reject.

Step 5: Check alignment

This is the part that confuses most people. DMARC passes only if the domain in your From address matches the domain that passed SPF or DKIM.

For example, if your From is hello@yourapp.com and DKIM is signed by yourapp.com, you are aligned. If DKIM is signed by someprovider.com instead, DMARC can still fail. Setting up DKIM on your own domain (Step 3) fixes this.

Step 6: Use Reply-To for real replies

Many founders want emails to come from hello@yourapp.com but replies to go to their personal inbox. You don't need a full mailbox for that. Set the Reply-To header:

await resend.emails.send({
  from: "YourApp <hello@yourapp.com>",
  replyTo: "founder@gmail.com",
  to: user.email,
  subject: "Welcome to YourApp",
  text: "Hi! Thanks for signing up. Reply to this email if you get stuck.",
});
Enter fullscreen mode Exit fullscreen mode

Most email APIs have a similar reply_to option. The From domain stays authenticated, and replies still reach you.

Step 7: Test before real users see it

Don't guess. Test:

  • Send a test to a Gmail address, open it, and click Show original. You want to see SPF: PASS, DKIM: PASS and DMARC: PASS.
  • Use a free checker like mail-tester.com to get a score and a list of problems.
  • Check your DNS with dig:
dig TXT send.yourapp.com +short
dig TXT resend._domainkey.yourapp.com +short
dig TXT _dmarc.yourapp.com +short
Enter fullscreen mode Exit fullscreen mode

DNS changes can take from a few minutes to a few hours to show up. Wait before you panic.

Content still matters a little

Once authentication passes, content is the next thing to look at:

  • Send a plain-text version along with HTML.
  • Avoid huge images with very little text.
  • Don't use link shorteners. Use links on your own domain.
  • Keep the first emails to new domains small. Warm up slowly instead of sending 5,000 emails on day one.
  • Add a clear unsubscribe link to any marketing or newsletter email.

Quick checklist

  • [ ] Emails come from my own domain, not a free address
  • [ ] Sending uses a subdomain like send.yourapp.com
  • [ ] One SPF record per host, under 10 lookups
  • [ ] DKIM record added with the exact selector from my provider
  • [ ] DMARC record added, starting with p=none
  • [ ] From domain aligns with the DKIM domain
  • [ ] Reply-To points to an inbox I actually read
  • [ ] Gmail "Show original" shows SPF, DKIM and DMARC all PASS
  • [ ] Marketing emails have an unsubscribe link

Wrapping up

Spam-folder problems feel random, but they usually come down to three DNS records and one matching domain. Fix those once, test with a real inbox, and your welcome, reset and launch emails will start arriving where users can see them.

If you are getting ready to launch and want a place to share your product with other makers, you can list it for free on PeekLaunch.

Top comments (0)