---
title: "Email deliverability - SPF, DKIM and DMARC for transactional email"
description: "Why a successfully sent email lands in spam, and how to set up SPF, DKIM and DMARC so your Shopify Flow transactional email reaches the inbox."
canonical: "https://crm-tool.k8s-gcp-dev.eu.codecreationlabs.cloud/h/flow-transactional-email/email-deliverability"
---

# Email deliverability

**History says Success but the email is not in the inbox.** That combination is almost always deliverability, and it is worth understanding who controls what.

## Who is responsible for what

Your email does not go out through us. It goes out through **your** mailbox - your Microsoft 365 tenant, your Google Workspace account, or your SMTP provider.

| Stage | Who controls it | What "Success" in History means |
| --- | --- | --- |
| Rendering the email | This app | The layout rendered and the variables resolved |
| Handing it to your provider | This app | **Your provider accepted the message.** This is what Success means |
| Delivering to the recipient | Your email provider | Not visible to us |
| Inbox or spam folder | The *receiving* server | Not visible to us |

A **Success** row means your provider took the message. Everything after that is between your provider and the recipient's, which is why a green row and an empty inbox are not a contradiction.

That also means deliverability is mostly in your hands - and that is good news, because it is fixable.

## The three DNS records

If you send from `orders@yourstore.com`, the receiving server asks three questions. Missing answers are the most common reason transactional mail lands in spam.

### SPF - is this server allowed to send for this domain?

A TXT record on your domain listing who may send on your behalf:

```
v=spf1 include:_spf.google.com ~all
```

Use the include your provider documents - `include:_spf.google.com` for Google Workspace, `include:spf.protection.outlook.com` for Microsoft 365, or whatever your SMTP provider specifies.

> [!WARNING]
> You may only have **one** SPF record per domain. If you already have one, add the new `include:` to it rather than creating a second record - two SPF records is itself a failure.

### DKIM - was the message tampered with?

A cryptographic signature proving the message really came from your domain and arrived unmodified. Your provider gives you the record to publish; both Google and Microsoft have a one-click setup in their admin console.

### DMARC - what should happen if the checks fail?

A TXT record at `_dmarc.yourdomain.com`:

```
v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com
```

Start with `p=none`, which monitors without affecting delivery. Once your reports are clean, tighten to `p=quarantine` and eventually `p=reject`.

DMARC has moved from optional to expected. Gmail and Yahoo now require it from bulk senders, and its absence increasingly counts against low-volume senders too.

### Checking what you have

Any DNS lookup tool works, or from a terminal:

```
dig +short TXT yourdomain.com
dig +short TXT _dmarc.yourdomain.com
```

You are looking for a line starting `v=spf1` on the first, and `v=DMARC1` on the second.

## Beyond DNS

**Send from a domain you own.** A free consumer address as the sender is heavily penalised. `orders@yourstore.com` beats `yourstore@gmail.com` every time.

**Match the From domain to the authenticated one.** Sending as `orders@yourstore.com` through a mailbox authenticated for a different domain fails alignment even when SPF and DKIM technically pass.

**Keep transactional email transactional.** Order confirmations, shipping updates and account notices are expected. Marketing blasts from a transactional setup damage the reputation your order emails depend on.

**Include real identifying details.** A postal address and a clear sender name in your footer preset. Absent contact detail is a spam signal, and in many jurisdictions a legal requirement.

**Warm up gradually.** A brand-new domain suddenly sending hundreds of emails looks exactly like a compromised account. Volume should grow over days.

**Watch your images-to-text ratio.** An email that is one big image with almost no text is a classic spam pattern.

## If mail is still not arriving

Work through it in this order - each step rules out a layer:

1. **Check History.** If the row says Failed, this is not deliverability - open it for the provider's error.
2. **Send a test email** from **Email Senders** to an address at a different provider than the failing one, so you are not fooled by a single receiver's filtering.
3. **Check the spam folder** at the destination. If it is there, the message was delivered - it is a reputation problem, so work through the DNS records above.
4. **Check your provider's own logs.** Microsoft 365 and Google Workspace both keep sent-mail and delivery logs showing what happened after they accepted it.
5. **Check the recipient side.** Corporate mail servers routinely quarantine mail from unfamiliar domains without informing the sender.

> [!NOTE]
> If the email is arriving but looks wrong - blanks where a name or order number should be - that is not deliverability. See [Passing data from Shopify Flow](https://crm-tool.k8s-gcp-dev.eu.codecreationlabs.cloud/h/flow-transactional-email/passing-data-from-shopify-flow.md).

## Sending IP allowlisting

If you use an SMTP relay that restricts senders by IP, the app shows its outbound address on the SMTP server page so you can allowlist it. This applies only to SMTP - Microsoft 365 and Google connections send through the provider's own infrastructure.

## Related

- [Email senders overview](https://crm-tool.k8s-gcp-dev.eu.codecreationlabs.cloud/h/flow-transactional-email/email-senders-overview.md) - choosing how your email goes out.
- [Subject line and preview text](https://crm-tool.k8s-gcp-dev.eu.codecreationlabs.cloud/h/flow-transactional-email/subject-line-and-preview-text.md) - what recipients see before opening.
- [History and troubleshooting](https://crm-tool.k8s-gcp-dev.eu.codecreationlabs.cloud/h/flow-transactional-email/history-and-troubleshooting.md) - reading a Failed row.
