Email Deliverability
debt(d9/e5/b5/t7)
Closest to 'silent in production until users hit it' (d9). The detection_hints indicate automated detection is 'no' and the tools listed (mail-tester, mxtoolbox, postmark) are manual, external diagnostic services — not integrated into CI/CD or linting pipelines. Emails silently route to spam in production; no compile-time, linter, or runtime error is raised. Users or business metrics (lost signups, missed password resets) are typically the first signal.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix points to swapping PHP mail() or raw SMTP for a transactional email service, but this also requires adding SPF/DKIM/DMARC DNS records, updating mail-sending code across the application, configuring authentication credentials, and setting up bounce/webhook handling. It is more than a one-line patch but typically contained to the email-sending component and DNS configuration rather than a full cross-cutting codebase refactor.
Closest to 'persistent productivity tax' (b5). The applies_to field covers web, cli, and queue-worker contexts — all three PHP runtime contexts — meaning any part of the application that sends email is affected. Poor deliverability setup creates ongoing operational overhead (monitoring bounce rates, maintaining DNS records, managing IP reputation) that persists across multiple work streams, though it does not fundamentally reshape the entire system architecture.
Closest to 'serious trap (contradicts how a similar concept works elsewhere)' (t7). The misconception field explicitly states that developers commonly believe SPF alone is sufficient, when in fact all three of SPF, DKIM, and DMARC are required, and DMARC without DKIM leaves the domain spoofable. This is a well-documented but widely misunderstood multi-layer requirement — a competent developer configuring SPF and believing the job is done will be wrong in a consequential way that is hard to detect until spoofing or spam filtering incidents occur.
Also Known As
TL;DR
Explanation
SPF (Sender Policy Framework): a DNS TXT record listing authorised sending IPs for your domain. DKIM (DomainKeys Identified Mail): cryptographic signature on outgoing emails, verified by recipients using a public key in DNS. DMARC (Domain-based Message Authentication): policy defining what to do when SPF/DKIM fail (none, quarantine, reject) and where to send reports. Sending reputation is built on low bounce rates, low spam complaint rates, and consistent sending volume. PHP applications should use a transactional email service (SendGrid, Postmark, SES) rather than server SMTP.
Diagram
flowchart LR
PHP[PHP App] -->|SMTP| MTA1[Sending MTA<br/>sendgrid.net]
MTA1 -->|DNS MX lookup| MTA2[Receiving MTA<br/>gmail.com]
MTA2 --> FILTER{Spam Filter}
FILTER -->|SPF pass| FILTER2{DKIM check}
FILTER2 -->|valid signature| INBOX[Inbox]
FILTER -->|SPF fail| SPAM[Spam / Rejected]
FILTER2 -->|invalid| SPAM
DNS[DNS Records:<br/>SPF TXT record<br/>DKIM TXT record<br/>DMARC TXT record] -.->|validates| FILTER & FILTER2
style INBOX fill:#238636,color:#fff
style SPAM fill:#f85149,color:#fff
style DNS fill:#1f6feb,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Using server's own SMTP for transactional email — shared hosting IP reputation is poor; use a dedicated sending service.
- SPF record with too many DNS lookups — SPF has a 10 DNS lookup limit; exceeding it causes SPF failures.
- Not setting DMARC policy — without DMARC, spoofed emails from your domain bypass SPF/DKIM failures.
- Not monitoring bounce rates — high bounce rates signal ISPs to start filtering your email.
Code Examples
// Using PHP mail() directly — poor deliverability:
mail('user@example.com', 'Reset Password', $body);
// Sent from shared hosting IP with no SPF/DKIM/DMARC
// Goes straight to spam or rejected
// Transactional email service with authentication:
// DNS records required:
// TXT @ 'v=spf1 include:sendgrid.net ~all'
// TXT s1._domainkey 'v=DKIM1; k=rsa; p=<public_key>'
// TXT _dmarc 'v=DMARC1; p=reject; rua=mailto:dmarc@example.com'
// PHP with SendGrid:
$email = new SendGrid\Mail\Mail();
$email->setFrom('noreply@example.com');
$email->addTo($userEmail);
$email->setSubject('Reset your password');
$email->addContent('text/html', $htmlBody);
$sendgrid = new SendGrid(getenv('SENDGRID_API_KEY'));
$sendgrid->send($email);