Venturehand

cold email · deliverability · DMARC · engineering

Our cold email was accepted and delivered to nobody: a DMARC fail, step by step

2026-10-29 · 8 min read

In short

Our first real cold email batch got 3 SMTP receipts, a green test suite and a "fully configured" provider badge, and reached 0 inboxes. mail-tester scored it 1.5/10. The cause was 4 findings: a wrong SMTP host that still worked, an SPF softfail, no DKIM signature at all, and DMARC p=reject with no reporting address, which turned every failure into silent deletion. An SMTP receipt is a transport receipt, not a delivery receipt.

Our first real cold email batch returned 3 SMTP receipts with real queue ids and reached 0 inboxes. A free mail-tester run scored it 1.5 out of 10. If you are asking "why are my emails going to spam", or staring at a "dmarc fail" in a message header, the short answer from our case is this: an SMTP "accepted" only means a server took the message. It says nothing about whether any receiver could authenticate it. Ours could not, for 4 separate reasons, and a strict DMARC policy turned all 4 into silent deletion with no report to anyone.

This is the full write-up: what each check said, what was actually wrong, how we found it, and where it stands today.

What "accepted" actually told us

Our outreach send path has 6 stages: draft, batch, founder approval, credit reservation, SMTP submission, receipt. Every stage reported success. The message left our system, the relay authenticated our account, took the message and returned a queue id. Our test suite, 1,729 tests at the time, was green.

None of that was false. It was just answering a different question. The tests proved our configuration loaded and reached the mail library. The receipt proved a server accepted the message. Neither can prove what a receiving mail server does with it, and that is the only part that decides whether a human ever reads your email.

We only learned the truth because we sent one test message to mail-tester before turning on real campaigns. 1.5/10 is the number that stopped us.

The 4 findings

FindingWhat we sawEffect
Wrong SMTP hostWe submitted to the account's IMAP host on port 587. It authenticated us and returned a queue id. Our mailbox provider's support later told us the correct submission host is a separate, dedicated SMTP hostA week of sends that looked successful
SPF softfailThe provider's SPF include expands to 18 IP addresses. Our message left from 199.231.165.220, which is not one of themSPF cannot pass
No DKIM signature at allThe only published selector, selector1._domainkey, was a CNAME to selector1._domainkey.outlook.com: a generic Microsoft key from 2016 whose private half our provider does not holdDKIM cannot pass
p=reject with no rua=v=DMARC1; p=reject; pct=100;Every failure becomes a deletion, and nobody sends you a report

The last row is what made this silent. DMARC with p=reject tells receivers to refuse anything that fails authentication. Without a rua= address, no aggregate report ever comes back. So the strictest possible policy was paired with zero visibility, and the sender sees nothing but successful receipts.

Note what it was not. Early on we guessed that the return-path domain was breaking alignment. That guess was wrong. The envelope-from was aligned. The SPF record simply did not cover the IP the mail was sent from.

Why the dashboard said everything was fine

3 days earlier, our mailbox provider's dashboard reported, word for word: "Domain is fully configured. MX, SPF, DKIM, DMARC records are set correctly, and mailboxes can send emails."

We did not take that on trust. We queried each record directly, and the DKIM record was already the problem: a selector that cannot validate a signature for our domain. The badge checked that records existed. It did not check that they could authenticate a message sent from our domain.

The wrong SMTP host is the same pattern. A comment in one of our migrations said "SMTP reaches the same host as IMAP on a different port". Nothing ever checked it, because the wrong host worked. A wrong setting that fails is easy to find. A wrong setting that returns success can survive for a week, and in our case it took a vendor reading our support ticket to catch it.

How we checked, in the order that worked

These are the steps we took. You can repeat them on your own sending domain before your first campaign.

  1. Send 1 message to a mail-tester address. It is free and it scores the message as a receiver sees it. Do this before any real send, not after a campaign fails.
  2. Read the sending IP out of the message headers and compare it with every IP your SPF record authorises, including what each include: expands to. Ours expanded to 18 addresses and the sender was not one of them.
  3. Look up the DKIM selector your provider gave you and see where it points. A CNAME to a key on someone else's domain, in our case a 2016 Microsoft key, cannot sign for yours.
  4. Read your DMARC record for p= and rua=. p=reject with no rua= means failures disappear and you will never get a report about them.
  5. Confirm the SMTP host from the provider, in writing. Do not derive it from the IMAP host or from your own domain name. Our old fallback, mail. plus our domain, resolved to proxy addresses that cannot speak SMTP at all.
  6. Make the first real message's Authentication-Results header a release gate. We added this as a gate in our send plan: no live sending until that header shows a pass.

The fix we chose: sign the mail ourselves

DMARC needs SPF or DKIM to pass with alignment, not both. That decided the fix.

The SPF problem was the provider's to solve, and their API has 25 routes, none of which writes a DNS record. We could not repair their IP pool on any schedule we control. Signing, though, is ours. Our mail library signs each message with a key we generate before the relay ever sees it, and the signing domain d= equals the From: domain by construction. So DMARC can pass on the DKIM side, and the SPF softfail stops mattering.

What shipped:

  • A DKIM module that reads a selector and a private key from the environment and accepts the key in the 3 shapes deployment dashboards hand back (an intact PEM, \n written as 2 literal characters, or base64). A key that is present but unreadable logs loudly, because otherwise mail keeps flowing and the only evidence is a DMARC failure at a receiver that never reports back.
  • One command, npm run outreach:dkim, that generates the keypair, gets the TXT record published, waits for DNS, confirms the published key matches the one we hold, and renders a message to check it comes out signed.
  • A required smtp_host on every mailbox credential. It is nullable, not defaulted: null means "we do not know how to submit for this mailbox", which is a mailbox that cannot send and a human who needs to look. The transport now throws instead of guessing a host.
  • Tests that assert the host explicitly, instead of trusting that a send succeeded.
  • A List-Unsubscribe header on every message. It is a mailto: link, not one-click, because one-click unsubscribe (RFC 8058) needs an endpoint we have not built, and advertising one would be a lie in a header. We left this header out of the signed set, because it is the newest and least standard header we send, and a relay that rewrites a signed header voids the signature.

Where it stands today

Honestly: the signing work is complete and dormant. The key generates and the message renders signed, but nothing reaches a receiver until 1 TXT record is published, and the DNS zone sits in our provider's account, not ours. Live sending stays off until a signed message passes. No signed message has been delivered yet, so this post does not claim the fix works. It claims the old setup could not.

There is also a named open risk. Our domain has click tracking turned on at the provider. Click tracking rewrites links in the body, and any change to the body voids the DKIM body hash. If a signed send still fails DKIM, tracking comes off.

The bigger lesson was about ownership. We had delegated the domain's nameservers to the provider at setup, so only they can publish records. The domain is ours, but the zone is not. If you are setting up cold email for the first time: keep registration and DNS hosting with you, and give the provider records, not the zone.

What to take from this

  • An SMTP receipt is a transport receipt. It is not a delivery receipt.
  • A provider's "fully configured" badge checks that records exist, not that they authenticate your mail.
  • p=reject with no rua= is the worst combination to debug: strict and silent.
  • Test with 1 message before your domain's warm-up, because unauthenticated mail damages a new domain's reputation while you are still trying to build it.

Cold email is also not the first thing to fix. In Venturehand, John's order is Customers, Competitors, Channels, Posts, Demo video, Cold outreach, CRM, and he only sends on your approval. If you are not sure yet who to email, start with the free customer map, and use the channel picker to check that cold email is the right channel for you at all. More engineering stories like this one are on the blog.

Sources

Questions

Why are my emails going to spam when my SMTP server says they were sent?

An SMTP 'accepted' only means a server took the message. Receivers then check SPF, DKIM and DMARC. In our case all 3 receipts said accepted while SPF softfailed and DKIM was missing, so nothing reached an inbox.

What does a DMARC fail mean if my SPF record looks set up?

DMARC needs SPF or DKIM to pass with alignment to your From domain. Our SPF record existed, but it did not cover the IP the message was actually sent from, and there was no DKIM signature, so DMARC had nothing to pass on.

Can I pass DMARC without fixing my provider's SPF?

Yes, if DKIM passes with alignment. DMARC needs SPF or DKIM, not both. We sign each message ourselves with a key on our own domain, so the d= domain equals the From domain. It only takes effect once the DKIM TXT record is published.

Why is DMARC p=reject with no rua address risky for a new sending domain?

p=reject tells receivers to refuse any message that fails authentication, and without rua= no aggregate report comes back. Failures turn into silent deletion, and the sender sees only successful SMTP receipts.

More writing