首页 > 解决方案 > 尝试使用 docker-compose 和 nodemailer 设置本地 docker-mailserver

问题描述

我正在尝试设置一个 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:

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

Jun 22 23:25:53 mailserver postfix/master[26133]: fatal: bind: private/proxywrite: Invalid argument

我认为这可能会导致问题,因为当我尝试使用 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)
  },
)

我收到以下错误:

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)

任何帮助将不胜感激。

标签: node.jsdockerdocker-composenodemailermail-server

解决方案


我猜你正在app容器中运行你的节点代码。

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

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

这将使您appmailserver容器直接与容器对话:

let transporter = nodemailer.createTransport({
  host: 'mailserver',
  port: 587,
})

更多疑难解答:

  • mailserver只是skynet网络的一部分。确保它app也属于那个。netcat//可以帮你排错:telnet-再容器里面:pingdocker-compose exec -it app bashping 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(无论如何“固定”使用的依赖项的主要版本是一种很好的做法)
  • 尝试通过其他端口发送邮件。例如,我在 docker-mailserver 的端口 25 上使用 STARTTLS 从我的应用程序发送邮件。

推荐阅读