After upgrading from Ghost 6.26.0 to 6.27.0, admin/staff login magic link emails are no longer being sent, even though the send-magic-link API returns 201 and there are no mail-related errors in the logs. The process-outbox job runs but reports no pending outbox entries to process. If I roll back to 6.26.0, magic links work immediately with the same database and SMTP config.
This looks like a regression in the members/magic-link → outbox pipeline between 6.26.0 and 6.27.0, rather than an SMTP or config issue.
Environment
- Ghost: 6.26.0 (working), 6.27.0 (failing)
- Install: self-hosted, Docker
- Ghost image:
ghost:6.26.0-alpine (working), ghost:6-alpine (6.27.0, failing)
- Database: MySQL 8 (in Docker)
- Mail: Gmail SMTP (app password), verified working on 6.26.0
- Reverse proxy: Traefik
- URL: generic public URL (self-hosted; anonymized here)
Relevant configuration
docker-compose excerpt (Ghost service):
services:
ghost:
image: ghost:6-alpine # 6.27.0
container_name: ghost
restart: unless-stopped
networks:
- proxy
- ghost
ports:
- 8088:2368
environment:
database__client: mysql
database__connection__host: <db-host>
database__connection__port: <db-port>
database__connection__user: ghost
database__connection__password: ********
database__connection__database: ghost
url: https://example.com/blog/
volumes:
- /path/to/config.production.json:/var/lib/ghost/config.production.json:ro
- /path/to/content:/var/lib/ghost/content
config.production.json mail section (used by both 6.26.0 and 6.27.0):
"mail": {
"from": "Blog Admin <no-reply@example.com>",
"transport": "SMTP",
"options": {
"service": "Gmail",
"host": "smtp.gmail.com",
"port": 587,
"secure": false,
"auth": {
"user": "no-reply@example.com",
"pass": "GMAIL_APP_PASSWORD"
}
}
}
Notes:
- This config sends magic link emails successfully in 6.26.0.
- The file is mounted into
/var/lib/ghost/config.production.json and verified inside the container.
- The
Missing mail.from config warning was present initially but resolved; it does not appear in 6.27.0 logs anymore.
What works (6.26.0)
With image: ghost:6.26.0-alpine:
-
Start Ghost.
-
Visit /blog/admin/, enter a staff user email to log in.
-
Logs show:
INFO "POST /blog/members/api/send-magic-link/" 201 ...
...
# then the outbox job runs and sends the email
INFO "POST /blog/members/api/verify-otc/" 200 ...
INFO "GET /blog/members/?token=...&action=signin..." 302 ...
-
Magic link email arrives in the inbox.
-
The Gmail account used for SMTP also shows the outgoing email in its “Sent” folder.
So in 6.26.0 the magic link flow and SMTP are both working correctly.
What fails (6.27.0)
Switch only the Ghost image to ghost:6-alpine (6.27.0), keeping the same DB and config:
-
Start Ghost; logs:
INFO Ghost is running in production...
INFO Ghost database ready...
# no "Missing mail.from" warning
-
Visit /blog/admin/, enter the same staff email to log in.
-
Logs show:
INFO "GET /blog/members/api/integrity-token/" 200 ...
INFO [Inbox links] Found no inbox links
INFO "POST /blog/members/api/send-magic-link/" 201 ...
...
INFO Worker for job "process-outbox" online
INFO Worker for job process-outbox sent a message: done
INFO [OUTBOX] No pending outbox entries to process
-
There are no EmailError, Failed to send email, EAUTH, or other mail-related errors.
-
No magic link email is received.
-
The Gmail SMTP account’s “Sent” folder shows no new magic link emails for these attempts.
From the logs it appears that:
send-magic-link returns 201.
process-outbox finds no queued jobs.
- SMTP is never hit; Ghost does not log any error.
This suggests the magic link flow is not enqueuing an outbox job in 6.27.0, despite returning a success status.
What I’ve already tried
- Verified
mail.from and full SMTP settings in config.production.json.
- Fixed the
Missing mail.from config warning; it no longer appears in 6.27.0.
- Confirmed the config file contents inside the 6.27.0 container.
- Confirmed Gmail SMTP and magic links work under Ghost 6.26.0 with the same DB and config.
- Migrated to MySQL 8 with a clean schema and imported content; all other Ghost features appear to work.
- Tested both port 465 (
secure: true) and 587 (secure: false) with the same Gmail app password.
- Checked logs around
send-magic-link, outbox, and email; 6.27.0 logs contain no mail-related errors at all.
Expected behavior
On 6.27.0:
POST /members/api/send-magic-link should:
- Create an outbox entry.
- Be picked up by
process-outbox.
- Send the magic link email via the configured SMTP transport.
Actual behavior
On 6.27.0:
POST /members/api/send-magic-link returns 201.
process-outbox immediately reports: [OUTBOX] No pending outbox entries to process.
- No magic link email is sent.
- No SMTP traffic appears in the Gmail account’s “Sent” folder.
- No errors or warnings are logged by Ghost for this flow.
Reverting the Ghost image back to 6.26.0 with the same DB and config immediately restores working magic link sign-in.
Question
Is there a known change in 6.27.0 around the members magic-link / outbox pipeline that could cause send-magic-link to return 201 but skip enqueuing an outbox job (e.g., based on member state, settings, or imported data)?
If not, this appears to be a regression between 6.26.0 and 6.27.0 in the magic-link sign-in flow on self-hosted Docker + MySQL, and I’d appreciate guidance on how to debug or confirm this.
After upgrading from Ghost 6.26.0 to 6.27.0, admin/staff login magic link emails are no longer being sent, even though the
send-magic-linkAPI returns201and there are no mail-related errors in the logs. Theprocess-outboxjob runs but reports no pending outbox entries to process. If I roll back to 6.26.0, magic links work immediately with the same database and SMTP config.This looks like a regression in the members/magic-link → outbox pipeline between 6.26.0 and 6.27.0, rather than an SMTP or config issue.
Environment
ghost:6.26.0-alpine(working),ghost:6-alpine(6.27.0, failing)Relevant configuration
docker-compose excerpt (Ghost service):
config.production.jsonmail section (used by both 6.26.0 and 6.27.0):Notes:
/var/lib/ghost/config.production.jsonand verified inside the container.Missing mail.from configwarning was present initially but resolved; it does not appear in 6.27.0 logs anymore.What works (6.26.0)
With
image: ghost:6.26.0-alpine:Start Ghost.
Visit
/blog/admin/, enter a staff user email to log in.Logs show:
Magic link email arrives in the inbox.
The Gmail account used for SMTP also shows the outgoing email in its “Sent” folder.
So in 6.26.0 the magic link flow and SMTP are both working correctly.
What fails (6.27.0)
Switch only the Ghost image to
ghost:6-alpine(6.27.0), keeping the same DB and config:Start Ghost; logs:
Visit
/blog/admin/, enter the same staff email to log in.Logs show:
There are no
EmailError,Failed to send email,EAUTH, or other mail-related errors.No magic link email is received.
The Gmail SMTP account’s “Sent” folder shows no new magic link emails for these attempts.
From the logs it appears that:
send-magic-linkreturns 201.process-outboxfinds no queued jobs.This suggests the magic link flow is not enqueuing an outbox job in 6.27.0, despite returning a success status.
What I’ve already tried
mail.fromand full SMTP settings inconfig.production.json.Missing mail.from configwarning; it no longer appears in 6.27.0.secure: true) and 587 (secure: false) with the same Gmail app password.send-magic-link, outbox, and email; 6.27.0 logs contain no mail-related errors at all.Expected behavior
On 6.27.0:
POST /members/api/send-magic-linkshould:process-outbox.Actual behavior
On 6.27.0:
POST /members/api/send-magic-linkreturns 201.process-outboximmediately reports:[OUTBOX] No pending outbox entries to process.Reverting the Ghost image back to 6.26.0 with the same DB and config immediately restores working magic link sign-in.
Question
Is there a known change in 6.27.0 around the members magic-link / outbox pipeline that could cause
send-magic-linkto return 201 but skip enqueuing an outbox job (e.g., based on member state, settings, or imported data)?If not, this appears to be a regression between 6.26.0 and 6.27.0 in the magic-link sign-in flow on self-hosted Docker + MySQL, and I’d appreciate guidance on how to debug or confirm this.