How to Set Up Email for a New SaaS (The Right Way)
Set up three things before you send your first production email: split your domains by purpose, configure SPF and DKIM through your ESP, and publish a DMARC record pointing at a monitoring tool. Everything else in this guide builds on those three steps. Skip them and no amount of warmup or bounce handling will save you when deliverability breaks.
This guide covers the full setup: which domains to use for which sending purposes, the MX and authentication records you need, how to warm up a brand-new sending domain, how to handle bounces and complaints, and the monitoring you should have in place before your first paying customer signs up.
Step 1: Decide your domain strategy before you send anything
The mistake most founders make: using their root domain (yourapp.com) for everything. Product emails, marketing, cold outreach. When anything goes wrong on any channel, it affects all of them.
The right setup splits domains by purpose:
yourapp.com: main domain, protect it, use for direct sends only (support replies, founder outreach), not mass sendingmail.yourapp.comorapp.yourapp.com: transactional sending subdomain (password resets, receipts, notifications)- Optional:
hello.yourapp.comornews.yourapp.comfor marketing/newsletter volume
This isn't premature optimization. Fixing a mixed-use domain after 10,000 users are receiving transactional email is a multi-week project. You'll be digging through SendGrid logs at 2 AM wondering why half your password resets landed in spam. Separate the sending paths now.
Why subdomains protect you: reputation isolation
Receiving servers build a reputation score for the exact domain that authenticates your mail. That reputation does not split cleanly between channels if everything sends from the same name. Send a clumsy marketing blast that triggers a wave of spam complaints, and the reputation hit lands on the same domain your password resets and payment receipts go out on. Now a customer can't reset their password because your newsletter annoyed people.
Subdomains give you blast doors. A reputation problem on news.yourapp.com does not automatically drag down mail.yourapp.com, because receivers track them as distinct sending identities. Your highest-stakes mail (security alerts, receipts, password resets) lives on a subdomain that only ever sends mail people asked for, so it keeps a clean reputation no matter what your marketing does.
There is a nuance worth knowing: a brand-new subdomain inherits some trust from an established root domain, which is why a subdomain off a domain you've owned for years starts out better than a freshly registered one. But once you start sending volume, each subdomain earns its own standing. Isolation works.
How DMARC alignment works across subdomains
DMARC is published at the organizational domain (yourapp.com) and, by default, covers every subdomain under it. Two tags control how that inheritance behaves:
sp=sets the policy for subdomains specifically. If you publishp=rejectbutsp=noneonyourapp.com, the root is enforced while subdomains stay in monitoring mode. This is useful while you're still ramping a new sending subdomain and don't want a misconfiguration there to bounce mail.np=sets the policy for non-existent subdomains : names with no DNS records at all. Settingnp=rejectblocks attackers from spoofing made-up subdomains likebilling.yourapp.comthat you never created, without affecting the subdomains you actually send from.
There's also the question of alignment mode. DMARC alignment can be relaxed (the default) or strict. In relaxed mode, mail.yourapp.com is considered aligned with a from: header of you@yourapp.com because they share the same organizational domain. In strict mode, the domains must match exactly. Relaxed is almost always what you want for a SaaS that sends from subdomains : it lets you keep a clean from: address on your root domain while authenticating from a dedicated sending subdomain. Don't reach for strict alignment unless you have a specific reason; it's a common way to accidentally break your own mail.
Step 2: Configure MX records (yes, even for a sending-only domain)
MX (Mail Exchange) records tell the world which servers receive mail for a domain. It's tempting to skip them on a domain you only send from : but that's a mistake that causes silent failures.
Here's why a sending-only or transactional domain still needs MX configured correctly:
- Bounces and replies need somewhere to land. When a transactional email bounces, the receiving server sends a bounce notification back to your envelope sender (the
Return-Path). If that domain has no MX record, the bounce can't be delivered, and you lose the signal that tells you an address is dead. Many ESPs handle this by routing theReturn-Paththrough their own domain, but if you're using a custom return path on your subdomain, it needs an MX record pointing at your ESP's bounce-handling servers. - Some receivers reject mail from domains with no MX record at all. A sending domain with zero MX records looks suspicious : legitimate domains almost always accept mail. A few spam filters treat "can send but can't receive" as a weak negative signal.
- Replies to your transactional mail have to go somewhere. If a customer hits reply on a receipt sent from
mail.yourapp.comand that subdomain has no MX record, their reply vanishes. Either point the MX at an inbox you monitor, or use aReply-Toheader that lands on a domain you do receive mail on.
The relationship to your inbound provider matters here. Whoever handles your incoming mail (Google Workspace, Fastmail, your ESP's inbound parsing, or a service like DMARCdrift for report ingestion) is what your MX records point to. Get this wrong and you have two failure modes: mail you send can't be replied to, and bounce notifications disappear. Set the MX records your ESP and inbox provider specify, then confirm they resolve before you send a single production email. A dig MX mail.yourapp.com (or any DNS lookup tool) should return the host you expect.
One practical rule: keep the MX records for your root domain pointed at whatever handles your real inbox (support@, hello@), and only add MX records to sending subdomains if your ESP asks for them for bounce processing. Don't blindly copy your root MX onto every subdomain.
Step 3: Choose your ESP and configure sending authentication
Transactional ESP options for indie builders:
- Resend: excellent DX, React Email integration, generous free tier. Good default.
- Postmark: highest deliverability reputation, stricter acceptable use policy. Good for high-importance transactional (payments, security alerts).
- AWS SES: cheapest at scale ($0.10/1000), more setup overhead and shared IP pool at the low end. Worth it at volume.
Whichever you pick, follow their DKIM setup guide completely. DKIM authenticates your email to receiving servers. Also add your ESP's sending IP ranges to your SPF record.
SPF is the first authentication layer. It says: "these are the IP addresses allowed to send from this domain." When a receiving server sees an email claiming to be from mail.yourapp.com, it looks up the SPF record and checks whether the incoming server's IP is on the whitelist. If it's not, the email fails SPF. If multiple servers can send from your domain (your ESP, plus a backup, plus a scheduled job), they all need to be in that SPF record.
DKIM is the second layer. Your ESP signs every email with a cryptographic key. Receiving servers verify the signature using the DKIM public key stored in your DNS. Unlike SPF, DKIM travels with the email even if it's forwarded, so it's more reliable. Use a 2048-bit DKIM key if your provider supports it; Gmail requires at least 1024 bits for delivery to personal accounts and recommends 2048.
Start with SPF and DKIM from your ESP. Verify both are live with the SPF checker. This is non-optional if you care about deliverability : Gmail and Yahoo require at least one (and both, plus DMARC, for bulk senders) to accept your mail at all.
Step 4: Publish a DMARC record
This takes 5 minutes and is the step most indie builders skip.
Add this TXT record to your DNS:
v=DMARC1; p=none; rua=mailto:[your-ingestion-address]
p=none means: collect reports, don't reject anything yet. You're in monitoring mode. The rua= address is where aggregate reports go. Receiving servers send these automatically, in bulk, once per day. One email per sending source, per domain, per day. For a new SaaS, expect 5-50 report emails depending on how many users you have and where they're located.
Raw XML is unreadable. You need a tool to process these reports. Point your rua= address at DMARCdrift (free for one domain) or any DMARC monitoring tool. The tool ingests the reports, parses them, and surfaces what actually matters: who's sending from your domain, whether they're passing authentication, and where the failures are.
Verify your DMARC record is live with the DMARC record checker. If you want to understand what you're monitoring, see what's in a DMARC aggregate report.
Step 5: Verify alignment before you send volume
Once you've sent test emails and your ESP is generating reports, check that your main senders are showing as passing alignment. Use the email authentication checker or your monitoring tool's dashboard.
Alignment means the from: domain on your email matches the domain authenticated via DKIM or SPF. If your ESP is sending from mail.yourapp.com with DKIM for mail.yourapp.com, and your from: header says you@yourapp.com, that's a misalignment. Gmail, Microsoft, and Yahoo now penalize misaligned mail. Fix it before it becomes a deliverability crater at volume.
The fix is usually simple: either have your ESP authenticate from the same domain you're claiming in the from: header, or update the from: header to match the authenticated domain. Your ESP's docs will tell you how. Because DMARC defaults to relaxed alignment, sending from a subdomain while keeping a root-domain from: address is fine : the two share the same organizational domain and count as aligned.
Step 6: Warm up a new sending domain (and decide shared vs dedicated IP)
A brand-new sending domain has no reputation. Receiving servers have never seen mail from it, so they're cautious : send 5,000 emails on day one from a name that didn't exist last week and a chunk of them will land in spam or get throttled, regardless of perfect SPF, DKIM, and DMARC. Authentication proves who you are. Warmup proves you're a good sender. They're different problems.
Warmup means ramping your volume gradually so receivers can build a positive reputation from real engagement (opens, replies, low complaints) before you hit full volume. A rough cadence for a new transactional domain:
- Days 1-3: a few dozen to a couple hundred emails a day, ideally to your most engaged recipients (your own team, beta users, people who will actually open them).
- First two weeks: roughly double volume every few days as long as complaint and bounce rates stay low. Back off if they climb.
- By week 3-4: you can usually reach a few thousand a day if engagement has held up.
For most new SaaS apps this happens naturally : you don't have 50,000 users on launch day, so your volume ramps as you grow and the domain warms organically. The danger is migrating an existing large list onto a fresh domain and blasting it all at once. Don't.
Shared vs dedicated IP: this is the trade-off most new founders get wrong.
- A shared IP pool is managed by your ESP and used by many senders. Its reputation is already established and warm. Your small volume blends into a large, healthy stream. The downside is you're exposed to other senders' behavior : but reputable ESPs (Resend, Postmark) police their pools aggressively, so this is rarely a real problem.
- A dedicated IP is yours alone. You control its reputation entirely, which is great at scale. But a cold dedicated IP has zero reputation and must be warmed slowly, and dedicated IPs generally need consistent volume (often cited as roughly 50,000+ messages a month) to stay warm. Below that threshold, a dedicated IP can actually hurt you : sporadic sending from a single IP looks more suspicious than blending into a shared pool.
For almost every new SaaS, start on a shared IP. You don't have the volume to justify or sustain a dedicated one. Move to dedicated only when you're consistently sending tens of thousands of messages a month and want full control. Until then, a dedicated IP is a liability, not an upgrade.
Step 7: Handle bounces and complaints (or your reputation erodes quietly)
Sending is half the job. What you do with the feedback is what keeps you deliverable long-term. Two signals matter most: bounces and complaints.
Hard vs soft bounces
A hard bounce is a permanent failure : the address doesn't exist, the domain is dead, the mailbox is gone. You must never send to a hard-bounced address again. Continuing to do so tells receivers you don't clean your list, which tanks your reputation.
A soft bounce is a temporary failure : mailbox full, server briefly down, message too large. It's reasonable to retry a soft bounce a few times, but if an address soft-bounces repeatedly over days, treat it as dead and stop.
Suppression lists
The mechanism that enforces this is a suppression list: a list of addresses you will not send to. Every hard bounce, every spam complaint, and every unsubscribe should be added to it automatically, and your sending path must check it before every send. Good ESPs maintain suppression lists for you and silently drop sends to suppressed addresses : but you should confirm yours does, and never override it to "just try anyway." Sending to a known-bad address is one of the fastest ways to wreck a young domain's reputation.
Feedback loops (FBLs) and the complaint rate threshold
A feedback loop is a service mailbox providers offer that notifies you when a recipient marks your mail as spam. When you register for FBLs (your ESP usually handles this), those complaints flow back to you so you can immediately suppress the complainer. A complaint is a much stronger negative signal than a bounce : the recipient is actively telling Gmail your mail is unwanted.
This connects directly to the hard threshold every sender now lives under. Gmail and Yahoo require senders to keep their spam complaint rate below 0.3%, and Gmail is explicit that you should aim to stay below 0.1% and never reach 0.3%. To put that in perspective: at a 0.3% rate, only 3 complaints per 1,000 delivered messages is enough to put you in trouble. Cross that line consistently and your mail starts getting filtered to spam or rejected outright : not just the marketing mail that caused it, but everything from that domain.
Keeping complaint rate down is mostly about not sending mail people don't want:
- Only send to people who opted in. Never buy lists.
- Make unsubscribe trivial. If you send marketing or subscribed messages at volume, you're now required to support one-click unsubscribe (the
List-UnsubscribeandList-Unsubscribe-Postheaders) and to honor it within a couple of days. - Watch your complaint rate in Google Postmaster Tools, which reports it directly for your domain.
- Suppress complainers immediately via your FBL : someone who complained once and gets another email is far more likely to complain again.
The practical takeaway: wire bounce and complaint handling into your suppression list from day one, register for feedback loops, and treat your complaint rate as a number you monitor as closely as your error rate. A clean list with low complaints is the single biggest lever on long-term deliverability : bigger than any DNS record.
Step 8: Configure alerts so you find out when something breaks
Your email configuration will break at some point. It always does. A new teammate adds a Notion integration that sends via your domain without DKIM. Your ESP rotates a DKIM key and the migration fails. Someone updates DNS and overwrites your SPF record. These happen in production.
A DMARC monitoring tool with alerts catches these within a few hours. Without one, you find out when customers stop receiving emails and file support tickets.
Minimum viable monitoring:
- DMARC aggregate reports processed (not sitting as gzipped XML in an alias)
- Alert on alignment regression (pass rate drops below ~95%)
- Alert on new unauthorized senders appearing in reports
This saves you from shipping a broken email flow. It also catches spoofing attempts early, before they affect customer trust.
Step 9 (when you're ready): Move to enforcement
p=none is permanent for a lot of people. They set it up, watch the reports for a day, then forget about them and never move forward. Don't do this.
Once your reports show more than 95% of legitimate mail passing DMARC alignment consistently (usually takes 2-4 weeks), move to p=quarantine. Watch for false positives for another 2-4 weeks. Once you're confident, move to p=reject.
p=reject means any email failing DMARC alignment gets rejected by receiving servers outright. This blocks spoofing attempts from your domain completely. Attackers can't impersonate you anymore. But it also means if your configuration is wrong, your emails stop landing. The monitoring you set up in step 8 is what makes it safe to get there.
If you're running enforcement at the root but still ramping a new sending subdomain, remember the sp= tag from step 1: you can hold the root at p=reject while keeping subdomains at sp=none until they're proven, then tighten.
For the full enforcement journey, see enforcing DMARC: p=quarantine vs p=reject.
What's next
Your first aggregate reports will start arriving within 24–48 hours of publishing your DMARC record. DMARCdrift is free for your first domain: point your rua= address at us and we'll turn the XML into something readable.
