Cannot send email after migrating to Docker (Ghost 6.0.3)

After migrating from CLI to the Docker image, I thought all was fine, but I don’t seem to be able to send emails (specifically, inviting Admins).

I use Protonmail’s services as my SMTP server. It’s always worked in the past just fine on the CLI version of Ghost. I’ve verified that I am able to connect to Protonmail’s SMTP server on port 587.

Mailgun is set up too, but from my understanding, that’s not relevant here.

Here are the relevant settings in the .env, and the log files when I attempt to resend an invite:

mail__transport=SMTP
mail__options__host=smtp.protonmail.ch
mail__options__port=587
mail__options__secure=false
mail__options__auth__user=admin@xxxxxxx.xxx
mail__options__auth__pass=XXXXXXXXXXXXXXXX

ghost-1 | [2025-08-15 22:34:38] WARN Error sending email: Failed to send email. Reason: Sending failed. Please check your email settings and resend the invitation.
ghost-1 | [2025-08-15 22:34:38] ERROR “POST /ghost/api/admin/invites/” 500 840ms
ghost-1 |
ghost-1 | Error sending email: Failed to send email. Reason: Sending failed. Please check your email settings and resend the invitation.
ghost-1 |
ghost-1 | “Please see Configuration - Ghost Developer Docs for instructions on configuring email.”
ghost-1 |
ghost-1 | Error ID:
ghost-1 | 070e65f0-7a28-11f0-92e0-7be8b2ef36af
ghost-1 |
ghost-1 | ----------------------------------------
ghost-1 |
ghost-1 | Error: Sending failed
ghost-1 | at createMailError (/var/lib/ghost/versions/6.0.3/core/server/services/mail/GhostMailer.js:81:12)
ghost-1 | at DirectMailer. (/var/lib/ghost/versions/6.0.3/node_modules/nodemailer-direct-transport/lib/direct-transport.js:157:41)
ghost-1 | at DirectMailer. (/var/lib/ghost/versions/6.0.3/node_modules/nodemailer-direct-transport/lib/direct-transport.js:228:30)
ghost-1 | at /var/lib/ghost/versions/6.0.3/node_modules/nodemailer-direct-transport/lib/direct-transport.js:350:28
ghost-1 | at callback (/var/lib/ghost/versions/6.0.3/node_modules/smtp-connection/lib/smtp-connection.js:374:14)
ghost-1 | at SMTPConnection. (/var/lib/ghost/versions/6.0.3/node_modules/smtp-connection/lib/smtp-connection.js:385:20)
ghost-1 | at SMTPConnection._actionMAIL (/var/lib/ghost/versions/6.0.3/node_modules/smtp-connection/lib/smtp-connection.js:1252:16)
ghost-1 | at SMTPConnection. (/var/lib/ghost/versions/6.0.3/node_modules/smtp-connection/lib/smtp-connection.js:759:14)
ghost-1 | at SMTPConnection._processResponse (/var/lib/ghost/versions/6.0.3/node_modules/smtp-connection/lib/smtp-connection.js:669:16)
ghost-1 | at SMTPConnection._onData (/var/lib/ghost/versions/6.0.3/node_modules/smtp-connection/lib/smtp-connection.js:493:10)
ghost-1 | at Socket.emit (node:events:518:28)
ghost-1 | at addChunk (node:internal/streams/readable:561:12)
ghost-1 | at readableAddChunkPushByteMode (node:internal/streams/readable:512:3)
ghost-1 | at Readable.push (node:internal/streams/readable:392:5)
ghost-1 | at TCP.onStreamRead (node:internal/stream_base_commons:189:23)

Edit:

I left out some additional things in the .env:

Configuration imported from existing Ghost install at /var/www/xxxxxxxxx

mail__from=“‘xxxxxxxx.xxx’ admin@xxxxxxx.xxx
mail__transport=Direct
mail__options__host=smtp.protonmail.ch
mail__options__port=587
mail__options__secureConnection=true
mail__options__ignoreTLS=true
mail__options__auth__user=admin@xxxxxx.xxx
mail__options__auth__pass=XXXXXXXXXXXXXXXX
security__staffDeviceVerification=true

Some of these variables seem to be duplicated in the .env file. Is that a problem?

In addition, I’ve been trying combinations true/false when it comes to TLS and secure connections, and one of the errors in one of those combinations resulted in:

Error sending email: Failed to send email. Reason: Email has been temporarily rejected. Please check your email settings and resend the invitation.

A different error than ‘Sending failed’…

Can you post the entire env file (removing any secrets)?

Duplicate keys would overwrite each other, e.g. the last ones would be the ones that are “relevant”. Make sure you only have unique properties in there.

Hi Jannis - here’s the entire .env below:

#Use the below flags to enable the Analytics or ActivityPub containers as well
#COMPOSE_PROFILES=analytics,activitypub
#COMPOSE_PROFILES=activitypub

# Ghost domain

# Custom public domain Ghost will run on

DOMAIN=xxxxxxxxx.xxx

# Ghost Admin domain

# If you have Ghost Admin setup on a separate domain uncomment the line below and add the domain

# You also need to uncomment the corresponding block in your Caddyfile

# ADMIN_DOMAIN=

# Database settings

# All database settings must not be changed once the database is initialised

DATABASE_ROOT_PASSWORD=

# DATABASE_USER=optionalusername

DATABASE_PASSWORD=

# ActivityPub

# If you’d prefer to self-host ActivityPub yourself uncomment the line below

#ACTIVITYPUB_TARGET=activitypub:8080

# Tinybird configuration

# If you want to run Analytics, paste the output from `docker compose run --rm tinybird-login get-tokens` below

# TINYBIRD_API_URL=https://api.tinybird.co

# TINYBIRD_TRACKER_TOKEN=p.eyJxxxxx

# TINYBIRD_ADMIN_TOKEN=p.eyJxxxxx

# TINYBIRD_WORKSPACE_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

# Ghost configuration (https://ghost.org/docs/config/)

# SMTP Email (https://ghost.org/docs/config/#mail)

# Transactional email is required for logins, account creation (staff invites), password resets and other features

# This is not related to bulk mail / newsletter sending

mail__transport=SMTP
mail__options__host=smtp.protonmail.ch
mail__options__port=587
mail__options__secure=false
mail__options__auth__user=xxxxx@xxxxxxxxx.xxx
mail__options__auth__pass=XXXXXXXXXXXXXXXX

# Advanced customizations

# Force Ghost version

# You should only do this if you need to pin a specific version

# The update commands won’t work

# GHOST_VERSION=6-alpine

# Port Ghost should listen on

# You should only need to edit this if you want to host

# multiple sites on the same server

# GHOST_PORT=2368

# Data locations

# Location to store uploaded data

UPLOAD_LOCATION=./data/ghost

# Location for database data

MYSQL_DATA_LOCATION=./data/mysql

# Configuration imported from existing Ghost install at /var/www/xxxxxxxxx

mail__from=“‘xxxxxxxxx.xxx’ <admin@xxxxxxxxx.xxx>”
mail__transport=Direct
mail__options__host=smtp.protonmail.ch
mail__options__port=587
mail__options__secureConnection=false
mail__options__ignoreTLS=true
mail__options__auth__user=xxxxx@xxxxxxxxx.xxx
mail__options__auth__pass=XXXXXXXXXXXXXXXX
security__staffDeviceVerification=true

Fixed. Commenting out all of the ‘imported’ configuration, except for

mail__from=“‘xxxxxxxxx.xxx’ admin@xxxxxxxxx.xxx

allowed the email to be sent.

1 Like

The exact problem seems to be because the transport was “direct” (meaning it would try to use the system mailer) instead of “smtp”

2 Likes

Appreciate the reply, and thanks for fixing my .env file output!

1 Like