Diagnosing Ghost CMS Transactional Email Failures: A Step‑by‑Step Guide
When Ghost’s sign‑in links, staff invites, and member emails stop arriving, the site is still up. This guide walks through the most common causes, ordered checks, and fixes—complete with config snippets, log‑examining commands, and escalation criteria.
14 Oct 2025, 01:03 UTC

Recognizable Condition
Users can open the public site and the Ghost Admin panel, but any email that should be sent automatically—magic sign‑in links, staff invites, password‑reset links, or member welcome/newsletter emails—never lands in inboxes. The Ghost UI reports “no email” or simply shows no activity in the email queue. The site remains functional, so the problem is isolated to the transactional mail subsystem.
Cause & Diagnostic Table
| Root Cause | Typical Symptom | Diagnostic Lead |
|---|---|---|
| Missing or unsupported mail transport | No log entries, Ghost shows “no email” | Check config.production.json mail block |
| SMTP authentication or TLS mismatch | Ghost logs “Authentication failed” or “STARTTLS not supported” | Inspect ghost log for Nodemailer errors |
Incorrect url setting | Received links point to a different host or are malformed | Verify url in config |
| Provider‑side suppression or DNS mis‑config (SPF/DKIM/DKIM) | Provider dashboard shows bounces or a blocked domain; mail arrives but is marked spam | Check provider logs, DNS records |
Ordered Checks
- Scope the failure. Trigger a password‑reset or staff invite and confirm that no email is received. If only member‑mail fails, note that distinction.
- Inspect the active Ghost config. On a self‑hosted install, run:
Verify that thecat /var/www/ghost/config.production.json | grep -A5 mailtransportfield is set and that the values match your SMTP provider’s documentation. - Reproduce the failure. From the command line, run Ghost’s built‑in test email:
The command prints the exact Nodemailer error if any.ghost test email --to [contact removed] - Read the logs. Ghost writes to
/var/log/ghost/ghost.logor via systemd. Run:
Look for entries likejournalctl -u ghost -n 200 | grep -i nodemailerSMTP Authentication failedorSTARTTLS required but not available. - Test SMTP outside Ghost. Use
openssl s_clientorswaks:
If the test succeeds, credentials are valid and the issue is Ghost‑specific.swaks --to [contact removed] \\n --server smtp.example.com:587 \\n --auth LOGIN --auth-user [contact removed] \\n --auth-password 'yourpassword' \\n --tls - Check provider status. Log into your SMTP dashboard and review suppression lists, bounce logs, and domain verification status. Verify that the sending domain has valid
SPF,DKIM, andDMARCrecords.
Fixes Tied to Findings
- Wrong transport. Set a supported transport. For example, to use Gmail’s SMTP:
Save the config and restart Ghost:{ "mail": { "transport": "SMTP", "options": { "host": "smtp.gmail.com", "port": 587, "secure": false, "auth": { "user": "[contact removed]", "pass": "app-password" } } } }ghost restart. - Auth/TLS mismatch. If the provider only supports STARTTLS on port 587, set
secure: falseand ensurerequireTLS: trueis not set. If TLS is mandatory, switch to port 465 withsecure: true. - Wrong
url. In the same config file, correct theurlfield:
A mismatch causes magic links to point to an unreachable host.{ "url": "https://your‑site.com" } - Provider suppression or DNS. Add or correct SPF, DKIM, and DMARC TXT records. After DNS propagation, clear any suppression entries for the test recipient in the provider’s console.
- Separate bulk vs transactional limits. If member newsletters fail but single transactional emails succeed, contact your provider to raise the bulk‑sending quota or set up a dedicated transactional SMTP account.
Escalation Criteria
- Credentials work in external tests but Ghost logs a persistent transport error.
- Provider shows emails as delivered but recipients never receive them.
- Failure starts after a Ghost or OS upgrade while config remains unchanged.
- Suspicion of credential leakage: the same credentials are used by an external app or appear in logs.
Practical Example
Suppose a Ghost 5.0 deployment on Ubuntu 24.04 uses SendGrid. The config.production.json contains:
{
"mail": {
"transport": "SMTP",
"options": {
"host": "smtp.sendgrid.net",
"port": 587,
"secure": false,
"auth": {
"user": "apikey",
"pass": "SG.xxxxx"
}
}
}
}
After a password reset, the user receives no email. Running ghost test email --to [contact removed] outputs:
error: 535 5.7.8 Authentication credentials invalid. (Service: SMTP, Status Code: 535, Request ID: null)
Running swaks --to [contact removed] --server smtp.sendgrid.net:587 --auth LOGIN --auth-user apikey --auth-password SG.xxxxx --tls succeeds. The issue is Ghost’s auth.user field incorrectly set to the literal string “apikey” instead of the SendGrid API key. Updating the config to use the actual API key value, restarting Ghost, and re‑testing resolves the problem.
Limitations & Verification
- Managed Ghost hosting often overrides
config.production.json. Verify the effective configuration via the host’s dashboard or by inspectingghost logfor the active settings. - Ghost versions prior to 4.0 used
mail.transportOptionsinstead ofmail.options. Check the official docs for your version. - After any change, always run
ghost restartand trigger a test email to confirm the fix. - Never expose real credentials in logs or tickets; rotate them before sharing.
By following the ordered checks and applying the targeted fixes above, most Ghost transactional email failures can be resolved quickly, restoring the full user experience without downtime.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.