Docs / Discourse

Configure Discourse email over SMTP

Discourse leans on email more than most apps: account confirmations, notifications, summary digests and, if you enable it, mailing list mode. A self-hosted Docker install ships no mail server of its own, so it needs an SMTP relay — configured in app.yml, not in the admin panel.

✓
You can get them on the token management page. For security reasons, a token is shown only once — at the moment it is created.

SMTP connection settings

SettingValue
SMTP hostsmtp.postwing.app
Port587
EncryptionSTARTTLS (the connection is upgraded to TLS before login)
UsernameThe login of an SMTP token for your domain
PasswordThe password of that token — shown once, when the token is created
ℹ
Every mode is also available on a high port: 8465 (SSL/TLS), 8587 (STARTTLS) and 8025 (plain). Many hosting providers and clouds block outbound 25, 465 and 587 — if the connection times out, switch to the matching high port.

Edit app.yml

Open /var/discourse/containers/app.yml and set these variables in the env: section — the sample file already has most of them, some commented out:

containers/app.yml
# /var/discourse/containers/app.yml — inside the env: section
env:
  # ...
  DISCOURSE_SMTP_ADDRESS: smtp.postwing.app
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: token-login@your-domain.com
  DISCOURSE_SMTP_PASSWORD: "your-token-password"   # keep the quotes
  DISCOURSE_SMTP_ENABLE_START_TLS: true            # the default, shown for clarity
  DISCOURSE_NOTIFICATION_EMAIL: noreply@your-domain.com
⚠
app.yml is YAML: a # in an unquoted value starts a comment and silently truncates the password. Keep it in double quotes.

If you need port 465 instead, change the port and swap the TLS mode:

# Port 465 (implicit TLS) instead of 587
  DISCOURSE_SMTP_PORT: 465
  DISCOURSE_SMTP_FORCE_TLS: true
  DISCOURSE_SMTP_ENABLE_START_TLS: false

Rebuild the container

Changes to app.yml take effect only after a rebuild, which takes a few minutes:

bash
cd /var/discourse
./launcher rebuild app

Send a test email

In the admin panel, open Email settings → Server settings (/admin/email/server-settings on current versions), enter an address and press Send test email. Email logs (/admin/email-logs) then shows every message under Sent, Skipped and Bounced. From the server, the bundled doctor script checks the configuration and offers to send a test message:

bash
cd /var/discourse
./discourse-doctor

Troubleshooting

ErrorCause and fix
Net::OpenTimeout Outbound port blocked — set DISCOURSE_SMTP_PORT to 8587, or 8465 with the port 465 settings.
SSL_connect ... wrong version number TLS mode does not match the port. 587 needs STARTTLS; 465 needs FORCE_TLS.
535 Authentication failedWrong token login or password — check the quoting too.
Edited app.yml, nothing changedThe container was not rebuilt.
Test works, signup emails go to spamnotification_email is not on your verified domain.
Messages listed under Skipped Discourse chose not to send them (user preferences, suppressed address). The Skip reason column says which.

Frequently asked questions

Where do I change SMTP settings in Discourse?

On a standard Docker install they live in /var/discourse/containers/app.yml as DISCOURSE_SMTP_* variables, not in the admin panel. The ./discourse-setup installer writes them there the first time; to change them later, edit the file and run ./launcher rebuild app.

Do I need to rebuild Discourse after changing app.yml?

Yes. The container reads app.yml only when it is built, so an edit does nothing until you run ./launcher rebuild app from /var/discourse. Expect a few minutes of downtime while it rebuilds.

Should Discourse use port 587 or 465?

587 with STARTTLS, which is Discourse's default behaviour — you only set the port. For 465, also set DISCOURSE_SMTP_FORCE_TLS: true and DISCOURSE_SMTP_ENABLE_START_TLS: false; otherwise the connection fails with an SSL 'wrong version number' error.

Which address do Discourse emails come from?

The notification_email site setting, which DISCOURSE_NOTIFICATION_EMAIL sets. It is used for all essential system mail, so it has to be on the domain you verified — otherwise DKIM and SPF do not align and signup confirmations land in spam.

Does Discourse need SMTP at all?

Recent installers let you skip it and have people log in with Discourse ID instead. Email digests, mailing list mode and replying by email still need SMTP, and so does classic email signup.

Why does Discourse fail to parse my SMTP password?

app.yml is YAML: a # starts a comment and some characters break parsing unless the value is quoted. Wrap DISCOURSE_SMTP_PASSWORD in double quotes, as the sample file does.

Next steps