# Failing to setup SMTP

**URL:** <https://forum.ghost.org/t/failing-to-setup-smtp/35562>\
**Category:** Developer help\
**Created:** [January 15, 2023, 9:48am UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562 "2023-01-15T09:48:04Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![Aleklu](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/aleklu/32/22249_2.png) [@Aleklu](https://forum.ghost.org/u/Aleklu)\
**Post date:** [January 15, 2023, 9:48am UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/1 "2023-01-15T09:48:04Z")

</div>

Hi everyone,

I am struggling to get the SMTP setup working for my self hosted Ghost installation. All the things I tried so far ended with “Failed to send magic link email” in Portal and “Failed to send email. Reason: Invalid login: 535 Authentication failed.” in the logs.

My knowledge leaves a lot to be desired, but maybe someone could help me still.

_My setup:_  
Running Ghost on my own hardware on top of Unraid. I am using the official Ghost Docker image available on Unraid. I am using Cloudflare for my domains, DNS und SSL. I also have to fight with a dynamic IP, so my router talks to Cloudflare in the background - Cloudflare provides my SSL cert. I am using NGINX Proxy Manager, again on Unraid, to proxy my host to the domain known to Cloudflare. For both mass mails and transactional mails I am trying to get Mailgun working following the official docs. (I hope I used some of the correct words here.^^)

Ghost-CLI version: 1.24.0  
Ghost version: 5.30.0 (at /var/lib/ghost)

_Current open questions:_

- Where can I find config.production.json? My current very limited understanding is that _something_ is cobbling together Ghost core during runtime. I can see both config.development.json and config.production.json and more with a “ls” in the console of the docker image. But for the life of me I cant find the “actual file” to edit.
  - I think I understood correctly that I can just put a config.production.json in the root and it’ll override settings. But this does not seem to work in the /appdata/ghost folder, which is the only Ghost root I can see in Unraids file system. Should this work? Do I have a complete misunderstanding here? Where is root and the files?
  - (Adjacent question - I managed to create a DE.json and place the translation handlebar in a copy of one of the default themes. Works good. How can I translate Core and/or Portal? Some content is missing from the theme but would need translation anyway. And again: where are the files? I read in some forum post here that core translation is on the roadmap - wait for progress or learn to do it myself?)

- Assumed the root mentioned above actually is the correct root, is anything wrong with my config below?

```auto
"mail": {
	"transport": "SMTP",
	"options": {
		"service": "Mailgun",
		"host": "smtp.eu.mailgun.org",
		"port": 465,
		"secureConnection": true,
		"auth": {
			"user": "USER@mg.MYDOMAIN.XYZ",
			"pass": "PW DEFINED IN MAILGUN SMTP CREDENTIALS"
		}
	}
},

```

- I tried many many iterations of this config. “secureConnection” true/false, “SecureConnection” renamed to “Secure”, port 465 & 587, host with “EU” and without. Nothing changed the error message in any way - leads me back to Ghost ignoring this config completely.

Any other troubleshoot steps you would recommend? Thanks a million in advance!

---

<div class="post-metadata">

**Author:** ![Aleklu](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/aleklu/32/22249_2.png) [@Aleklu](https://forum.ghost.org/u/Aleklu)\
**Post date:** [January 15, 2023, 9:55am UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/2 "2023-01-15T09:55:13Z")

</div>

EDIT: Mass mailing works - I just tried to send a newsletter to myself. That’s great, at least this part of the Mailgun integration is good for me.

Now, how to diagnose and troubleshoot the SMTP stuff…

---

<div class="post-metadata">

**Author:** ![mjw](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/mjw/32/30781_2.png) [@mjw](https://forum.ghost.org/u/mjw)\
**Post date:** [January 15, 2023, 4:20pm UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/3 "2023-01-15T16:20:15Z")

</div>

Whilst `config.production.json` is used when setting up SMTP for a standard installation, Docker does it differently.

You need to supply environment variables using docker-compose, e.g., `mail__transport=SMTP`.

[https://hub.docker.com/\_/ghost](https://hub.docker.com/_/ghost)

---

<div class="post-metadata">

**Author:** ![Aleklu](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/aleklu/32/22249_2.png) [@Aleklu](https://forum.ghost.org/u/Aleklu)\
**Post date:** [January 15, 2023, 9:33pm UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/4 "2023-01-15T21:33:16Z")

</div>

Thanks for the pointer. I now created several more environment variables that seem to work. I also, for testing, set up gMail as the SMTP sender and this worked - but only after I left the variables for “host” and “port” empty. Seems like Nodemailer (?) is picking all this up automagically when “service: gmail” is set.

While looking at this I also found [Proxy support :: Nodemailer](https://nodemailer.com/smtp/proxies/) - my Ghost installation IS behind a proxy, NGINX proxy manager. I guess I somehow need to tell Nodemailer that it sits behind a proxy. I don’t really know if this is also done via the docker env variables of Ghost. And the Nodemailer help site linked is currently overwhelming me.

Oh well, more to learn next week. Any additional pointers would still be much appreciated.

EDIT: In case this is helpful - I followed this tutorial to get to where I am: [Self-Hosting a Blog with Ghost and Unraid](https://christiansibo.com/self-hosting-a-blog-with-ghost-and-unraid/).

---

<div class="post-metadata">

**Author:** ![Aleklu](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/aleklu/32/22249_2.png) [@Aleklu](https://forum.ghost.org/u/Aleklu)\
**Post date:** [January 16, 2023, 8:46am UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/5 "2023-01-16T08:46:43Z")

</div>

I could verify with telnet that my Mailgun SMTP credentials in fact DO work, at least via telnet on ports 25 and 587.

So I tried to mirror my telnet input in the env variables as so:

```auto
mail__transport "SMTP"
mail __options__ service "Mailgun"
mail __options__ auth__user "My Mailgun SMTP user"
mail __options__ auth__pass "My Mailgun SMTP pw" OR "My Mailgun SMTP pw in BASE64"
mail_options_port "587"
mail_options_secure "false"
mail_options_host "smtp.eu.mailgun.org"
mail_options_auth_type "auth login" OR "login" OR ""

```

When setting up the env variables as described I still get

```auto
Failed to send email. Reason: Invalid login: 535 Authentication failed.

"Please see https://ghost.org/docs/config/#mail for instructions on configuring email."

Error ID:
    3fd839b0-9579-11ed-a8a0-bfb98a8f37af

Error Code: 
    EAUTH

----------------------------------------

Error: Invalid login: 535 Authentication failed
    at createMailError (/var/lib/ghost/versions/5.30.0/core/server/services/mail/GhostMailer.js:68:12)
    at SMTPConnection._formatError (/var/lib/ghost/versions/5.30.0/node_modules/nodemailer/lib/smtp-connection/index.js:790:19)
    at SMTPConnection._actionAUTHComplete (/var/lib/ghost/versions/5.30.0/node_modules/nodemailer/lib/smtp-connection/index.js:1542:34)
    at SMTPConnection.<anonymous> (/var/lib/ghost/versions/5.30.0/node_modules/nodemailer/lib/smtp-connection/index.js:546:26)
    at SMTPConnection._processResponse (/var/lib/ghost/versions/5.30.0/node_modules/nodemailer/lib/smtp-connection/index.js:953:20)
    at SMTPConnection._onData (/var/lib/ghost/versions/5.30.0/node_modules/nodemailer/lib/smtp-connection/index.js:755:14)
    at TLSSocket.SMTPConnection._onSocketData (/var/lib/ghost/versions/5.30.0/node_modules/nodemailer/lib/smtp-connection/index.js:193:44)
    at TLSSocket.emit (node:events:513:28)
    at addChunk (node:internal/streams/readable:315:12)
    at readableAddChunk (node:internal/streams/readable:289:9)
    at TLSSocket.Readable.push (node:internal/streams/readable:228:10)
    at TLSWrap.onStreamRead (node:internal/stream_base_commons:190:23)

```

So it looks like something gets malformed between env variables and Ghost talking to Mailgun. Any additional ideas would be lovely.

---

<div class="post-metadata">

**Author:** ![thimiraonline](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/thimiraonline/32/22599_2.png) [@thimiraonline](https://forum.ghost.org/u/thimiraonline)\
**Post date:** [January 16, 2023, 11:07am UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/6 "2023-01-16T11:07:20Z")

</div>

Try this configuration. This is what I am using for my website’s SMTP in config.production.json file.

```auto
  "mail": {
    "transport": "SMTP",
    "options": {
      "service": "Mailgun",
      "host": "smtp.mailgun.org",
      "port": 587,
      "secure": false,
      "auth": {
        "user": "user address",
        "pass": "password"
      }
    }
  },

```

---

<div class="post-metadata">

**Author:** ![Aleklu](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/aleklu/32/22249_2.png) [@Aleklu](https://forum.ghost.org/u/Aleklu)\
**Post date:** [January 16, 2023, 11:38am UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/7 "2023-01-16T11:38:18Z")

</div>

Unfortunately does not work either.

My current config

 ![Bildschirm­foto 2023-01-16 um 12.28.24](https://us1.discourse-cdn.com/flex015/uploads/ghost2/original/3X/d/a/da1d9e55a0a9b334cbfc15edcec78563b4228568.jpeg)

I tried this and many iterations of it.

---

<div class="post-metadata">

**Author:** ![markstos](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/markstos/32/18182_2.png) [@markstos](https://forum.ghost.org/u/markstos)\
**Post date:** [January 16, 2023, 1:25pm UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/8 "2023-01-16T13:25:17Z")

</div>

For config options that would be nested in JSON, you need to separate the config keys with two underscores, but some of your config keys here use a single underscore, which won’t work.

> **[Configuration - Adapt your publication to suit your needs](https://ghost.org/docs/config/#running-ghost-with-config-env-variables)**
>
> Find out how to configure your Ghost publication or override Ghost's default behaviour with robust config options, including mail, storage, scheduling and more!

Also, if you are going to try quoting them, quote the whole string, ex: ‘mail\_\_logger=’

---

<div class="post-metadata">

**Author:** ![Aleklu](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/aleklu/32/22249_2.png) [@Aleklu](https://forum.ghost.org/u/Aleklu)\
**Post date:** [January 16, 2023, 3:24pm UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/9 "2023-01-16T15:24:06Z")

</div>

Thanks, that brought me a step further - I am getting a different error message now.

```auto
[2023-01-16 14:37:22] ERROR "POST /members/api/send-magic-link/" 500 48ms

Failed to send email. Reason: connect ECONNREFUSED 127.0.0.1:587.

"Please see https://ghost.org/docs/config/#mail for instructions on configuring email."

Error ID:
    498a4ca0-95ab-11ed-83ee-1f539c442ef4

Error Code: 
    ESOCKET

----------------------------------------

Error: connect ECONNREFUSED 127.0.0.1:587
    at createMailError (/var/lib/ghost/versions/5.30.0/core/server/services/mail/GhostMailer.js:68:12)
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1278:16)

```

I omitted almost everything from my env variables now:

```auto
-e 'mail__transport'='SMTP'
  -e 'mail __options__ service'='Mailgun'
  -e 'mail __options__ auth__user'='USER@mg.MYDOMAIN.XYZ'
  -e 'mail __options__ auth__pass'='USERS PASSWORD FROM MAILGUN'

```

The 127.0.0.1 in the error message now seems curious. One the one hand: [No email setup in Ghost? - Reclaim Cloud - Reclaim Hosting Community Forums](https://forums.reclaimhosting.com/t/no-email-setup-in-ghost/4363)

> I’ve updated and tested our installer to work better with email setups other than Mailgun. Ghost has a built-in fallback email option called “direct email” via the Nodemailer package it uses internally, and in my testing it doesn’t seem to work in Docker based setups.

But there the recommendation is to use Mailgun as external SMTP server, which is exactly what I am trying to do in the first place.

---

<div class="post-metadata">

**Author:** ![mjw](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/mjw/32/30781_2.png) [@mjw](https://forum.ghost.org/u/mjw)\
**Post date:** [January 16, 2023, 3:31pm UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/10 "2023-01-16T15:31:38Z")

</div>

You need to add RequireTLS as an environment variable. But double check syntax as I’m on mobile, so haven’t checked.

Additionally, Nginx is proxying HTTP and HTTPS, so won’t impact mail delivery.

---

<div class="post-metadata">

**Author:** ![Aleklu](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/aleklu/32/22249_2.png) [@Aleklu](https://forum.ghost.org/u/Aleklu)\
**Post date:** [January 16, 2023, 4:26pm UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/11 "2023-01-16T16:26:55Z")

</div>

Once more thanks for the input. It didn’t change the results unfortunately.

This config - which gets loaded correctly -

```auto
  -e 'mail__transport'='SMTP'
  -e 'mail __options__ service'='Mailgun'
  -e 'mail __options__ auth__user'='User@mg.MYDOMAIN.xyz'
  -e 'mail __options__ auth__pass'='Mailgun User PW'
  -e 'mail __options__ port'=''
  -e 'mail __options__ secure'='true'
  -e 'mail __options__ host'=''
  -e 'mail __options__ requireTLS'='true'

```

as well as false-false, true-false and false-true for _secure_ and _requireTLS_ also lead to the same result:

```auto
[2023-01-16 16:20:21] ERROR "POST /members/api/send-magic-link/" 500 122ms

Failed to send email. Reason: connect ECONNREFUSED 127.0.0.1:465.

"Please see https://ghost.org/docs/config/#mail for instructions on configuring email."

Error ID:
    acdb3950-95b9-11ed-b2e0-33769715db9a

Error Code: 
    ESOCKET

----------------------------------------

Error: connect ECONNREFUSED 127.0.0.1:465
    at createMailError (/var/lib/ghost/versions/5.30.0/core/server/services/mail/GhostMailer.js:68:12)
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1278:16)

```

(same result on port 587 when _secure = false_).

Once again for your help and input, sorry for being annoying.

---

<div class="post-metadata">

**Author:** ![mjw](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/mjw/32/30781_2.png) [@mjw](https://forum.ghost.org/u/mjw)\
**Post date:** [January 16, 2023, 4:35pm UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/12 "2023-01-16T16:35:17Z")

</div>

Secure needs to be false; TLS starts the negotiation using plain text.

Are you using the key from Mailgun as the password (only displayed when setting up?)

---

<div class="post-metadata">

**Author:** ![markstos](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/markstos/32/18182_2.png) [@markstos](https://forum.ghost.org/u/markstos)\
**Post date:** [January 16, 2023, 4:36pm UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/13 "2023-01-16T16:36:24Z")

</div>

Your host value is empty, so it’s trying to connect to port 465 on your localhost.

---

<div class="post-metadata">

**Author:** ![mjw](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/mjw/32/30781_2.png) [@mjw](https://forum.ghost.org/u/mjw)\
**Post date:** [January 16, 2023, 4:38pm UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/14 "2023-01-16T16:38:05Z")

</div>

Good spot; this should resolve it.

Port and host must be populated.

---

<div class="post-metadata">

**Author:** ![Aleklu](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/aleklu/32/22249_2.png) [@Aleklu](https://forum.ghost.org/u/Aleklu)\
**Post date:** [January 16, 2023, 4:45pm UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/15 "2023-01-16T16:45:22Z")

</div>

If it only would be so easy - but no, now I have come full circle. Error:

```auto
Failed to send email. Reason: Invalid login: 535 Authentication failed.

"Please see https://ghost.org/docs/config/#mail for instructions on configuring email."

Error ID:
    680c24d0-95bc-11ed-b4ef-abbf45b7ddda

Error Code: 
    EAUTH

----------------------------------------

Error: Invalid login: 535 Authentication failed
    at createMailError (/var/lib/ghost/versions/5.30.0/core/server/services/mail/GhostMailer.js:68:12)
    at SMTPConnection._formatError (/var/lib/ghost/versions/5.30.0/node_modules/nodemailer/lib/smtp-connection/index.js:790:19)
    at SMTPConnection._actionAUTHComplete (/var/lib/ghost/versions/5.30.0/node_modules/nodemailer/lib/smtp-connection/index.js:1542:34)
    at SMTPConnection.<anonymous> (/var/lib/ghost/versions/5.30.0/node_modules/nodemailer/lib/smtp-connection/index.js:546:26)
    at SMTPConnection._processResponse (/var/lib/ghost/versions/5.30.0/node_modules/nodemailer/lib/smtp-connection/index.js:953:20)
    at SMTPConnection._onData (/var/lib/ghost/versions/5.30.0/node_modules/nodemailer/lib/smtp-connection/index.js:755:14)
    at TLSSocket.SMTPConnection._onSocketData (/var/lib/ghost/versions/5.30.0/node_modules/nodemailer/lib/smtp-connection/index.js:193:44)
    at TLSSocket.emit (node:events:513:28)
    at addChunk (node:internal/streams/readable:315:12)
    at readableAddChunk (node:internal/streams/readable:289:9)
    at TLSSocket.Readable.push (node:internal/streams/readable:228:10)
    at TLSWrap.onStreamRead (node:internal/stream_base_commons:190:23)

```

Config (tried port empty - default set depending on _secure_ state; port=587 and port=465):

```auto
  -e 'mail__transport'='SMTP'
  -e 'mail __options__ service'='Mailgun'
  -e 'mail __options__ auth__user'='USER@mg.MYDOMAIN.xyz'
  -e 'mail __options__ auth__pass'='MAILGUN USER PW'
  -e 'mail __options__ port'=''
  -e 'mail __options__ secure'='false'
  -e 'mail __options__ host'='smtp.eu.mailgun.org'
  -e 'mail __options__ requireTLS'='true'

```

And keep in mind - those credentials DO work in telnet with 587 (AFAIK telnet out of the box does not do SSL, hence 465 does not work in telnet).

I am really out of my depths here…^^

---

<div class="post-metadata">

**Author:** ![Aleklu](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/aleklu/32/22249_2.png) [@Aleklu](https://forum.ghost.org/u/Aleklu)\
**Post date:** [January 16, 2023, 5:11pm UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/16 "2023-01-16T17:11:26Z")

</div>

Wohoo… great success. Sort of.

I think this is what happened:

Mailgun recommends during domain setup to setup a subdomain for Mailgun, e.g. `mg.mydomain.com`. I did so.

Because my SSL certs from Cloudflare only cover ONE level of subdomains for free, `email.mg.mydomain.com` was out of scope for the cert.

Hence I was unable to connect to Mailgun via SMTP. Somehow. I guess. I would be lying if I said I understand what’s going on.

I now created a new domain in Mailgun that omits the subdomain, so `mydomain.com`. After setting up all the needed DNS entries my sites portal now can send emails.

Yay.

I somehow feel not satisfied because I didn’t really fix it, but alas. Sidestepping is good enough, I think.

---

<div class="post-metadata">

**Author:** ![mjw](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/mjw/32/30781_2.png) [@mjw](https://forum.ghost.org/u/mjw)\
**Post date:** [January 16, 2023, 5:17pm UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/17 "2023-01-16T17:17:10Z")

</div>

Your MX records should be something like mg.your.domain, and optionally a CNAME for email.mg.your.domain for tracking.

If your MX records were email.mg.your.domain, that would explain the error. However, Mailgun usually validates the domain in the control panel.

---

<div class="post-metadata">

**Author:** ![Aleklu](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/aleklu/32/22249_2.png) [@Aleklu](https://forum.ghost.org/u/Aleklu)\
**Post date:** [January 16, 2023, 5:21pm UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/18 "2023-01-16T17:21:02Z")

</div>

I set them up correctly with the `mg.mydomain.com` subdomain - both MX pointed to `mg.mydomain.com`, not `email.mg.mydomain.com`. As you say, the CNAME was the only one pointing to `email.gm. ...`. I checked a million times. (And all but the CNAME also had the verified badge. The CNAME shows unverified in Mailgun, and also in Cloudflare with the note that its not covered by my certificates.)

So if it was not that then I don’t know. I changed nothing in my config but the new credentials for the new Mailgun domain, omitting the subdomain. I would be really curious to understand what the error was/is.

---

<div class="post-metadata">

**Author:** ![mjw](https://sea1.discourse-cdn.com/flex015/user_avatar/forum.ghost.org/mjw/32/30781_2.png) [@mjw](https://forum.ghost.org/u/mjw)\
**Post date:** [December 5, 2023, 10:38am UTC](https://forum.ghost.org/t/failing-to-setup-smtp/35562/20 "2023-12-05T10:38:07Z")

</div>


