Replace the default SMTP configuration with an API-based transactional email service. JekCMS ships with driver classes for Mailgun, Postmark, and Amazon SES in classes/Mail/. Set the MAIL_DRIVER constant in your environment file and add the API key. For most installations, Mailgun's pay-as-you-go tier is the most cost-effective starting point; Postmark is better for installations where inbox placement is critical and volume is predictable.

SPF, DKIM, and DMARC: Do This Before Sending

Configure SPF and DKIM records in your DNS before sending any production email. Your transactional email provider's control panel will give you the exact record values. Allow 24–48 hours for DNS propagation, then test with mail-tester.com before going live. A score below 8/10 indicates a configuration problem that will affect deliverability. DMARC should be added in monitoring mode first (p=none), then tightened to quarantine and reject after observing the DMARC aggregate reports for two weeks.

Bounce Handling and Suppression

Bounce handling requires a webhook endpoint or a dedicated mailbox. Hard bounces — addresses that return a permanent error — should immediately suppress the recipient. JekCMS's built-in mail drivers handle suppression automatically when you configure the provider's bounce webhook to point at /api/v1/mail/bounce. Soft bounces (temporary failures) are retried three times with exponential backoff before the address is suppressed.

Separate Domains for Newsletters vs. Transactional

For high-volume sending — newsletters, weekly digests — utilize a separate sending domain from your transactional domain. A newsletter batch flagged as spam should not affect the deliverability of password-reset and account-confirmation emails. Configure per-email-type sending domains in config/email.php using the from_domain key in each mail type's configuration block.

Delivery Monitoring and Alerting

Deliverability is not a set-and-forget configuration. Track these four metrics on a weekly basis:

  • Delivery rate: should stay above 98%. A drop below 95% indicates a reputation problem requiring immediate investigation.
  • Bounce rate: hard bounces above 2% per campaign signal a list hygiene issue. Audit your import process and remove addresses older than 12 months without engagement.
  • Spam complaint rate: must remain below 0.1%, the threshold Google publishes for Gmail senders. Above 0.3% and Gmail routes your messages to spam for all recipients.
  • Transactional open rate: password resets and order confirmations typically see 60-80% open rates. Below 40% suggests inbox placement problems that need DNS or reputation investigation.

JekCMS logs delivery events in the email_logs table with columns for status, provider_message_id, opened_at, and bounced_at. The admin dashboard includes a 7-day rolling summary widget. For automated alerting, set the MAIL_ALERT_EMAIL constant in your environment file; the system sends a daily digest whenever any metric crosses its warning threshold.

Verifying DNS Records

After configuring your sending domain, verify the records are live before enabling production email:

# Check SPF record
dig TXT yourdomain.com +short
# Expected: "v=spf1 include:mailgun.org ~all"

# Check DKIM record
dig TXT selector._domainkey.yourdomain.com +short
# Expected: "k=rsa; p=MIGfMA0..."

# Check DMARC record
dig TXT _dmarc.yourdomain.com +short
# Expected: "v=DMARC1; p=none; rua=mailto:..."

Unsubscribe Mechanics and Compliance

Every marketing and newsletter email must include a functioning unsubscribe link. RFC 8058 requires a List-Unsubscribe header with a one-click POST URL. Gmail and Yahoo enforce this since February 2024 for bulk senders exceeding 5,000 messages per day. JekCMS adds this header automatically for email types configured as marketing or newsletter.

The unsubscribe endpoint at /api/v1/mail/unsubscribe accepts both GET (for the visible link in the email body) and POST (for the one-click header mechanism). Both methods require a signed HMAC token to prevent abuse. After unsubscription, the address is added to the per-list suppression table, not the global suppression list, so a user who unsubscribes from the weekly digest still receives password-reset emails.

Pre-Launch Email Testing Checklist

Before enabling production email, send test messages to accounts on Gmail, Outlook, Yahoo, and Apple Mail. Verify each condition:

  • Message lands in the primary inbox, not spam or promotions tab
  • HTML rendering matches your template across all four clients
  • Unsubscribe link processes the request within 10 seconds
  • DKIM signature shows pass in the Authentication-Results header
  • SPF check shows pass in the Received-SPF header
  • Reply-to address is monitored and functioning

Run this checklist after every DNS change, after switching providers, and after modifying email templates. A 5-minute verification prevents weeks of reputation damage that takes 30-60 days to recover from.

Provider Comparison for JekCMS Sites

Based on our experience running transactional email for 200+ JekCMS installations, here is a practical comparison of the three supported providers:

  • Mailgun: best for sites sending under 10,000 emails per month. Pay-as-you-go pricing at $0.80 per 1,000 emails. Deliverability is solid with proper DNS configuration. Setup time: 30 minutes including DNS propagation verification.
  • Postmark: best for sites where inbox placement is mission-critical (e-commerce order confirmations, appointment reminders). Higher base cost at $1.25 per 1,000 emails, but consistently achieves 98%+ inbox placement rates. Dedicated IP addresses available for high-volume senders.
  • Amazon SES: best for high-volume senders exceeding 100,000 emails per month. Lowest unit cost at $0.10 per 1,000 emails, but requires more configuration effort and monitoring. Not recommended for teams without DevOps experience.

Switch between providers by changing the MAIL_DRIVER constant and updating the API key. No code changes are required in your themes or admin panel. The JekCMS mail abstraction layer handles the provider-specific API differences transparently.