Estoy ejecutando un servidor Ubuntu 14.04 (Linux). He instalado y configurado Postfix y OpenDKIM muy bien en el servidor; Puedo enviar mensajes de correo electrónico a mí mismo con comandos como echo hi | sendmail root
, y postfix / opendkim a añadir encabezados tales como Message-Id
, Date
y DKIM-Signature
, reenviar el correo electrónico a mi dirección de correo electrónico personal, y todo funciona muy bien.
Ahora me gustaría crear una aplicación que se ejecute en un contenedor Docker y pueda enviar correos electrónicos con la misma facilidad. En particular, no quiero preocuparme por agregar encabezados como Message-Id
, y no quiero hacer mucha configuración o instalación de software dentro del contenedor.
¿Cuál es la mejor manera de hacer esto?
¿Hay alguna forma de permitir que el contenedor ejecute lo sendmail
ejecutable en el host?
Traté de hacer una conexión a Postfix desde un contenedor usando el protocolo SMTP en el puerto 25, pero Postfix parece tratar los mensajes recibidos de esa manera de manera diferente; Creo que no agregó ningún encabezado, por lo que el mensaje fue rechazado directamente como spam por gmail (ni siquiera era lo suficientemente bueno como para colocarlo en mi carpeta de Spam).
Aquí el contenido del maillog
Sep 28 23:35:52 dantooine postfix/smtpd[4306]: connect from unknown[172.17.0.95]
Sep 28 23:35:52 dantooine postfix/smtpd[4306]: DD457889B: client=unknown[172.17.0.95]
Sep 28 23:35:52 dantooine postfix/cleanup[4309]: DD457889B: message-id=<>
Sep 28 23:35:52 dantooine spamd[3175]: spamd: connection from localhost [::1]:59471 to port 783, fd 6
Sep 28 23:35:52 dantooine spamd[3175]: spamd: handle_user (getpwnam) unable to find user: 'someone'
Sep 28 23:35:52 dantooine spamd[3175]: spamd: still running as root: user not specified with -u, not found, or set to root, falling back to nobody
Sep 28 23:35:52 dantooine spamd[3175]: spamd: processing message (unknown) for someone:65534
Sep 28 23:35:52 dantooine spamd[3175]: spamd: clean message (2.5/5.0) for someone:65534 in 0.0 seconds, 331 bytes.
Sep 28 23:35:52 dantooine spamd[3175]: spamd: result: . 2 - MISSING_DATE,MISSING_FROM,MISSING_MID,UNPARSEABLE_RELAY scantime=0.0,size=331,user=someone,uid=65534,required_score=5.0,rhost=localhost,raddr=::1,rport=59471,mid=(unknown),autolearn=no autolearn_force=no
Sep 28 23:35:52 dantooine opendkim[3179]: DD457889B: can't determine message sender; accepting
Sep 28 23:35:53 dantooine postfix/qmgr[3664]: DD457889B: from=<[email protected]>, size=275, nrcpt=1 (queue active)
Sep 28 23:35:53 dantooine postfix/smtpd[4306]: disconnect from unknown[172.17.0.95]
Sep 28 23:35:53 dantooine postfix/smtp[4311]: DD457889B: to=<[email protected]>, relay=gmail-smtp-in.l.google.com[2607:f8b0:4003:c05::1b]:25, delay=0.25, delays=0.12/0.01/0.03/0.09, dsn=5.7.1, status=bounced (host gmail-smtp-in.l.google.com[2607:f8b0:4003:c05::1b] said: 550-5.7.1 [fd17:8b70:893a:44bf:fe73:6c21] Our system has detected that 550-5.7.1 this message is likely unsolicited mail. To reduce the amount of spam 550-5.7.1 sent to Gmail, this message has been blocked. Please visit 550-5.7.1 http://support.google.com/mail/bin/answer.py?hl=en&answer=188131 for 550 5.7.1 more information. su20si7357528oeb.94 - gsmtp (in reply to end of DATA command))
Sep 28 23:35:53 dantooine postfix/cleanup[4309]: 254E688A0: message-id=<[email protected]>
Sep 28 23:35:53 dantooine postfix/bounce[4330]: DD457889B: sender non-delivery notification: 254E688A0
Sep 28 23:35:53 dantooine postfix/qmgr[3664]: 254E688A0: from=<>, size=3374, nrcpt=1 (queue active)
Sep 28 23:35:53 dantooine postfix/qmgr[3664]: DD457889B: removed
Sep 28 23:35:53 dantooine postfix/virtual[4331]: 254E688A0: to=<[email protected]>, relay=virtual, delay=0.01, delays=0/0/0/0, dsn=2.0.0, status=sent (delivered to maildir)
Sep 28 23:35:53 dantooine postfix/qmgr[3664]: 254E688A0: removed
To
encabezado,Subject
encabezado y un cuerpo de una línea. No estoy seguro de cómo saber qué encabezados tenía después de que Postfix lo revisara, ¿sabes cómo? Aquí está el resultado en / var / log / syslog que muestra cómo fue procesado por Postfix y rechazado por Gmail: gist.github.com/DavidEGrayson/fbf65c8290c049a1f262Respuestas:
Debido a que tiene una solución que funciona, aquí trataré de explicar diferentes comportamientos cuando hace telnet para postfix (SMTP) y cuando usa sendmail (no SMTP).
FYI, OpenDKIM será invocado por postfix con mecanismo Milter . Puede obtener información sobre la implementación más fácil en postfix a través de esta documentación oficial . Aquí el diagrama del gancho milter en postfix.
Puede ver que sendmail-way (no SMTP) y telnet-way (SMTP) tienen un orden de procesamiento diferente.
El correo electrónico que no sea SMTP se procesará mediante limpieza antes de inyectarlo en milter. Demonio de la limpieza era responsable de añadir cabeceras faltantes: (resentimiento) De :, Para :, Mensaje-Id :, y Fecha: . Por lo tanto, su correo electrónico tendrá un encabezado completo cuando se inyecte en OpenDKIM milter, incluso el correo electrónico original tenía un encabezado incompleto.
El correo electrónico SMTP se inyectará en OpenDKIM milter antes de que se realice el proceso de limpieza. Por lo tanto, si su correo electrónico original tenía un encabezado incompleto, opendkim puede negarse a firmar el correo electrónico. El encabezado De: era obligatorio (consulte RFC 6376 ) y si un correo electrónico no lo tiene, OpenDKIM se negará a firmar el correo electrónico y le dará una advertencia.
Como nunca uso docker, entonces no sé qué limitación en sendmail / pickup dentro de un contenedor. Creo que la solución alternativa de David Grayson fue lo suficientemente segura como para garantizar que OpenDKIM firme el mensaje.
fuente
From:
encabezado en su correo electrónico :)Message-Id
que no sé mucho y probablemente me equivocaría ... parece más fácil dejar que el demonio de la limpieza se encargue de eso.From
encabezado. Pero, si desea generar su propia ID de mensaje, puede usar una recomendación como este Borrador de IETFTienes que señalar el
inet_interfaces
puente acoplable (docker0
) en la configuración de postfix ubicada en set/etc/postfix/main.cf
Más detalles de trabajo internos en el envío de correo electrónico desde docker a través de postfix-instaló-en-el-host
fuente
172.17.0.0/16
quemynetworks
en/etc/postfix/main.cf
yservice postfix restart
.Esta es una respuesta a medias, o al menos a medias, ya que actualmente estoy trabajando en el mismo problema. Espero que alguien pueda ayudar a desarrollar lo que me he perdido.
La respuesta del OP (David Grayson) me suena como una reinvención de la bobina de correo postdrop, pero usar esa bobina de correo suena como un enfoque prometedor, así que aquí es donde he llegado.
La interfaz de compatibilidad / usr / bin / sendmail proporcionada por postfix pasa el correo a postdrop, que es sgid postdrop, lo que le permite almacenar el correo en la cola de maildrop en / var / spool / postfix / maildrop. Esto debería ocurrir en el contenedor acoplable. Es de esperar que el resto de postfix no tenga que ejecutarse en el contenedor.
Entonces, estoy montando el host / var / spool / postfix / maildrop y / var / spool / postfix / public. Puedo enviar el correo a / var / spool / postfix / maildrop en el entorno host, ya que he montado el directorio de cola de maildrop. Porque he montado
/var/spool/postfix/public
,maildrop
puedo señalarpickup
que recoja el correo de la cola. Desafortunadamente, los uids y gids involucrados a menos que me ocupe de eso, lo que significa que la recolección en el directorio host no puede leer los archivos de spool, y peor aún, la instalación de postfix desordena los permisos en el directorio maildrop en el entorno host.Aún así, esto parece funcionar:
Si bien funciona, no estoy terriblemente feliz con la codificación dura de los uids y gids. Esto significa que no se puede contar el mismo contenedor para ejecutarlo en todas partes. Sin embargo, me imagino que si en lugar de montar el volumen desde el host lo monte desde un contenedor que ejecuta postfix, entonces nunca entrará en conflicto, y solo necesito una instalación de postfix para obtener el correo de muchos contenedores. Establecería esos uids y gids en una imagen base de la que heredan todos mis contenedores.
Sin embargo, me pregunto si este es realmente un buen enfoque. Con una configuración de correo tan simple, y ningún demonio en uso en el contenedor para volver a intentar la entrega, un MTA local más simple como msmtp podría ser más apropiado. Se entregaría a través de TCP a un relé en el mismo host, donde se produciría la cola.
Las preocupaciones con el enfoque msmtp incluyen:
En general, el enfoque de spool de postfix compartido parece más probable que sea una configuración frágil para configurar, pero es menos probable que falle en el tiempo de ejecución (retransmisión no disponible, por lo que el correo se descartó).
fuente
Decidí que la forma en que el contenedor enviará correo es escribiéndolo en un archivo en un directorio particular, al que se podrá acceder tanto desde el contenedor como desde el host como un "volumen" de Docker.
Hice un script de shell llamado mailsender.sh que lee correos de un directorio específico, los envía a sendmail y luego los elimina:
Ubuntu usa el sistema de arranque, así que creé un archivo llamado
/etc/init/mailsender.conf
para convertir este script en un demonio:Puedo iniciar el servicio con
start mailsender
y detenerlostop mailsender
. Puedo ver sus registros/var/log/upstart/mailsender.log
y, por supuesto, puedo monitorearlo usando el archivo PID.Debe crear el
/var/mailsend
directorio y luego hacerlo accesible desde el contenedor Docker agregando el argumento-v /var/mailsend:/var/mailsend
a sudocker run
comando.fuente