尝试使用 docker-compose 和 nodemailer 设置本地 docker-mailserver

Lou*_*Kim 5 mail-server node.js nodemailer docker docker-compose

我正在尝试设置一个 docker-mailserver 实例以使用该nodemailer模块从我的本地开发设置中发送电子邮件。这是我的 docker-compose.yml 文件的样子:

version: '3.1'

services:
  postgres:
    container_name: postgres
    image: postgres
    restart: always
    volumes:
      - $PWD/.dbData:/data/db
    networks:
      - skynet
    environment:
      POSTGRES_PASSWORD: <PASSWORD>
      POSTGRES_USER: <USER>
      POSTGRES_DB: <DB>
  mailserver:
    image: docker.io/mailserver/docker-mailserver:latest
    env_file: $PWD/mailserver.env
    hostname: mailserver
    domainname: example.com
    container_name: mailserver
    ports:
      - "25:25"
      - "143:143"
      - "587:587"
      - "993:993"
    volumes:
      - $PWD/.mailData/maildata:/var/mail
      - $PWD/.mailData/mailstate:/var/mail-state
      - $PWD/.mailData/maillogs:/var/log/mail
      - /etc/localtime:/etc/localtime:ro
      - ./config/:/tmp/docker-mailserver/
    environment:
      - ENABLE_SPAMASSASSIN=1
      - SPAMASSASSIN_SPAM_TO_INBOX=1
      - ENABLE_CLAMAV=1
      - ENABLE_FAIL2BAN=1
      - ENABLE_POSTGREY=1
      - ENABLE_SASLAUTHD=0
      - ONE_DIR=1
      - DMS_DEBUG=0
    cap_add:
      - NET_ADMIN
      - SYS_PTRACE
    restart: always
    networks: 
      - skynet
  adminer:
    image: adminer
    hostname: adminer
    ports:
      - '8080:8080'
    depends_on:
      - postgres
    networks:
      - skynet
  app:
    # ... app details
networks:
  skynet:
Run Code Online (Sandbox Code Playgroud)

根据文档,我复制了示例mailserver.env文件和setup.sh管理脚本。当我尝试运行时docker-compose up -d,我在邮件服务器容器的 docker 日志中看到以下内容:

Jun 22 23:25:53 mailserver postfix/master[26133]: fatal: bind: private/proxywrite: Invalid argument
Run Code Online (Sandbox Code Playgroud)

我认为这可能会导致问题,因为当我尝试使用 nodemailer(在同一台机器上)发送一条简单的消息时,如下所示:

const nodemailer = require('nodemailer')

let transporter = nodemailer.createTransport({
  host: 'localhost', // <--- defaults to this anyway
  port: 587,
})

const message = {
  from: 'foo@example.com',
  to: '<MY_PERSONAL_EMAIL>@gmail.com',
  subject: 'YOUR CARS EXTENDED WARRANTY',
  text: 'WEVE BEEN TRYING TO REACH YOU ABOUT YOUR CARS EXTENDED WARRANTY',
  html: '<p>WEVE BEEN TRYING TO REACH YOU ABOUT YOUR CARS EXTENDED WARRANTY</p>',
}

transporter.sendMail(message).then(
  () => {
    console.log('success!')
  },
  (err) => {
    console.error('=========== error occurred', err)
  },
)
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

error occurred Error: Unexpected socket close
    at Timeout._onTimeout (/path/to/nodemailer-test/node_modules/nodemailer/lib/smtp-transport/index.js:189:31)
    at listOnTimeout (internal/timers.js:551:17)
    at processTimers (internal/timers.js:494:7)

Run Code Online (Sandbox Code Playgroud)

任何帮助将不胜感激。

Jon*_*rle 0

我猜您正在容器中运行节点代码app

您试图localhost:587从那里与app容器的端口 587 进行通信,而不是服务上可用的端口mailserver(您也将其绑定到主机)。

您可能想与那里的主机交谈,但是在 docker 中获取主机 IP 并不简单。幸运的是,在这种情况下也不需要:由于两个容器都是同一个 docker-compose 项目的一部分,因此它们会通过服务名称在内部自动路由。

这将使您的容器直接app与容器对话:mailserver

let transporter = nodemailer.createTransport({
  host: 'mailserver',
  port: 587,
})
Run Code Online (Sandbox Code Playgroud)

更多故障排除:

  • mailserver只是skynet网络的一部分。确保它app也属于那个。netcat//telnet可以ping帮你排查问题:docker-compose exec -it app bash- 那么容器里面:ping mailserver
  • 将您的mailserver服务配置与https://github.com/docker-mailserver/docker-mailserver/blob/v10.0.0/docker-compose.yml进行比较- 看来您使用了较旧的配置版本,但mailserver/docker-mailserver:latest指的是 v10。看来README.md/docker hub 页面的示例配置尚未反映这一点。由于它是 v10 的第一个版本,您可能想尝试一下mailserver/docker-mailserver:9(无论如何,“固定”所用依赖项的主要版本是一个很好的做法)
  • 尝试通过其他端口发送邮件。例如,我在端口 25 上使用 STARTTLS 和 docker-mailserver 从我的应用程序发送邮件。