Dunning emails: timing, content and deliverability
Last reviewed 2026-10-07
A dunning email has one job: get a customer who did not choose to leave to enter a new card. Most advice on this topic is unsourced folklore about subject lines. This page sticks to what is documented, plus one section on deliverability where we can speak from a mistake we made ourselves.
Start with the emails you already have
Before writing anything, check whether Stripe is already sending it. Stripe Billing has a set of customer emails that cost nothing extra, and plenty of accounts have never switched them on. They are in the dashboard under Billing settings, in the email notifications and customer management section.
| When Stripe sends it | Links to a card-update page | |
|---|---|---|
| Failed payment | After every failed payment attempt | Yes |
| Card expiring | One month before the stored default card expires | Yes |
| Upcoming renewal | A configurable number of days before renewal, for automatic collection only | Yes |
| Trial ending | Seven days before the trial ends | Yes |
| Payment confirmation needed | When a payment requires 3D Secure, with optional repeat reminders | Yes, to a confirmation page |
All of them use your branding settings, and the link can point either at Stripe's hosted customer portal or at your own subscription management page. If you only do one thing from this guide, enable the failed-payment email and the card-expiring email.
Timing: most of it is already decided
The timing debate is narrower than it looks, because the retry schedule drives it. Stripe sends a failed-payment email after each attempt, so your email cadence is your retry cadence. Change one and you change the other.
Stripe's recommended default for Smart Retries is eight attempts over two weeks, with the model choosing the exact moments. A custom schedule allows at most three retries, which means at most three emails. That is usually the wrong trade: fewer attempts and fewer reminders, in exchange for control you probably do not need.
The one piece of timing genuinely worth your attention sits before the failure. The card-expiring email goes out a month ahead, and a customer who updates their card in advance never generates a failed payment at all. It is the cheapest message in the whole sequence and the one most often left off.
Watch the expiry of the hosted recovery link. Stripe disables it when the subscription moves to cancelled, incomplete_expired or unpaid, when the current renewal period has passed, or thirty days after a trial-end email. A reminder sent after the link dies is worse than no reminder.
What a failed-payment email should contain
This part is judgement rather than documentation, so treat it as opinion. It is opinion shaped by what the decline families actually require.
- One action, one link. The customer needs to enter a new card. Everything else on the page competes with that.
- Say what failed and what happens next. A date for the next attempt, and what happens if it also fails, removes the two questions that otherwise generate support tickets.
- Do not explain the decline code. Stripe's own guidance for several hard declines is to show a generic message rather than the issuer's reason, and telling a customer their card was reported stolen is not a conversation an automated email should start.
- Do not threaten in the first message. The subscription is still active and the customer has not done anything wrong. Escalation belongs at the end of the sequence, if at all.
- Match the sender to the product. An email from a name the customer does not recognise, about a card they did not know had failed, is indistinguishable from phishing.
For the insufficient-funds family, consider whether to email at all on the first failure. The card is valid and a later retry may well succeed on its own. An email in that case asks the customer to solve a problem that was about to solve itself.
Deliverability, from a mistake we made
The best-written dunning email in the world recovers nothing from a spam folder. If you send from your own domain rather than through Stripe, you need three DNS records, and we got this wrong on our own domain in a way worth describing.
- SPF, a TXT record listing who may send on your behalf. If your email provider wants it on a subdomain, it goes on that subdomain and not on the root.
- DKIM, a TXT record holding a public key your provider signs messages with. It is long, and it is the one people most often fail to paste correctly.
- DMARC, a TXT record on _dmarc telling receivers what to do when the first two fail. Start at p=none and watch before tightening.
Our mistake: while adding the DKIM record, the existing SPF record on the sending subdomain was overwritten rather than joined. The provider's dashboard still showed SPF as verified, because it had cached its last successful check, while the record had actually stopped being published. Nothing broke loudly. Sending simply would have degraded.
Two lessons from that. A provider's green tick is a record of the last check, not a live reading — verify from DNS itself. And a root-domain SPF record and a sending-subdomain SPF record are different records on different names, which coexist happily; what is never valid is two SPF records on the same name.
Testing without spamming your customers
Stripe does not send customer emails automatically from a sandbox, which is usually what you want and occasionally confusing. To test, the customer's email address has to belong to your verified email domain or to an active member of your team. Under those conditions, failed-payment, upcoming-invoice, trial-ending and card-expiring emails do go out in test mode.
Once live, the Customers page in the dashboard keeps email logs for the last sixty days, covering failed attempts, finalised invoices, receipts, 3D Secure prompts, expiring cards and cancellations. The logs update daily and exclude the current day, so do not panic at an empty result an hour after sending.
Questions people ask
- How many dunning emails should I send?
- With Stripe's defaults, one per failed attempt, which means up to eight over two weeks on the recommended Smart Retries setting. A custom retry schedule caps at three attempts and therefore three emails, which is usually a downgrade rather than a refinement.
- Does Stripe send failed payment emails automatically?
- Only if you enable them. The setting is in the dashboard under revenue recovery emails, and when it is on Stripe emails the customer after every failed payment with a link to update their payment method.
- Should dunning emails come from Stripe or from my own domain?
- Stripe's are branded with your settings and work immediately, which makes them the right starting point. Sending from your own domain gives you control of tone and sequence, but you take on SPF, DKIM and DMARC, and a misconfiguration there costs you more than any wording gain.
- Why are my dunning emails going to spam?
- Almost always authentication. Check SPF, DKIM and DMARC by querying DNS directly rather than trusting your provider's dashboard, which may be showing the result of an earlier check. Verify that each record is on the exact name your provider asked for.
- When should I email a customer about an expiring card?
- Stripe does it a month before expiry for the default card, if you enable it. That is the cheapest recovery in the whole sequence, because it prevents the failure rather than chasing it.
Sources
- Stripe Docs — Automate customer emails — checked 7 October 2026
- Stripe Docs — Automate failed payment retries (Smart Retries) — checked 7 October 2026
- Stripe Docs — Decline codes — checked 7 October 2026