SMTP 邮件无法发送且连接失败,但 openssl 正常工作

您好!如果这个问题已经有明确的解决方案,我很抱歉;我确实到处查找了,但没有找到解决我问题的明确方案。

所以,我自行托管了一个 Discord 实例,经过一些调整后,我获得了正确的 SMTP 配置,但发送给新用户的邮件没有发送(甚至没有发送给初始管理员用户;我最终通过容器内的 rake 命令创建了一个)。

起初,我以为由于一些 DNS 问题,它无法连接到 SMTP,因为当我尝试使用 ./discourse-doctor 并最终进入容器 shell 时,它会返回:

Testing sending to xxxx@gmail.com using smtp-relay.brevo.com:587, username:xxxxxxx@smtp-brevo.com with plain auth.
======================================== ERROR ========================================
Connection to port 587 failed.
====================================== SOLUTION =======================================
The most likely problem is that your server has outgoing SMTP traffic blocked.
If you are using a service like Mailgun or Sendgrid, try using port 2525.
=======================================================================================

然而,在 SMTP 故障排除指南 中推荐的 openssl 命令不仅连接成功了,而且我还可以使用 EHLO、AUTH LOGIN 以及所有这些命令(我直到现在才知道它们的存在,呵呵 ^^'),从容器内部向自己发送测试邮件。所以我认为问题不在于容器无法连接到 SMTP 服务器。

为清晰起见进行编辑
在容器内完成了这个操作:我使用 ./launcher enter container 命令登录到容器。在该提示符下,我执行了之前的命令。

如果对您有帮助,以下是我的 SMTP 设置。当然,我已经编辑掉了登录信息。

  DISCOURSE_SMTP_ADDRESS: 'smtp-relay.brevo.com'
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: 'xxxxxxxx@smtp-brevo.com'
  DISCOURSE_SMTP_PASSWORD: 'xxxxxxxxxxxx'
  #DISCOURSE_SMTP_ENABLE_START_TLS: true           # (optional, default true)
  #DISCOURSE_SMTP_DOMAIN: discourse.example.com    # (required by some providers)
  DISCOURSE_NOTIFICATION_EMAIL: 'noreply@mydomain.xyz'    # (address to send notifications from)
  #DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: none

通知邮件是我通过 openssl 命令测试的邮件,最后一行是我在另一个帖子中看到的,并添加了它,但将其注释掉了,并且从未尝试过,因为它是一个旧帖子。

总之,我在这里真的感到很迷茫,希望有人能帮我一把,如果这是一个我已经解决但没有找到的问题,我真的很抱歉!

您能否尝试一下错误提示的建议,看看是否能侥幸成功?

2 个赞

您好!我已经试过了,但没用 :frowning:

确实能够通过 openssl 发送测试邮件,但使用的是 587 端口。然而,通过 Discourse 界面(无论是通过 GUI 中的测试邮件按钮还是 rake tests:email[mail] 命令),我都无法发送成功,无论是通过 287 端口还是 2525 端口。

另外,我发现了关于未发送邮件的 sidekiq 错误:

Jobs::HandledExceptionWrapper: Wrapped Net::OpenTimeout: execution expired

Found the shared/standalone/log/rails/production.log relevant lines:

Started POST "/admin/email/test" for 192.168.0.206 at 2024-10-18 23:49:02 +0000
Processing by Admin::EmailController#test as */*
  Parameters: {"email_address"=>"jggalindez@gmail.com"}
Completed 422 Unprocessable Entity in 5201ms (Views: 0.4ms | ActiveRecord: 0.0ms | Allocations: 12487)

从容器内部能够连接到端口 587 吗?

听起来您从主机可以连接到端口 587,但您可能无法从容器内部连接,这意味着您的服务器存在网络问题。

2 个赞

您好!抱歉,我之前说得不太清楚。据我所知,我能够从容器内部连接到端口 587,因为我执行了以下操作:

  • 我使用 ./launcher enter containername 登录到容器。
  • 从容器内部,我运行了 openssl 命令。
  • 从伪 telnet 提示符(我不确定它到底是什么)中,我使用 SMTP 服务器进行了身份验证(完成了将用户名和密码转换为 base64 的操作)并发送了一封电子邮件。

我实际上并没有尝试从服务器内部发送电子邮件。只是从容器内部(据我理解)发送,但我认为如果它能够从容器内部发送,那么它也应该能够从服务器内部发送。

所以,我搞定了。看起来确实是 DNS 问题(因为在使用 getentopenssl 命令时它能够解析 url)。所以我运行了 getent 来获取 SMTP 中继的主机 IP,然后更改服务器地址为原始 IP 来运行容器。这导致了另一个错误,这个帖子里的那个。那里指出的解决方案,在 yaml 文件中添加一行 DISCOURSE_SMTP_OPENSSL_VERIFY_MODE: none,最终解决了问题。

我不太确定 DNS 问题将来是否还会引起麻烦,希望不会,哈哈,但还是非常感谢你们两位的帮助!

1 个赞

您确实在容器中遇到了网络问题,但问题源于 DNS 而非 IP 连接。

您能否从容器内部使用 openssl s_client 连接到主机名?

您应该能够运行:

openssl s_client -connect smtp-relay.brevo.com:587 -starttls smtp

并得到:

…
Verify return code: 0 (ok)
…

这是预料之中的,因为您连接的是一个 IP 地址,而该 IP 地址不在证书上。

会的。

1 个赞

是的,我猜到了,所以我最终在配置文件中添加了 docker_args yaml 标签,并直接指定了一些 DNS 服务器。

供大家参考(我不得不查找 docker_args 标签的位置),这是 app.yml 文件的一部分:

*******Omitted lines above*********
## 编辑时请 *务必* 小心!
## YAML 文件对空格或对齐错误非常非常敏感!
## 如有需要,请访问 http://www.yamllint.com/ 来验证此文件

docker_args: "--dns 1.1.1.1 --dns 8.8.4.4 --dns 8.8.8.8"

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  ## 取消注释下一行以启用 IPv6 监听器
  #- "templates/web.ipv6.template.yml"
  - "templates/web.ratelimited.template.yml"
*******Omitted rest of file below*********

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.