【问题标题】:Python send mail inside docker container with local SMTP serverPython 使用本地 SMTP 服务器在 docker 容器内发送邮件
【发布时间】:2020-06-15 09:22:48
【问题描述】:

我想在 python 上使用smtp lib 发送邮件。我知道它在端口号 25 上使用本地 smtp 服务。我有以下代码。这些代码在我的本地运行没有任何问题,邮件发送成功。但是当我将它们移动到 docker 容器时,邮件不会发送,也不会出现任何错误。

我的代码:

from_mail = 'noreply@testmail.com'
to_mail = 'to@testmail.com'

s = smtplib.SMTP('localhost')
subject = 'Test Subject'
content = 'content test'

message = f"""\
      Subject: {subject}
      To: {to_mail}
      From: {from_mail}
      {content}"""
result = s.sendmail(from_mail, to_mail, message)
s.quit()

运行这些代码后,我得到空 dict ({}) 作为 result 值。在sendmail方法描述中有这样的:

...邮件已被接受以传递给三个 四个地址中的一个,其中一个被拒绝,错误代码为 550. 如果所有地址都被接受,那么该方法将返回一个 空字典。

是关于网络配置的吗?我应该配置任何网络设置吗?

【问题讨论】:

  • 旅游集装箱基于什么图像?以及如何运行容器?这可能有助于解决您的问题
  • 我的容器基于python:3.6-slim-buster
  • 可以分享一下dockerfile吗?
  • 你的操作系统是什么?

标签: python-3.x docker email smtp sendmail


【解决方案1】:

您共享的代码是 SMTP 客户端应用程序。假设使用 SMTP 客户端标准库smtplib 并且 SMTP 服务器运行在 localhost 上,代码将在以下情况下在 Docker 容器中运行:

  • 使用--net=host 启动容器,则无需更改。调用smtplib.SMTP('localhost') 将连接到主机上运行的 SMTP 服务器。
  • 您不使用--net=host 启动容器。如果您使用 Windows 或 MacOS,则需要连接到 host.docker.internal 而不是 localhost。如果你使用Linux,可能需要使用另一个trick。本质上,代码仍在连接到主机上运行的 SMTP 服务器。
  • 您将 SMTP 服务器和 python stmp 客户端应用程序(您共享的代码)打包在同一个 Docker 映像中。这是不好的做法,应该避免。不过你可以关注docs来实现。

请分享以下内容以更好地理解问题:

更具体地说:

  • 您正在使用的操作系统。桌面版 Docker 对于 Mac 和 Windows 的行为不同,especially 在网络功能方面。

  • Dockerfile你用。否则无法运行映像并复制您面临的问题并理解您的意思 sendmail service is running in my container.

  • 完全可以工作的python代码(包括导入等)否则,不清楚你使用什么smtplib。

  • 文档链接。如果你使用标准库smtplib,那么它的docs没有这样的描述:

sendmail 方法描述有这样的:

... 邮件被接受发送到四个地址中的三个,一个被拒绝,错误代码为 550。如果所有 地址被接受,然后该方法将返回一个空 字典。

【讨论】:

  • --net=host 对我不起作用(可能是因为我使用的是0.0.0.0 而不是localhost)但host.docker.internal 工作得很好!谢谢。
【解决方案2】:

默认情况下,docker 容器在单独的网络堆栈中运行,因此localhost 在 docker 容器中的含义与代码直接在计算机上运行时的含义不同。

根据您的 SMTP 服务器的设置方式,它也可能被配置为拒绝发送任何电子邮件,但那些直接来自您的计算机的电子邮件除外,并且 docker 容器可能被视为不应通过它发送电子邮件的局外人.

我想最简单的解决方案是使用--net=host 运行您的 docker 容器。这样,docker 容器的网络堆栈将与您计算机的堆栈相同,并且一切都应该像代码直接在 docker 外部运行一样工作。

【讨论】:

  • 我对连接到 docker 容器上的 smtp 服务没有任何问题。当我更改连接信息时 - 例如另一个端口号或主机名 - 我收到连接错误。
【解决方案3】:

如果它可以在主机上运行,​​请尝试使用主机 IP 而不是 localhost。

s = smtplib.SMTP(HOST_IP)

或者按照 Arthur 的建议,您可以使用 --net=host 在主机网络中运行容器,然后继续使用 localhost。

【讨论】:

  • 感谢您的回答,sendmail 服务正在我的容器中运行。我想从不使用主机的容器发送邮件。
  • 你确定吗?然后,您需要为您的问题添加更多详细信息。你的容器的 dockerfile,你如何在容器中安装 smtp 服务等
猜你喜欢
  • 1970-01-01
  • 2013-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-19
  • 2017-01-30
  • 2017-12-16
相关资源
最近更新 更多