Solución:
Solución 1:
Debido a que tiene una solución que funciona, aquí intentaré explicar el comportamiento diferente cuando usa telnet para postfix (SMTP) y cuando usa sendmail (no SMTP).
Para su información, OpenDKIM se invocará mediante postfix con mecanismo Milter. Puede obtener información sobre la implementación de postfix a través de esta documentación oficial. Aquí el diagrama de milter hook en postfix.
SMTP-only non-SMTP
filters filters
^ | ^ |
| v | |
Network -> smtpd(8) | |
| V
Network -> qmqpd(8) -> cleanup(8) -> incoming
/
pickup(8)
:
Local -> sendmail(1)
Puede ver que sendmail-way (no SMTP) y telnet-way (SMTP) tienen un orden de procesamiento diferente.
-
El correo electrónico no SMTP se procesará mediante limpieza antes de inyectarse en milter. El demonio de limpieza fue responsable de agregar encabezados faltantes: (Resentido-) De :, Para :, Id. De mensaje :, y Fecha:. Por lo tanto, su correo electrónico tendrá un encabezado completo cuando se inyecte en OpenDKIM, 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 lleve a cabo cualquier 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. los De: El encabezado era obligatorio (ver 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.
can't determine message sender; accepting
Como nunca uso la ventana acoplable, no sé qué limitación en el envío / recogida dentro del contenedor. Creo que la solución alternativa de David Grayson fue lo suficientemente segura como para garantizar que OpenDKIM firmara el mensaje.
Solucion 2:
Tienes que apuntar inet_interfaces
al puente de dockerdocker0
) en la configuración de postfix ubicada en set /etc/postfix/main.cf
inet_interfaces = <docker0_ip>
Más detalles de trabajo interno en send-email-from-docker-through-postfix-installed-on-the-host
Solución 3:
Esta es una respuesta a medias, o al menos una respuesta a medias, ya que actualmente estoy resolviendo el mismo problema. Espero que alguien pueda ayudarme a desarrollar lo que me he perdido.
La respuesta del OP (David Grayson) me suena como una reinvención del spool de correo postdrop, pero usar ese spool de correo suena como un enfoque prometedor, así que aquí es donde llegué.
La interfaz de compatibilidad / usr / bin / sendmail proporcionada por postfix pasa correo a postdrop, que es sgid postdrop, lo que le permite almacenar correo en la cola de maildrop en / var / spool / postfix / maildrop. Esto debería ocurrir en el contenedor de la ventana acoplable. Es de esperar que el resto de postfix no tenga que ejecutarse en el contenedor.
Entonces, soy el montaje de host / var / spool / postfix / maildrop y / var / spool / postfix / public. Puedo recibir correo enviado a / var / spool / postfix / maildrop en el entorno de host, ya que he montado el directorio de cola de maildrop. Porque he montado /var/spool/postfix/public
, maildrop
puede señalar pickup
para recoger el correo de la cola. Desafortunadamente, los uids y gids involucrados a menos que me ocupe de eso, lo que significa que la recogida en el directorio del host no puede leer los archivos de cola y, lo que es peor, la instalación de postfix estropea los permisos en el directorio maildrop en el entorno del host.
Aún así, esto parece funcionar:
$ cat Dockerfile
FROM debian:jessie
# Ids from parent environment
RUN groupadd -g 124 postfix &&
groupadd -g 125 postdrop &&
useradd -u 116 -g 124 postfix
RUN apt-get update &&
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y
postfix
bsd-mailx
CMD echo test mail | mail [email protected]
$ sudo docker build .
...
Successfully built 16316fcd44b6
$ sudo docker run -v /var/spool/postfix/maildrop:/var/spool/postfix/maildrop
-v /var/spool/postfix/public:/var/spool/postfix/public 16316fcd44b6
Si bien funciona, no estoy muy contento con la codificación rígida de los uids y gids. Esto significa que no se puede contar que el mismo contenedor se ejecute de la misma manera en todas partes. Sin embargo, me imagino que si en lugar de montar el volumen desde el host, lo monto desde un contenedor que ejecuta postfix, nunca entrará en conflicto, y solo necesito una instalación de postfix para sacar 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 sin un 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 el spooling.
Las preocupaciones con el enfoque msmtp incluyen:
- mayor posibilidad de perder correo si la retransmisión smtp a la que envía no está disponible. Si eso es un relé en el mismo host, entonces la posibilidad de problemas de red es baja, pero tendría que tener cuidado con la forma en que reinicié el contenedor de relés.
- ¿rendimiento?
- Si pasa una gran cantidad de correo, ¿comienza a caerse el correo?
En general, el enfoque de spool de postfix compartido parece más probable que sea una configuración frágil de configurar, pero es menos probable que falle en tiempo de ejecución (retransmisión no disponible, por lo que el correo se descartó).
Solución 4:
Decidí que la forma en que el contenedor enviará correo es escribirlo 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 los correos de un directorio específico, los envía a sendmail y luego los elimina:
#!/bin/bash
# Runs on the host system, reading mails files from a directory
# and piping them to sendmail -t and then deleting them.
DIR=$1
if [ ! ( -d "$DIR" -a -w "$DIR" ) ]
then
echo "Invalid directory given: $DIR"
exit 1
fi
echo "`date`: Starting mailsender on directory $DIR"
cd $DIR
while :
do
for file in `find . -maxdepth 1 -type f`
do
echo "`date`: Sending $file"
sendmail -t < $file
rm $file
done
sleep 1
done
Ubuntu usa advenedizo, así que creé un archivo llamado /etc/init/mailsender.conf
para convertir este script en un demonio:
description "sends mails from directory"
start on stopped rc RUNLEVEL=[2345]
stop on runlevel[!2345]
respawn
exec start-stop-daemon --start --make-pidfile --pidfile /var/run/mailsender.pid --exec
/path/to/mailsender.sh /var/mailsend
Puedo iniciar el servicio con start mailsender
y detenerlo con stop mailsender
. Puedo mirar sus registros /var/log/upstart/mailsender.log
y, por supuesto, puedo monitorearlo usando el archivo PID.
Necesitas crear el /var/mailsend
directorio y luego hágalo accesible desde el contenedor Docker agregando el argumento -v /var/mailsend:/var/mailsend
para usted docker run
mando.