Skip to content
dmarc.quest

Your SaaS Sends Email From Five Places. Here's How That Goes Wrong.

Google Workspace, Intercom, Resend, Loops and Stripe each verify their own records. None of that proves every service sending as your domain is set up correctly. What each one puts in your DNS, and five ways the combination breaks.

If you're building a SaaS product, your domain probably sends mail from more places than you realize.

A typical stack looks like this. Google Workspace for your own inbox. Intercom for support. Resend for password resets and magic links. Loops for onboarding sequences and the changelog. Stripe, once you turn on its custom email domain, for receipts and invoices.

That's five services putting your name in the From line. Each one walks you through its own records and shows a green check when they verify. But verifying a domain in one service doesn't establish that every service sending for that domain is configured correctly. The checks don't share notes, and DMARC judges each message on its own.

Here's what each service puts in your DNS, and five ways the combination goes wrong.

Three names on every message

Every message carries three domains, and nearly everything below comes down to whether they line up. Take a receipt sent from billing@example.com:

  • The From domain, example.com: what the recipient sees. DMARC protects this one.
  • The return path (envelope sender), say bounce.example.com: where bounces go. SPF checks this name, not the From domain.
  • The DKIM signing domain, the d= in the signature, say d=example.com. DKIM checks this.

DMARC passes when SPF or DKIM passes and the domain that passed is aligned with the From domain. Under relaxed alignment, the default, "aligned" means sharing the same organizational domain. Under strict alignment it means the identical name (RFC 9989 §4.4).

What each service adds

This is a summary of the authentication records in each service's current setup guide. The actual values are generated per account and shown in each service's dashboard. Names are relative to the domain you verify with that service.

ServiceDKIMSPF / return pathAdds to your root SPF?
Google WorkspaceTXT at <selector>._domainkey (default selector google); you publish the public key directlyinclude:_spf.google.com in the root recordYes
IntercomCNAME, e.g. intercom._domainkeyA return-path CNAME at a name Intercom generatesNot when the custom return path is set up (see below)
ResendTXT at resend._domainkeyMX + TXT at send. by default (newer domains may get CNAMEs)No
LoopsRecords from the dashboardMX + SPF at envelope.<sending domain>No
StripeCNAMEsA "Mail From" CNAME (Stripe's troubleshooting example uses bounce.)No

Stripe also asks for an ownership TXT record, which isn't an authentication record and so isn't in the table.

The last column holds the most common misconception. In these configurations, only Workspace sends with your root domain as the return path, so only Workspace belongs in your root SPF record. The other four send with a return path on a name of their own, and SPF checks that name. Each SPF record "is placed in the DNS tree at the owner name it pertains to" (RFC 7208 §3), so a record at send.example.com is unrelated to the one at example.com. What decides where a service belongs is its return path, not what kind of service it is.

Intercom's own docs aren't consistent on this. Its troubleshooting guide says it "handles SPF for you by setting a custom return-path", while its connection guide still suggests include:sparkpostmail.com. Once the custom return path is in place, that include does nothing for aligned mail.

Unnecessary includes aren't free, either. SPF caps evaluation at ten DNS-querying terms (RFC 7208 §4.6.4), including the lookups nested inside each include. Evaluation runs left to right and stops at the first match (§4.6.2), so whether an over-long record actually breaks your mail depends on which path a given message takes. If an evaluation exceeds ten terms before it finds a match, the result is permerror. It's a budget better not spent on records that do nothing.

1. Strict SPF alignment can remove your fallback

Under aspf=s, SPF only aligns when the return path is the identical name as the From domain. A message from billing@example.com with a return path of bounce.example.com passes SPF but isn't aligned. For four of the five services in the table, mail from your root domain is in exactly that situation.

Google's DMARC guide explains both modes and warns that strict alignment "can result in messages from associated subdomains to be rejected or sent to spam." Stripe states the limitation flatly for its own product: it doesn't support strict SPF alignment, so your DMARC record shouldn't contain aspf=s.

That mail usually still passes DMARC on DKIM alone. But that leaves one mechanism carrying it, and if the DKIM signature fails for any reason, nothing else does. Unless you have a specific reason, leave aspf out; relaxed is the default. RFC 9989 notes that "nearly all Domain Owners have found relaxed alignment sufficient" (§4.4).

2. Two services want the same name

Return-path labels come from a short shared list: send, mail, bounce, email. Each is some service's default, or the example in someone's guide.

That matters most when one of the records is a CNAME. RFC 1034 §3.6.2: "If a CNAME RR is present at a node, no other data should be present." A CNAME can't share its name with an MX or TXT record. Some DNS hosts refuse the conflict; others accept it and serve something receivers won't handle consistently.

Both services that use CNAMEs here say so. Stripe tells you not to have other records sharing a name with its CNAMEs. Resend's Forge (launched October 2026) moves the return path to a new CNAME, leaves your existing records in place, and checks whether the name it suggests is free. The risk sits with names you choose yourself, and with records another service created a year ago that nobody remembers.

Before adding a return-path record, look at what already lives at that name.

3. Every guide includes a DMARC step

Intercom's troubleshooting guide requires DMARC of at least p=none. Stripe requires DMARC before the custom domain works. Loops provides a record during setup, and Resend walks you through adding one. Several of these guides include an example rua= reporting address.

You publish one DMARC record per name. Two records at the same _dmarc name and receivers discard both (RFC 9989 §4.10), then keep walking up the DNS tree as if that name had no record. At your root domain there's usually nothing above it, so the result is effectively no DMARC at all.

So if you already have a record that covers the From domain a service sends with, that service's DMARC step is done. Loops says as much: one record at the root can cover your subdomains. If you want reports to go to two places, list two addresses in a single record's rua=, not two records.

4. Subdomains inherit your policy, not your authentication

Every one of these guides eventually suggests moving from monitoring (p=none) to enforcement. Your root policy covers subdomains too: unless a subdomain publishes its own record, or your record sets a separate sp=, the p= value applies to them (RFC 9989 §4.7).

Authentication doesn't travel down the tree the same way. SPF is per name. DKIM can cover subdomains under relaxed alignment: a valid d=example.com signature aligns with mail from news.example.com (§4.4). But that only helps if whoever sends from news.example.com actually signs with a key under example.com.

The rule before enforcing is therefore: verify that each legitimate mail stream passes at least one aligned check. That means the services you set up this year, and also the old newsletter on news. and the CRM a contractor connected two years ago. Under p=reject, receivers can reject the ones that fail.

That's the job DMARC reports exist for. Your DNS shows what you meant to set up. The reports show who is actually sending as you, and which of those messages pass.

5. Your DKIM keys vouch for more than one name

The same relaxed alignment cuts the other way. If you let a service sign with d=example.com, its signatures align for mail From any name in your organization, not just the address you set it up for. The same holds for a service signing with a sibling or child domain: d=mail.example.com aligns with billing@example.com under relaxed DKIM alignment.

This isn't a reason to panic. These are services you chose, and they send what your account tells them to. But anyone holding a signing key anywhere under your organizational domain can produce DMARC-passing mail across all of it. Google's DMARC guide suggests considering strict alignment when subdomains are managed by another entity or send from outside your control. adkim=s does narrow it, but it also breaks the common case of a service signing subdomain mail with a root-domain key. Know the trade before you make it.

Three things that look wrong and aren't

send.send.example.com. Verify send.example.com with Resend and its default return-path label is applied beneath that, giving send.send.example.com. One send is your sending domain, the other is Resend's return path. Resend lets you pick a different label when you create a domain. Changing it later through the normal settings means re-adding the domain, though activating Forge sets up its own new return-path name on an existing domain.

Resend's 1024-bit DKIM key. RFC 8301 §3.2: signers "MUST use RSA keys of at least 1024 bits" and "SHOULD use RSA keys of at least 2048 bits." So a 1024-bit key is compliant, though below the recommendation. Resend documents that it signs with 1024-bit keys and that the length can't be changed. If a checker flags it, that's a limit of the service, not a DNS setting you can fix.

Google's "up to 10 include: tags." Google's SPF page simplifies the limit. The RFC counts every DNS-querying term evaluated, nested includes and a, mx, ptr, exists and redirect included, so a record with four includes can still exceed it.

See your own setup

Each service's checker can tell you whether its own records are in place. What none of them can show you is the combination.

Run your domain through dmarc.quest. The Names in your mail setup section shows the mail infrastructure we can find for your domain: which names have sending records, which service each belongs to, and what's wrong with them. Then point your DMARC reports at us to see which of those names are actually sending and passing, and send us a test email from your app to see the verdict a real receiver gave that message.