# Why do my app's emails land in spam (or never arrive)?

## Context for the AI tool

You are checking why emails from this app land in spam or don't arrive, and fixing the sending setup.

- Do not change any DNS record until you have listed every existing record for the domain,
  reported your findings and I have confirmed.
- Never replace or delete an existing TXT record on the root domain. Root TXT records are shared:
  SPF, Google and Microsoft site verification and other services all live there. Add to them or
  edit the one SPF value; never overwrite the set.
- Report findings as a table: record (name and type), current value, problem, proposed value.
- I make the DNS changes myself unless I say otherwise. Give me the exact name, type and value.
- Do not print API keys or SMTP passwords. Refer to them by the environment variable name.

## 1. Find out who sends what

**What to look for:** every place the app sends email from, and from which address. Typical
senders: the auth provider (Supabase Auth, Clerk, Firebase), a transactional provider (Resend,
Postmark, SendGrid, Amazon SES) and the domain's normal mailbox (Google Workspace, Microsoft 365).

```bash
grep -rniE "from:|sender|smtp|resend|postmark|sendgrid|nodemailer|ses" --include=*.{ts,js,tsx,svelte,py,toml,env.example} . | grep -v node_modules
```

**How to fix:** nothing yet. List each sender with its from-address and the provider behind it.

**How to verify:** you have a table of senders. Every from-address uses a domain you own (not a
gmail.com address, not the provider's test domain).

## 2. Don't send production mail through test SMTP

**What to look for:** auth emails (sign-up confirmation, magic link, password reset) still going
through the auth provider's built-in mail service. Supabase's default email service is meant for
testing: it is heavily rate-limited and only delivers to members of your project team, so real
users never get the email.

**How to fix:** configure custom SMTP in the auth provider (for Supabase: Authentication →
Emails → SMTP settings) using your transactional provider's SMTP details and a from-address on
your own domain.

**How to verify:** sign up with an address that is not on your team. The confirmation email
arrives within a minute.

## 3. SPF: one record, with every sender in it

**What to look for:** the SPF record on the domain in the from-address (and on the provider's
sending subdomain, if it uses one).

```bash
dig +short TXT example.com
dig +short TXT send.example.com
```

Problems we see: no SPF at all, two separate `v=spf1` records (that makes SPF fail completely),
a sender missing from the list, or so many `include:` entries that SPF goes over its limit of 10
DNS lookups.

**How to fix:** keep exactly one `v=spf1` record per name, with every sender's `include:` in it,
ending in `~all`. Add or edit only that value; leave every other TXT record on the name as it is.
Many providers (Resend, for example) send from a subdomain such as `send.example.com` with its
own SPF and MX records: add those exactly as the provider shows them.

**How to verify:** the `dig` output shows one `v=spf1` value per name, and all the other TXT
records you listed before (site verification and so on) are still there.

## 4. DKIM: the provider's key is published

**What to look for:** the DKIM record the provider asked you to add, at its selector (for
Resend `resend._domainkey`, for Google Workspace `google._domainkey`).

```bash
dig +short TXT resend._domainkey.example.com
```

**How to fix:** copy the record from the provider's domain settings exactly: name, type (TXT or
CNAME) and value. Some DNS panels add the domain to the name automatically, so
`resend._domainkey.example.com.example.com` is a common mistake.

**How to verify:** the provider's dashboard shows the domain as verified, and `dig` returns the
key.

## 5. DMARC: start with monitoring

**What to look for:** a TXT record at `_dmarc.example.com`. Google and Yahoo require DMARC for
bulk senders, and mail without it is more likely to land in spam.

```bash
dig +short TXT _dmarc.example.com
```

**How to fix:** if there is none, start with a monitoring policy that blocks nothing:

```
_dmarc.example.com  TXT  "v=DMARC1; p=none; rua=mailto:dmarc@example.com"
```

Read the reports for a few weeks. Move to `p=quarantine` only when every legitimate sender
passes.

**How to verify:** `dig` returns exactly one `v=DMARC1` record.

## 6. Test with a real inbox

**What to look for:** the result as a mailbox provider sees it.

**How to fix:** send each type of email (sign-up, reset, order) to a Gmail address and an
Outlook address. In Gmail, open the message, choose *Show original* and read the SPF, DKIM and
DMARC lines.

**How to verify:** all three show `PASS`, the messages land in the inbox, and the from-address
and reply-to are on your own domain.

---

Still stuck? WDDW fixes it. Book a free 15-minute call:
https://www.wedodevwork.com/en/contact-us?utm_source=fixes&utm_medium=md&utm_campaign=email-deliverability-check

Did this help? An honest review helps us a lot: https://g.page/r/CXmlHMBM4uxyEBM/review
More free fixes: https://www.wedodevwork.com/en/fixes · Star the repo: https://github.com/WEDODEVWORK/fixes
