Skip to content

SOP: Email Deliverability for Web Applications

SOP: Email Deliverability for Web Applications

Section titled “SOP: Email Deliverability for Web Applications”

Document Type: Standard Operating Procedure (SOP)
Version: 1.0
Status: Approved for Use
Audience: Technician
Confidentiality: Internal
Platforms Supported: Any web application sending transactional email


To ensure that automated emails sent by web applications (account verification, password resets, order confirmations, notifications) are delivered to the recipient’s inbox — not their spam folder.

This SOP covers DNS authentication, email provider configuration, and a verification checklist that should be completed before any site goes live.


This SOP applies to:

  • Transactional email from web applications (auth emails, notifications, receipts)
  • DNS record setup for email authentication (SPF, DKIM, DMARC)
  • Email service provider domain verification
  • Auth provider custom SMTP relay configuration
  • Deliverability testing and scoring

Not included:

  • Client-facing email accounts (see SOP: Email Setup Services)
  • Email marketing campaigns
  • Mailing list management

Technician Responsibilities

  • Configure sending subdomain and DNS records
  • Set up email service provider and verify domain
  • Configure auth provider SMTP relay
  • Run deliverability tests and verify passing scores
  • Document the sending configuration for the project

Project Manager Responsibilities

  • Ensure email deliverability is included in project scope
  • Verify testing is completed before go-live
  • Confirm client has DNS access or delegate credentials

  • DNS management access (e.g., Cloudflare, GoDaddy, Namecheap)
  • Email service provider account (e.g., Resend, SendGrid, Postmark, Mailgun)
  • Auth provider dashboard access (e.g., Supabase, Firebase, Auth0) — if auth emails are in scope
  • Terminal with dig command (for DNS verification)
  • mail-tester.com (for deliverability scoring)
  • Access to Gmail, Outlook, and Yahoo test accounts (for cross-provider testing)

Never send transactional email from the root domain. Always use a dedicated subdomain.

ConcernRoot domainSubdomain
Reputation isolationIf deliverability suffers, your entire domain is affectedSubdomain reputation is separate from root
Blocklist riskRoot domain blocklisted = all email affected (including business email)Only the sending subdomain is at risk
DNS claritySPF/DKIM records mix with business email recordsClean separation of concerns

Choose a subdomain name that reflects its purpose:

SubdomainUse case
updates.domain.comGeneral transactional (notifications, auth)
mail.domain.comGeneric sending
notify.domain.comNotification-heavy apps
send.domain.comSimple, common convention

The “From” address should be noreply@{subdomain} for automated emails.

Example: noreply@updates.wizardtechservices.com


Every sending subdomain needs four types of DNS records. SPF and DKIM do not inherit from the root domain — each subdomain must have its own.

What it does: Tells receiving mail servers which IP addresses are allowed to send email for this domain.

Record type: TXT
Name: The sending subdomain (or a sub-subdomain like send.updates — check your provider)
Format:

v=spf1 include:{provider-spf-domain} ~all

Common provider SPF includes:

ProviderSPF include
Resend (via Amazon SES)include:amazonses.com
SendGridinclude:sendgrid.net
Postmarkinclude:spf.mtasv.net
Mailguninclude:mailgun.org

Example (Resend + Cloudflare):
Type: TXT | Name: send.updates | Content: v=spf1 include:amazonses.com ~all

What it does: Adds a cryptographic signature to every email, proving it hasn’t been tampered with in transit. The receiving server checks the signature against a public key in your DNS.

Record type: TXT or CNAME (varies by provider)
Name: Provider-specific (e.g., resend._domainkey.updates, s1._domainkey.send, etc.)
Value: Provided by the email service — this is a public key, not something you generate.

Example (Resend + Cloudflare):
Type: TXT | Name: resend._domainkey.updates | Content: p=MIGfMA0GCSq... (key from Resend dashboard)

What it does: Enables the email provider to receive bounce notifications and complaint feedback for emails sent from this subdomain.

Record type: MX
Name: The sending subdomain
Priority: 10
Value: Provider’s feedback SMTP server

Example (Resend + Cloudflare):
Type: MX | Name: send.updates | Priority: 10 | Content: feedback-smtp.us-east-1.amazonses.com

6.4 DMARC (Domain-based Message Authentication, Reporting & Conformance)

Section titled “6.4 DMARC (Domain-based Message Authentication, Reporting & Conformance)”

What it does: Tells receiving servers what to do with emails that fail SPF/DKIM checks, and where to send reports about authentication results.

Record type: TXT
Name: _dmarc.{subdomain} (e.g., _dmarc.updates)
Format:

v=DMARC1; p={policy}; rua=mailto:{reports-email}

Policy values:

PolicyMeaningWhen to use
p=noneMonitor only, don’t act on failuresInitial setup if unsure about all senders
p=quarantineSend failures to spam/junkRecommended baseline for sending subdomains
p=rejectBlock failures entirelyAfter monitoring confirms no legitimate failures

For a dedicated sending subdomain (where the only sender is your email provider), go straight to p=quarantine. There’s no risk of blocking legitimate email from other sources.

Example (Cloudflare):
Type: TXT | Name: _dmarc.updates | Content: v=DMARC1; p=quarantine; rua=mailto:support@domain.com

Also strengthen the root domain DMARC if it’s set to p=none:

v=DMARC1; p=quarantine; rua=mailto:support@domain.com; pct=100

7. Procedure — Email Provider Domain Verification

Section titled “7. Procedure — Email Provider Domain Verification”

This section walks through verifying a sending domain with your email provider. The steps are similar across providers.

  1. Log in to your email service provider dashboard
  2. Navigate to Domains or Sender Authentication
  3. Click Add Domain → enter your sending subdomain (e.g., updates.domain.com)
  4. The provider will generate the exact DNS records you need (SPF, DKIM, MX)
  5. Add each record to your DNS provider (see Section 6)
  6. Return to the email service dashboard and click Verify
  7. Wait for propagation (usually under 5 minutes with Cloudflare)
  8. All status indicators should turn green

Note: Resend is used here as an example. The same pattern applies to SendGrid, Postmark, Mailgun, etc.

  1. Go to resend.com/domains
  2. Click Add Domain → enter updates.clientdomain.com
  3. Resend provides three records:
    • DKIM: TXT record for resend._domainkey.updates
    • SPF: TXT record for send.updates with include:amazonses.com
    • MX: MX record for send.updates pointing to feedback-smtp.us-east-1.amazonses.com
  4. Add all three in Cloudflare (set to DNS only, not Proxied)
  5. Add DMARC manually (Resend doesn’t generate this — see Section 6.4)
  6. Return to Resend and click Verify — all three should show green checkmarks

8. Procedure — Auth Provider SMTP Configuration

Section titled “8. Procedure — Auth Provider SMTP Configuration”

If the web application uses a hosted auth provider (Supabase, Firebase, Auth0, etc.) for signup/login, the auth provider sends verification and password reset emails. By default these come from the provider’s own domain (e.g., noreply@mail.app.supabase.io), which looks unprofessional and may trigger spam filters.

Configure custom SMTP so auth emails route through your email service and use your verified sending domain.

  1. In your email service provider, find or generate SMTP credentials (host, port, username, password)
  2. In your auth provider dashboard, go to Authentication → SMTP Settings (or equivalent)
  3. Enable custom SMTP and enter the credentials
  4. Set the Sender email to match your verified domain (e.g., noreply@updates.domain.com)
  5. Save and send a test email

8.2 Example — Supabase Auth via Resend SMTP

Section titled “8.2 Example — Supabase Auth via Resend SMTP”

Note: Supabase and Resend are used as examples. The pattern is the same for Firebase + SendGrid, Auth0 + Postmark, etc.

  1. In Resend, go to API Keys and generate an SMTP credential, or use the API key as the SMTP password
  2. In Supabase Dashboard → Project Settings → Authentication → SMTP Settings:
    • Host: smtp.resend.com
    • Port: 465
    • Username: resend
    • Password: Your Resend API key
    • Sender email: noreply@updates.clientdomain.com
  3. Save and test by triggering a signup on the app

Critical: The “Sender email” must match the verified sending domain. If the domain in the “From” address doesn’t match what’s verified in your email provider, emails will fail DKIM/SPF.


9. Procedure — Google & Microsoft Sender Requirements (2025)

Section titled “9. Procedure — Google & Microsoft Sender Requirements (2025)”

Major mailbox providers enforce strict sender authentication. Non-compliant emails are junked or rejected outright.

Applies to: All senders to personal Gmail accounts (stricter for 5,000+ msgs/day)

RequirementDetails
SPF or DKIMAt least one must pass (both recommended)
DMARCRequired with alignment to SPF or DKIM
TLSEmail must be sent over encrypted connection
Spam rateMust stay below 0.3%
One-click unsubscribeRequired for marketing email (not transactional)

Applies to: Senders to Outlook.com, Hotmail, Live.com

RequirementDetails
SPF + DKIM + DMARCAll three required with alignment
Valid From/Reply-ToMust use real, monitored addresses
Unsubscribe optionRequired for bulk/marketing email
ComplianceNon-compliant emails blocked as of July 2025

Bottom line: If SPF, DKIM, and DMARC aren’t all passing, emails to Gmail and Outlook users will land in spam or be rejected entirely.


Run these from a terminal after adding DNS records. All should return values (not empty):

Terminal window
# Check SPF
dig TXT send.updates.clientdomain.com +short
# Check DKIM
dig TXT resend._domainkey.updates.clientdomain.com +short
# Check MX
dig MX send.updates.clientdomain.com +short
# Check DMARC (subdomain)
dig TXT _dmarc.updates.clientdomain.com +short
# Check DMARC (root)
dig TXT _dmarc.clientdomain.com +short

Replace clientdomain.com, send.updates, and resend._domainkey.updates with the actual record names from your email provider.

  1. Go to mail-tester.com
  2. Copy the test email address shown on the page
  3. Trigger an email from the app to that address (or send one via the provider’s API/dashboard)
  4. Click “Then check your score”
  5. Target: 9+/10 — anything below 7 indicates a problem

Open a received test email and view the full headers (in Gmail: three dots → “Show original”). Confirm:

  • spf=pass
  • dkim=pass
  • dmarc=pass

All three must show pass. If any show fail, softfail, or none, go to Troubleshooting.

Send test emails to accounts on each major provider and verify inbox delivery (not spam):

  • Gmail
  • Outlook / Hotmail
  • Yahoo Mail
  • Apple Mail (iCloud)
CheckStatus
Sending subdomain chosen and documented
SPF record added and resolves via dig
DKIM record added and resolves via dig
MX record added and resolves via dig
DMARC record added for subdomain (p=quarantine minimum)
Root domain DMARC strengthened (p=quarantine or p=reject)
Domain verified in email provider dashboard (all green)
Auth provider custom SMTP configured and “From” matches domain
mail-tester.com score 9+/10
Email headers show spf=pass, dkim=pass, dmarc=pass
Test email delivered to inbox on Gmail
Test email delivered to inbox on Outlook

ProblemCauseFix
Emails land in spamMissing or failing SPF/DKIM/DMARCVerify all DNS records resolve correctly with dig
spf=softfail in headersSPF record uses ~all but provider not includedAdd the correct include: for your email provider
spf=fail in headersNo SPF record for the sending subdomainSPF doesn’t inherit from root — add one for the subdomain
dkim=fail in headersDKIM record missing or wrong keyRe-copy the DKIM value from provider dashboard; check for typos
dmarc=none in headersNo DMARC record for the sending subdomainAdd _dmarc.{subdomain} TXT record
dmarc=fail in headers”From” domain doesn’t align with SPF/DKIM domainEnsure the “From” address uses the same subdomain that has SPF/DKIM
Domain shows “Not Verified” in providerDNS records haven’t propagatedWait 5-15 minutes; Cloudflare is usually instant, other registrars can take up to 48 hours
Auth emails still come from provider’s domainCustom SMTP not enabled or “From” not setCheck auth provider SMTP settings; ensure sender email matches verified domain
Bounces not being trackedNo MX record on sending subdomainAdd the MX record your email provider requires
mail-tester score below 7Multiple issues (check the report details)mail-tester shows exactly what’s failing — fix each item listed
Emails to Outlook blocked entirelyMicrosoft 2025 enforcementEnsure SPF + DKIM + DMARC all pass with alignment

  • Monitor DMARC reports: Check the rua inbox periodically for aggregate reports — look for unexpected authentication failures
  • Review provider dashboard: Check bounce rates and complaint rates monthly; keep complaint rate below 0.1%
  • DMARC policy progression: After 2-4 weeks of clean reports, upgrade from p=quarantine to p=reject
  • Re-test after changes: Any DNS or provider change requires re-running the verification checklist (Section 10)
  • Key rotation: If your email provider rotates DKIM keys, update the DNS record promptly

  • SPF and DKIM do not inherit from the root domain — every sending subdomain needs its own records
  • Cloudflare-proxied (orange cloud) DNS records can interfere with email — set email-related records to DNS only (grey cloud)
  • p=none DMARC provides zero protection and is treated as a red flag by Gmail and Outlook — always use p=quarantine or stronger for sending subdomains
  • Some email providers have sending limits on free tiers — verify limits before go-live
  • Never store email API keys in client-side code — all email sending must happen server-side

  • Version: 1.0
  • Editor: Wizard Tech Services
  • Next Review: Within 90 Days