Connecting to a SMTP server on localhost:25 without auth?

What are the correct settings passed to ./discourse-setup for connecting to an smtp server on localhost:25 without auth?

I’m very surprised that this isn’t supported OOTB; it’s the default config on most linux installs…

My server runs postfix locally; it is not accessible from the Internet. It works fine, for example, when running the mail command. I found a few unofficial guides on the Internet suggesting changes to /var/discourse/containers/app.yml, and I finally got it to install & start with the following settings:

  DISCOURSE_SMTP_ADDRESS: localhost
  DISCOURSE_SMTP_PORT: 25
  DISCOURSE_SMTP_USER_NAME: discourse@opensouceecology.org
  DISCOURSE_SMTP_PASSWORD: "none"
  DISCOURSE_SMTP_AUTHENTICATION: none
  DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: none
  DISCOURSE_SMTP_ENABLE_START_TLS: false

Note that if I omit the DISCOURSE_SMTP_USER_NAME or DISCOURSE_SMTP_PASSWORD variables, your install script yells at me stating that they’re required (bug?).

And now when I click the “Resend Activation Email” button in the Discourse wui, this entry pops-up in the log file (/var/discourse/shared/standalone/log/rails/production.log):

Started PUT "/finish-installation/resend-email" for 127.0.0.1 at 2019-11-07 13:15:31 +0000
Processing by FinishInstallationController#resend_email as HTML
  Parameters: {"authenticity_token"=>"SzQCvRWiqdXsBKzOjIB0X7KkvXro7Od6SdP8Qa8vvrskPeNYZNos5ORHJfyDUrHiKShZR/txM6NHuqHHCQCR1w=="}
  Rendering finish_installation/resend_email.html.erb within layouts/finish_installation
  Rendered finish_installation/resend_email.html.erb within layouts/finish_installation (Duration: 0.7ms | Allocations: 103)
  Rendered layouts/_head.html.erb (Duration: 0.5ms | Allocations: 103)
Completed 200 OK in 98ms (Views: 3.0ms | ActiveRecord: 0.0ms | Allocations: 4763)
  Rendering layouts/email_template.html.erb
  Rendered layouts/email_template.html.erb (Duration: 0.5ms | Allocations: 141)
Delivered mail c4ca58ca-345e-46c4-81bc-6d0eac7afa04@discourse.opensourceecology.org (11.3ms)
Job exception: wrong authentication type none

…But my authentication type is ‘none’. What should the correct setting be for no authentication?

EDIT: also, can someone link me to the doc that defines all of the possible “DISCOURSE_SMTP_*” variables and all of their valid values?

EDIT2: this is proving to be far more difficult than it should be. I think ‘localhost’ is resolving inside the docker container to the Discourse docker container itself (app) – not the docker host that is running my postfix smtp server. That’s further complicated by postfix’s mynetworks and iptables (which were configured by the discourse-setup script or its children scripts). What’s the correct config here to just have Discourse use the smtp server on which I want to run Discourse, with no smtp auth?

1 个赞

I think that hasn’t been very true for about 20 years.

You can’t use discourse-setup for situations like yours because few people have non password protected smtp servers, even behind a firewall.

What I would do is configure smtp passwords for my mail server. There really isn’t much downside.

If you don’t want to do that I think that instead of “none” for authentication you might want “” (and similarly for the password and username).

I think so too. You might try using the container name. I think that you need to see that they are both on the same docker network.

2 个赞

In 2019, it’s the default config for postfix on RHEL/CentOS. Postfix binds only to the loopback interface and drops all smtp requests that don’t originate from 127.0.0.0/8. No auth required. I’m not sure about debian, but I’d imagine exim has a similar default config.

A couple relevant topics on these forums from other users who hit this issue:

There doesn’t appear to be a topic for how to set this up on RHEL/Cent OS with the necessary changes to both Discourse and postfix, so I’m documenting this here.

This does not appear to be possible with the discourse-setup script, but I did get this to work.

First, I had to figure out the IP address of the docker host as the docker container sees it. Using 127.0.0.1 won’t work because the docker container will see 127.0.0.1 as itself. Rather, we need to specify the IP address or hostname of the docker host that is running the postfix SMTP server, and one that is addressible by the docker container (so not your docker host’s Internet-facing IP address if you want your SMTP server to not be Internet-accessible, for example).

I extracted the relevant IP address of the docker host (172.17.0.1) from the docker0 interface by executing this on the docker host:

[maltfield@osestaging1 ~]$ ip address show docker0
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether 02:42:80:35:65:a1 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:80ff:fe35:65a1/64 scope link 
       valid_lft forever preferred_lft forever
[maltfield@osestaging1 ~]$

Then I edited my Discourse app’s yaml file, setting the “DISCOURSE_SMTP_ADDRESS” to 172.17.0.1 from above.

[maltfield@osestaging1 ~]$ cd /var/discourse/
[maltfield@osestaging1 discourse]$ grep SMTP containers/app.yml
  DISCOURSE_SMTP_ADDRESS: 172.17.0.1
  DISCOURSE_SMTP_PORT: 25
  DISCOURSE_SMTP_AUTHENTICATION: none
  DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: none
  DISCOURSE_SMTP_ENABLE_START_TLS: false
[maltfield@osestaging1 discourse]$ 

Note that I first tried to use the internal docker hostname host.docker.internal for this, but apparently this hostname isn’t available to linux docker users

Because the default postfix configuration in RHEL/Cent OS binds only to 127.0.0.1 (which is good), you’ll need to change /etc/postfix/main.cf so it also binds to the docker0 interface and add that subnet to the mynetworks group so that SMTP traffic coming from docker containers will be accepted by postfix.

[maltfield@osestaging1 postfix]$ grep -ir '172.17' /etc/postfix/*
/etc/postfix/main.cf:inet_interfaces = 127.0.0.1, 172.17.0.1
/etc/postfix/main.cf:mynetworks = 127.0.0.0/8, 172.17.0.0/16
[maltfield@osestaging1 postfix]$ 

After those changes, rebuild Discourse and it should now be able to send emails out through your docker host’s postfix.

/var/discourse/launcher rebuild app

While this works, I have a few questions:

  1. Is there some other environment variable or hostname that already points to the docker host (172.17.0.1 in this case)?

I noticed that there is a DISCOURSE_HOST_IP environment variable “injected” by launcher. Is it possible to set this DISCOURSE_SMTP_ADDRESS yaml key to the same value as the other’s yaml key with something like this?

DISCOURSE_SMTP_ADDRESS: $DISCOURSE_HOST_IP
  1. In general, how durable is the 172.17.0.1 IP of the docker host? Is it always this IP on RHEL/Cent OS systems? Will it ever change on me?
3 个赞

@maltfield Just wanted to say thank you for the instructions.

I ran into same issue on Debian… Could create a separate mail user for Discourse I suppose and have it connect and log in to site:465 but connecting to port 25 from the inside is more logical, in my opinion.

And by the way, on Debian 10 with docker.io from the repositories - docker0 is still 172.17.0.1/16.

Maybe you are misunderstanding what @maltfield is saying?

For as long as I can remember (which goes further back than 20 years), Linux ( / Unix / BSD / Solaris) systems have an SMTP server running which is configured by default to be happy to relay anything received from localhost without any questions. This relieves any other application running on that machine from having to worry about and configure SMTP settings themselves.

2 个赞

Yes, most linux servers don’t require auth to send mail (either by default or after installl & configuring). Nor is it necessary if they don’t relay from anywhere but the local network. The default Discourse install scripts won’t work for most servers. It’s designed for a narrow set of docker-based cloud solutions.

You can read my full comprehensive instructions for installing Discourse on a dedicated, baremetal server running RHEL/CentOS 7 on the Open Source Ecology wiki. Note the section on SMTP here:

2 个赞

Well, I almost always defer to you on such matters! I guess it’s been a good number of years since I’ve run an SMTP server on localhost, so it’s a good bet that I don’t know what I’m talking about.

More evidence that I’m wrong! :man_shrugging:

Nice!

But discourse-setup is only ever going to be for people who know virtually nothing about system administration. If you know how to install an SMTP server, you can edit a yml file.

3 个赞

If the host where the container is running has a name you can get via DNS, it works just to specify that:

DISCOURSE_SMTP_ADDRESS: real.machine.example.com

Postfix will still see that the source of the mail is local and handle it that way.

1 个赞

如果 DISCOURSE_HOSTNAMEDISCOURSE_SMTP_ADDRESS 相同,是否会导致问题?

我已经设置了 Docker 主机上的 Postfix 和 Dovecot,以接受 TLS 上的身份验证请求。我的服务器有有效的证书,但无论我尝试哪种配置,都无法让 Discourse 正确地将邮件发送到 Docker 主机上运行的 Postfix。

如果我使用主机名(discourse.[myhost].com),它不起作用(甚至无法连接)。如果我使用 Docker 主机的 IP 地址(172.17.0.1),我会收到

主机名“172.17.0.1”与服务器证书不匹配

显然,我需要使用创建证书时使用的 FQDN。如果我尝试将 DISCOURSE_SMTP_ENABLE_START_TLS 设置为 false,它会提示我需要发出 start TLS 命令。我不想在没有 TLS 的情况下开放 Postfix,所以这对我来说并不是一个可行的选择。

使用外部 SMTP 中继也不是一个选项,因为我不想支付更多费用才能确保电子邮件不会进入人们的垃圾邮件/垃圾邮件文件夹。

我必须说,我对 Docker 网络只有初步的了解,对设置带有 Dovecot 进行身份验证的 Postfix SMTP 服务器的了解更少,但我不是完全的新手,但以安全/可靠的方式进行设置被证明极其困难。

@maltfield 我读了你关于开源生态的文章,但我不希望使用端口 25 上的未身份验证连接。我工作的大学对于使用未加密、未身份验证的通信(即使在本地网络设置中)有非常严格的协议。他们非常担心它会被心怀不满的学生滥用。

1 个赞

所以,我发现使用相同的hostname来运行Discourse服务器和SMTP服务器有些可疑。

进一步调查发现,docker容器在hosts文件中添加了以下条目:

172.17.0.2	discourse.[mydomain].com discourse

因此,任何试图为运行中的容器和docker主机使用相同hostname的尝试都会导致容器发出的所有请求都指向容器本身,而不是docker主机。

真是个惨败!为什么Discourse不在容器中提供默认配置的SMTP服务器!?
或者让不使用Docker也能更容易地使用Discourse!

我在这两个问题上浪费了两天生命。

最后,我接受了无法使用 TLS 与 Docker 主机上运行的 SMTP 进行通信(除非使用不同的主机名获取证书)这一事实。为了最终让它工作起来,我必须确保在 Postfix main.cf 文件中将 172.17.0.0/16 添加到 mynetworks 变量中:

mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.17.0.0/16

这允许 Postfix 将此服务器上运行的任何 Docker 容器视为网络的一部分。

我必须做的另一个更改是确保 smtpd_sasl_security_options 设置为 noanonymous,以防止“陌生人”将 Postfix 用作 SMTP 中继。请确保此处未设置 noplaintext 选项,否则 Postfix 将只允许使用 TLS 进行身份验证。

smtpd_sasl_security_options = noanonymous

有了这些配置设置,我就可以在 app.yml 中指定以下设置:

  DISCOURSE_SMTP_ADDRESS: 172.17.0.1                            # Docker 主机的 IP 地址(从该容器内部可见)
  DISCOURSE_SMTP_PORT: 25
  DISCOURSE_SMTP_USER_NAME: discourse
  DISCOURSE_SMTP_PASSWORD: pa$$word
  DISCOURSE_SMTP_ENABLE_START_TLS: false                         # (可选,默认为 true)
  DISCOURSE_SMTP_DOMAIN: discourse.[mydomian].com                # (某些提供商需要)
  DISCOURSE_NOTIFICATION_EMAIL: noreply@discourse.[mydomain].com # (用于发送通知的地址)

我还为 Docker 主机创建了一个本地用户帐户,仅用于 SASL 身份验证。
通过这些更改,我终于可以从容器发送邮件了,但我总觉得这是一个不理想的配置。理想情况下,应该可以使用所需的 Docker 主机名,并将对 discourse.[mydomain].com 的请求正确路由。

现在我需要设置 SPF 和 DKIM,以便邮件能够进入人们的收件箱(而不是垃圾邮件文件夹)。我非常希望有一天这个痛苦的过程能更加自动化。也许提供一些关于如何在不使用 Docker 的情况下配置 discourse 的说明(例如,可以与 cPanel 一起使用),或者通过在 Docker 容器中提供某种默认的 SMTP 配置来简化邮件设置过程!

2 个赞

如果你回到上世纪90年代初,情况就像你希望的那样。你所谈论的一切都运行正常。但垃圾邮件发送者导致了情况变得更加复杂。这个过程只会变得更加困难,这就是为什么建议使用一些能为你处理许多复杂问题的服务。

2 个赞

很高兴您的邮件设置已成功运行!

昨天以来,邮件故障排除指南有一些更新。如果您仍然对您的邮件设置不满意,不妨再试一次!


可以通过使用以下方法解决:


……只是默认的域名到 IP 的 DNS 解析。

别误会我的意思。我明白 SPF 和 DKIM 的重要性。只是有点烦人。我只希望这些东西能安装在我们现有的 cPanel 服务器上,因为这些东西已经在那里配置好了。

1 个赞

这正是我缺少的。现在使用 TLS 可以正常工作了。

我还启用了 DKIM,所以邮件应该不会再被标记为垃圾邮件了。

2 个赞