Why transactional email delivery is a different beast
There's a critical distinction between marketing emails and transactional emails that many developers miss when they first start thinking seriously about deliverability. Marketing emails — newsletters, promotional campaigns, announcements — go to subscribers who've opted in. They can tolerate occasional delays and even occasional spam folder placements. If a newsletter goes to spam for 2% of your list, that's unfortunate but your business continues.
Transactional emails are completely different. Verification links, password resets, purchase confirmations, two-factor authentication codes, account security alerts — these land at critical moments in a user's journey. A password reset going to spam means your user is locked out of their account and will likely raise a support ticket or, worse, never come back. A verification email going to spam means a new user can't complete registration and your acquisition funnel has a silent, invisible leak.
And yet, transactional emails are frequently set up with less care than marketing campaigns. Many developers use whatever email-sending code their framework provides, configure it with a shared SMTP server, deploy it, test it once with their own inbox — which has generous spam thresholds — and move on. The problems only surface when real users on Gmail, Outlook, or Yahoo report missing emails. By that point, the issue has been silently failing in production for weeks.
SPF: the foundation of email authentication
Sender Policy Framework (SPF) is a DNS TXT record on your sending domain that tells the world which mail servers are authorised to send email on your behalf. When Gmail receives an email purportedly from noreply@yourapp.com, it performs a DNS lookup for your domain's SPF record. If the IP address of the server that actually sent the email is listed in your SPF record, the email passes SPF. If there's no SPF record at all — or the sending server isn't listed — the email is treated with suspicion before any content evaluation even begins.
Setting up SPF is straightforward once you know what you're doing. Add a TXT record to your domain's DNS. The value depends on your sending provider. If you use SendGrid: v=spf1 include:sendgrid.net ~all. If you use AWS SES: v=spf1 include:amazonses.com ~all. If you use Mailgun: v=spf1 include:mailgun.org ~all. Your provider's documentation will give you the exact include value. The ~all suffix is a "soft fail" — emails from unlisted servers are flagged but not outright rejected. Once you're confident that your SPF record is complete and correct, you can upgrade to -all (hard fail), which instructs receiving servers to reject unauthorised mail entirely.
One common pitfall: the 10-DNS-lookup limit. SPF records that chain together multiple include: directives can exceed this limit, causing SPF to fail even if all your servers are technically listed. Use MXToolbox to check your SPF record — it will flag lookup count issues clearly. Understanding how SPF, DKIM, and DMARC interrelate is covered well in SendGrid's documentation on email authentication.
DKIM: cryptographic proof your email wasn't tampered with
DomainKeys Identified Mail (DKIM) adds a cryptographic signature to every email you send. The signature is generated using a private key held by your sending provider, and receiving mail servers verify it against a public key you publish as a DNS TXT record. If the signature checks out, two things are proven: the email genuinely originated from your sending infrastructure, and the content was not modified between sending and receipt.
Without DKIM configured, it becomes significantly easier for malicious actors to spoof your domain — to send emails that appear to come from noreply@yourapp.com but were actually sent by someone else entirely. This is how phishing campaigns work. Spam filters know this too, which is why an email missing a valid DKIM signature from a domain that should have one is treated with elevated suspicion. Spamhaus and other reputation services factor DKIM signing history into domain reputation scores.
Setting up DKIM is done through your sending provider. They generate a key pair, hold the private key on their infrastructure, and give you a public key to add to your DNS as a TXT record. Once that DNS record is published and propagated, every email they send on your behalf will carry a valid DKIM signature automatically. Most major providers — SendGrid, Mailgun, Amazon SES, Postmark — walk you through this process during initial setup. If you skipped it, go back and configure it now.
DMARC: the policy layer that ties it together
DMARC (Domain-based Message Authentication, Reporting, and Conformance) builds on SPF and DKIM by defining what receiving servers should do when an email fails those checks. It also introduces "alignment" — requiring that the domain in the email's From header actually matches the domain that passed SPF or DKIM. This prevents attackers from passing SPF checks on one domain while spoofing another in the visible From address.
The right approach to DMARC is to start gradually. Begin with a monitoring-only policy: v=DMARC1; p=none; rua=mailto:dmarc-reports@yourapp.com. The p=none tells receiving servers not to take action on failures, just to send you reports. Those aggregate reports will tell you which servers are sending email on your behalf and whether they're passing SPF and DKIM. Review them for a few weeks before making any policy changes.
Once you're confident everything legitimate is passing, move to p=quarantine (failed emails go to spam folder) and eventually p=reject (failed emails are rejected outright). This progression protects your domain's reputation from spoofing while giving you time to catch any legitimate email sources you may have missed. A DMARC policy of p=reject combined with passing SPF and DKIM makes it nearly impossible for attackers to impersonate your domain effectively.
IP reputation: why your sending server matters
Even with perfect SPF, DKIM, and DMARC, your emails can still go to spam if the IP address they're sent from has a poor reputation. Receiving mail servers maintain — or consult third-party services that maintain — blocklists and reputation scores for sending IP addresses. An IP with a history of sending spam, or that appears on blocklists maintained by services like Spamhaus, will have its outbound emails treated with suspicion regardless of your authentication setup.
If you're using a shared IP address from a shared hosting provider or a cheap SMTP service, your reputation is tied to everyone else using that same IP. One spammer on the same shared pool can tank deliverability for all senders on that IP. This is one of the strongest arguments for using a dedicated transactional email provider — SendGrid, Amazon SES, Postmark, Mailgun — rather than sending email directly from your application server or through a shared SMTP service.
On a new sending IP, you'll also need to "warm up" the IP gradually. Sending a sudden spike of email volume from a fresh IP looks like spam behaviour to receiving servers. Start with lower volumes and increase gradually over days or weeks. Most dedicated email providers handle IP warming automatically if you're on a shared sending pool, or provide IP warming schedules if you're using a dedicated IP.
Content and subject line: what triggers filters
Beyond authentication and IP reputation, the content of your email itself is evaluated by spam filters. Certain patterns reliably trigger spam classification. Spam trigger words in the subject line — "FREE", "GUARANTEED", "ACT NOW", excessive exclamation marks, ALL CAPS — are obvious ones that most developers avoid. Less obvious: subject lines that are too vague ("Important message for you"), too urgent ("Your account will be closed"), or too promotional for what's supposed to be a transactional email.
The text-to-image ratio matters too. An email that's mostly images with minimal text is a classic spam pattern — bulk mailers use images to obscure keywords from text-based filters. Transactional emails should be primarily text-based with minimal images. Broken HTML — unclosed tags, malformed attributes — is another red flag. Always send a plain text alternative alongside your HTML version. Spam filters view HTML-only emails with heightened suspicion, and corporate email systems often strip HTML entirely.
Testing your email delivery — the right way
The fastest and most practical testing method for email delivery is: send a test email to a fresh temp mail inbox and check both the inbox folder and the spam folder. This gives you immediate, unambiguous feedback on whether your email is reaching the inbox or being filtered. Unlike testing with your own Gmail account — which may have you whitelisted as a frequent sender — a fresh temporary address has no prior history with your domain, which more accurately simulates a new user's first-contact experience.
You should test delivery every time you change anything that could affect it: switching email providers, updating your HTML template significantly, changing your sending domain, adding a new sending subdomain, or deploying to a new environment (staging, production). It takes two minutes and gives you definitive evidence. The alternative — waiting for users to report problems — means your deliverability issues have already been silently failing for an unknown period.
Beyond the inbox/spam check, use MXToolbox's email health checker to check your domain's overall health: SPF, DKIM, DMARC, blacklist status, and MX record configuration all in one place. Make this part of your pre-launch checklist for any new application or sending domain. Also check the OWASP guidelines for security-related email best practices.
Bounce rates and spam complaints: the metrics that matter
Two metrics have an outsized effect on long-term deliverability: bounce rate and spam complaint rate. A bounce rate above 2% tells receiving servers and your sending provider that you're sending to a lot of invalid or non-existent addresses — which is a pattern associated with purchased email lists and spam operations. Even if you're doing everything else right, a high bounce rate will cause deliverability problems. Remove hard bounces from your sending list immediately and permanently.
A spam complaint rate above 0.1% (one complaint per thousand emails sent) is the threshold where most sending providers will start restricting your account. Gmail's Postmaster Tools reports complaint rates directly if you've set it up. Monitor these metrics through your sending provider's dashboard. If complaint rates are rising, investigate why — are you sending to users who didn't explicitly opt in? Are your emails too frequent? Is there a mismatch between what users expected and what they're receiving?
Complete deliverability checklist
- SPF record: DNS TXT record on your sending domain listing all authorised sending servers. Test with MXToolbox.
- DKIM: Cryptographic signing configured through your sending provider, public key published in DNS.
- DMARC: Start with
p=nonemonitoring, progress top=quarantinethenp=rejectafter reviewing aggregate reports. - Dedicated sending provider: Use SendGrid, SES, Postmark, or Mailgun — not your application server or shared SMTP.
- Clean subject lines: Specific, relevant, no trigger words, no excessive punctuation or caps.
- HTML + plain text: Always include both. Never send HTML-only emails.
- No URL shorteners: Use full, direct URLs in email body and verification links.
- Unsubscribe link: Include even in transactional email where appropriate — some providers require it.
- Physical address: Required by CAN-SPAM and similar regulations in many jurisdictions.
- Hard bounce handling: Remove immediately; never retry a hard bounce.
- Complaint monitoring: Set up Gmail Postmaster Tools; monitor complaint rate dashboard.
- Inbox testing: Send test emails to fresh temporary inboxes before each deploy and after any template or config change.
- MXToolbox health check: Include in your pre-launch checklist for every new domain and environment.
When to use a dedicated transactional email service
If your application sends any email at all that the user needs to receive to function — verification links, password resets, purchase confirmations — you should be using a dedicated transactional email provider from day one. The cost is low (often free up to tens of thousands of emails per month), the reliability is dramatically better than DIY SMTP, and the deliverability infrastructure — shared IP pools with managed reputation, automatic DKIM signing, bounce and complaint handling — is maintained by teams whose entire job is keeping email in inboxes.
The most common DIY mistake is running a mail server on the same IP as your web application, or using a cheap hosting provider's bundled SMTP service. These IPs are routinely added to blocklists by services like Spamhaus because the hosting environment is shared with bad actors. Switching to a dedicated transactional provider is usually an afternoon of work and has an immediate positive impact on deliverability. It's one of the highest-leverage infrastructure improvements a small team can make. Privacy-conscious teams should also review guidance from the Electronic Frontier Foundation on handling user data responsibly when email is involved. Additionally, monitoring addresses against known breach databases via Have I Been Pwned can supplement your fraud prevention when new accounts are created.