Estou executando um servidor Ubuntu 14.04 (Linux). Eu instalei e configurei muito bem o Postfix e o OpenDKIM no servidor; Posso enviar e-mails para mim com comandos como echo hi | sendmail root
, e postfix / opendkim irá adicionar cabeçalhos tais como Message-Id
, Date
, e DKIM-Signature
, para a frente e-mail para o meu endereço de e-mail pessoal, e tudo funciona muito bem.
Agora, eu gostaria de criar um aplicativo que é executado em um contêiner do Docker e pode enviar e-mails com a mesma facilidade. Em particular, não quero me preocupar em adicionar cabeçalhos como Message-Id
, e não quero fazer muita configuração ou instalação de software dentro do próprio contêiner.
Qual é a melhor maneira de fazer isso?
Existe alguma maneira de deixar o contêiner executar o sendmail
executável no host?
Tentei fazer uma conexão com o Postfix a partir de um contêiner usando o protocolo SMTP na porta 25, mas o Postfix parece tratar as mensagens recebidas dessa maneira de maneira diferente; Eu acho que ele não adicionou nenhum cabeçalho, então a mensagem foi totalmente rejeitada como spam pelo gmail (nem sequer era boa o suficiente para ser colocada na minha pasta Spam).
Aqui o conteúdo do 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
cabeçalho,Subject
cabeçalho e um corpo de uma linha. Não sei ao certo como saber quais cabeçalhos tinham depois que o Postfix passou por todas as etapas, sabe como? Aqui é a saída em var / log / exibição / syslog como ele foi processado pelo Postfix e recusado pelo Gmail: gist.github.com/DavidEGrayson/fbf65c8290c049a1f262Respostas:
Como você tem uma solução funcional, aqui tentarei explicar um comportamento diferente quando você telnetar para postfix (SMTP) e quando você usar o sendmail (não SMTP).
Para sua informação, o OpenDKIM será chamado pelo postfix com o mecanismo Milter . Você pode obter algumas informações sobre como implementar o milter no postfix através desta documentação oficial . Aqui o diagrama do gancho milter no postfix.
Você pode ver que a maneira sendmail (não SMTP) e a maneira telnet (SMTP) têm ordem de processamento diferente.
O e-mail não SMTP será processado pela limpeza antes de ser injetado na ordenha. Daemon Cleanup foi responsável por adicionar cabeçalhos ausentes: (resent) De :, Para :, Message-Id :, e Data: . Portanto, seu e-mail terá um cabeçalho completo quando injetado no OpenDKIM milter, mesmo que o e-mail original tenha um cabeçalho incompleto.
O email SMTP será injetado no OpenDKIM milter antes de qualquer processamento de limpeza. Portanto, se o seu email original tiver um cabeçalho incompleto, o opendkim poderá se recusar a assinar o email. O cabeçalho De: era obrigatório (consulte a RFC 6376 ) e, se um email não o possuir, o OpenDKIM se recusará a assinar o email e enviar um aviso
Como eu nunca uso o docker, não sei qual limitação no sendmail / pickup dentro de um contêiner. Acho que a solução alternativa de David Grayson foi segura o suficiente para garantir que o OpenDKIM assine a mensagem.
fonte
From:
cabeçalho no seu e-mail :)Message-Id
que não conheço muito e provavelmente erraria ... parece mais fácil deixar o daemon de limpeza cuidar disso.From
cabeçalho. Mas, se você deseja gerar seu próprio ID da mensagem, pode usar recomendações como esta IETF DraftVocê precisa apontar
inet_interfaces
para o docker bridge (docker0
) na configuração do postfix localizada em set/etc/postfix/main.cf
Mais detalhes de trabalho interno em envio de email do docker através do postfix instalado no host
fonte
172.17.0.0/16
amynetworks
em/etc/postfix/main.cf
eservice postfix restart
.Esta é uma meia resposta, ou pelo menos uma metade testada, pois atualmente estou trabalhando com o mesmo problema. Espero que alguém possa ajudar a concretizar o que perdi.
A resposta do OP (David Grayson) me parece uma reinvenção do spool de mensagens pós-lançamento, mas usá-lo parece uma abordagem promissora, então é aqui que eu cheguei.
A interface de compatibilidade / usr / bin / sendmail fornecida pelo postfix passa o email para o postdrop, que é o sgid postdrop, permitindo armazenar emails na fila do maildrop em / var / spool / postfix / maildrop. Isso deve ocorrer no contêiner da janela de encaixe. Esperamos que o restante do postfix não precise ser executado no contêiner.
Então, sou host mount / var / spool / postfix / maildrop e / var / spool / postfix / public. Posso receber mensagens entregues em / var / spool / postfix / maildrop no ambiente host, desde que montei o diretório da fila do maildrop. Porque eu montei
/var/spool/postfix/public
,maildrop
posso sinalizarpickup
para coletar o correio da fila. Infelizmente, os uids e os gids envolvidos, a menos que eu cuide disso, significam que a coleta no diretório host não pode ler os arquivos em spool e, pior ainda, a instalação do postfix altera as permissões no diretório maildrop no ambiente host.Ainda assim, isso parece funcionar:
Enquanto funciona, não estou muito feliz com a codificação dos uids e gids. Isso significa que o mesmo contêiner não pode ser contado para executar o mesmo em qualquer lugar. No entanto, acho que se, em vez de montar o volume do host, eu o montar a partir de um contêiner que executa o postfix, ele nunca entrará em conflito, e eu só preciso de uma instalação do postfix para enviar as mensagens de muitos contêineres. Eu definiria esses uids e gids em uma imagem base da qual todos os meus contêineres herdam.
Eu me pergunto se essa é realmente uma boa abordagem. Com uma configuração de email tão simples e nenhum daemon em uso no contêiner para tentar novamente a entrega, um MTA local mais simples como o msmtp pode ser mais apropriado. Seria entregue via TCP para um relé no mesmo host, onde ocorreria o spool.
As preocupações com a abordagem msmtp incluem:
Em geral, a abordagem de spool compartilhado do Postfix parece mais provável de ser uma configuração frágil a ser configurada, mas menos provável de falhar no tempo de execução (retransmissão indisponível, portanto, o correio caiu).
fonte
Decidi que a maneira como o contêiner enviará correio é gravá-lo em um arquivo em um diretório específico, acessível a partir do contêiner e do host como um "volume" do Docker.
Criei um script de shell chamado mailsender.sh que lê e-mails de um diretório especificado, envia-os para sendmail e os exclui:
O Ubuntu usa upstart, então eu criei um arquivo chamado
/etc/init/mailsender.conf
para transformar esse script em um daemon:Eu posso iniciar o serviço
start mailsender
e pará-lostop mailsender
. Posso ver seus logins/var/log/upstart/mailsender.log
e, é claro, monitorá-lo usando o arquivo PID.Você precisa criar o
/var/mailsend
diretório e torná-lo acessível a partir do contêiner do Docker adicionando o argumento-v /var/mailsend:/var/mailsend
ao seudocker run
comando.fonte