호스트의 Postfix를 사용하여 Docker 컨테이너에서 메일 보내기


18

Ubuntu 14.04 (Linux) 서버를 실행 중입니다. PostfixOpenDKIM을 서버에 아주 잘 설치하고 구성했습니다 . 나는 다음과 같은 명령을 자신에게 이메일을 보낼 수 있습니다 echo hi | sendmail root, 그리고 후위 / opendkim 같은 헤더를 추가 할 것 Message-Id, Date그리고 DKIM-Signature앞으로 이메일을 내 개인 이메일 주소로 모든 것이 잘 작동합니다.

이제 Docker 컨테이너 에서 실행되고 동일한 전자 메일을 보낼 수 있는 응용 프로그램을 만들고 싶습니다 . 특히,와 같은 헤더 추가에 대해 걱정 Message-Id하고 싶지 않으며 컨테이너 자체 내부에서 많은 구성이나 소프트웨어 설치를 원하지 않습니다.

가장 좋은 방법은 무엇입니까?

컨테이너 sendmail가 호스트 에서 실행 파일을 실행할 수있는 방법이 있습니까?

포트 25의 SMTP 프로토콜을 사용하여 컨테이너에서 Postfix에 연결을 시도했지만 Postfix는 이와 같이 수신 된 메시지를 다르게 취급하는 것 같습니다. 헤더가 추가되지 않아 Gmail이 스팸으로 메시지를 완전히 거부했다고 생각합니다 (스팸 폴더에 넣을만큼 충분하지 않았습니다).

여기 메일 로그 내용

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=<whoever@example.com>, 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=<someone@gmail.com>, 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=<20140928233553.254E688A0@myserver.example.com>
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=<whoever@example.com>, 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

이메일 헤더 (GMAIL에 의해 스팸으로 잘못 식별 된 헤더)를 게시하십시오
masegaloeh

보내려는 이메일에는 To헤더, Subject헤더 및 한 줄 본문이 있습니다. Postfix가 milters를 통해 실행 한 후 어떤 헤더를 사용했는지 알 수 없습니다. 어떻게 아십니까? 여기가 Gmail의 후위 처리 및 거절 된 방법는 / var / log / syslog 파일 표시에서의 출력은 : gist.github.com/DavidEGrayson/fbf65c8290c049a1f262
데이비드 그레이

답변:


8

작동하는 솔루션이 있기 때문에 여기서는 텔넷 후 접미사 (SMTP) 및 sendmail (비 SMTP)을 사용할 때 다른 동작을 설명하려고합니다.

참고로, OpenDKIM은 Milter 메커니즘 으로 postfix에 의해 호출됩니다 . 이 공식 문서 를 통해 postfix에서 더 나은 구현 방법에 대한 정보를 얻을 수 있습니다 . 다음은 접미사의 밀터 후크 다이어그램입니다.

             SMTP-only       non-SMTP
             filters         filters
                ^ |            ^ |
                | v            | |
Network ->  smtpd(8)           | |
                       \       | V
Network ->  qmqpd(8)    ->  cleanup(8)  ->  incoming
                       /
            pickup(8)
               :
Local   ->  sendmail(1)

sendmail-way (SMTP가 아닌)와 telnet-way (SMTP)의 처리 순서가 다르다는 것을 알 수 있습니다.

  • SMTP 이외의 이메일은 정리하기 전에 정리하여 처리합니다. 정리 데몬 은 누락 된 헤더 (Resent-) From :, To :, Message-Id :Date :를 추가해야했습니다 . 따라서 OpenDKIM milter에 주입되면 이메일에는 완전한 헤더가 있으며 원본 이메일에도 헤더가 불완전합니다.

  • 정리 프로세스가 수행되기 전에 SMTP 전자 메일이 OpenDKIM milter에 주입됩니다. 따라서 원래 이메일에 불완전한 헤더가 있으면 opendkim이 이메일 서명을 거부 할 수 있습니다. 에서 : 헤더 (참조 필수했다 6376 RFC를 ) 및 이메일이없는 경우, OpenDKIM 이메일에 서명을 거부하고 당신에게 경고를 줄 것이다

    can't determine message sender; accepting
    

도커를 절대 사용하지 않기 때문에 컨테이너 내부의 sendmail / pickup에 어떤 제한이 있는지 모릅니다. David Grayson의 해결책은 OpenDKIM이 메시지에 서명 할 수있을 정도로 안전하다고 생각합니다.


그것은 깨달았습니다; 감사합니다. 불행히도 여전히 내 솔루션보다 더 나은 솔루션을 찾지 못합니다 (내 답변에 설명되어 있음).
David Grayson

명백한 이유는 추가로 응용 프로그램을 수정했다 From:이메일 :)에서 헤더
masegaloeh

그러나 나는 또한 Message-Id잘 모르는 것들을 추가해야 할 것이고 아마도 잘못했을 것입니다 ... 정리 데몬이 그것을 처리하게하는 것이 더 쉬운 것 같습니다.
David Grayson

실제로 RFC 6376이 말한 것처럼 Message-ID는 필수가 아닙니다 . 기본적으로 필수 헤더는 From헤더 뿐입니다 . 당신이 당신의 자신의 메시지 ID를 생성 할 경우에, 당신은 같은 권장 사항을 사용할 수있는 이 IETF 초안
masegaloeh

6

set에있는 postfix 설정에서 inet_interfacesdocker bridge ( docker0) 를 가리켜 야 합니다./etc/postfix/main.cf

inet_interfaces = <docker0_ip>

호스트에서 전자 우편을 통해 도커에서 포스트 픽스를 설치하는 데 대한 내부 작업 세부 사항


링크 주셔서 감사합니다! 나에게 관련된 부분은 에 와 같은 172.17.0.0/16것을 추가하는 것이 었습니다 . mynetworks/etc/postfix/main.cfservice postfix restart
JSchirrmacher

5

나는 현재 같은 문제를 겪고 있기 때문에 반 답이거나 적어도 반 테스트 된 것입니다. 나는 내가 놓친 것을 육체적으로 도울 수 있기를 바랍니다.

OP (David Grayson)의 대답은 postdrop 메일 스풀의 재발 명처럼 들리지만 그 메일 스풀을 사용하는 것은 유망한 접근 방식처럼 들리므로 여기에 도착했습니다.

postfix가 제공하는 / usr / bin / sendmail 호환성 인터페이스는 mail을 postdrop로 전달합니다. postdrop은 sgid postdrop입니다. 메일을 / var / spool / postfix / maildrop의 maildrop 큐에 저장할 수 있습니다. 도커 컨테이너에서 발생해야합니다. 나머지 postfix는 컨테이너에서 실행하지 않아도됩니다.

그래서 저는 호스트 마운트 / var / spool / postfix / maildrop 및 / var / spool / postfix / public입니다. maildrop 큐 디렉토리를 마운트 했으므로 호스트 환경에서 / var / spool / postfix / maildrop으로 메일을 전달할 수 있습니다. 내가 탑재했기 때문에 /var/spool/postfix/public, maildrop신호를 보낼 수 pickup큐에서 메일을 수집 할 수 있습니다. 불행히도, 내가 처리하지 않으면 uids와 gids가 관여합니다. 즉, 호스트 디렉토리의 픽업이 스풀 파일을 읽을 수 없으며 더 나쁜 접미사 설치는 호스트 환경의 maildrop 디렉토리에 대한 권한을 엉망으로 만듭니다.

여전히 이것은 작동하는 것 같습니다.

$ 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 myemail@example.com

$ 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

그것이 작동하는 동안, 나는 UID와 GID를 하드 코딩하는 것에 크게 만족하지 않습니다. 즉, 동일한 컨테이너를 모든 곳에서 동일하게 실행할 수는 없습니다. 호스트에서 볼륨을 마운트하는 대신 postfix를 실행하는 컨테이너에서 볼륨을 마운트하면 충돌하지 않으며 많은 컨테이너에서 메일을 가져 오기 위해 하나의 postfix 설치 만 필요하다고 생각합니다. 모든 컨테이너가 상속하는 기본 이미지에 해당 uid 및 gid를 설정했습니다.

이것이 정말로 좋은 접근법인지 궁금합니다. 이러한 간단한 메일 구성과 배달 재 시도를 위해 컨테이너에서 데몬을 사용하지 않는 경우 msmtp와 같은 간단한 로컬 MTA가 더 적합 할 수 있습니다. 스풀링이 발생하는 동일한 호스트의 릴레이로 TCP를 통해 전달됩니다.

msmtp 접근 방식에 대한 우려는 다음과 같습니다.

  • 보내는 SMTP 릴레이를 사용할 수없는 경우 메일을 잃을 가능성이 높습니다. 동일한 호스트의 릴레이 인 경우 네트워크 문제가 발생할 가능성이 낮지 만 릴레이 컨테이너를 다시 시작하는 방법에주의해야합니다.
  • 공연?
  • 대량의 메일이 통과되면 메일이 삭제되기 시작합니까?

일반적으로 공유 postfix 스풀 접근 방식은 설정하기에 취약한 구성 인 것 같지만 런타임에 실패 할 가능성은 적습니다 (릴레이를 사용할 수 없으므로 메일이 삭제됨).


4

컨테이너가 메일을 보내는 방식은 컨테이너와 호스트에서 Docker "볼륨"으로 액세스 할 수있는 특정 디렉토리의 파일에 메일을 쓰는 것입니다.

지정된 디렉토리에서 메일을 읽고 sendmail로 보낸 다음 삭제하는 mailsender.sh라는 쉘 스크립트를 작성했습니다.

#!/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는 upstart를 사용하므로이 /etc/init/mailsender.conf스크립트를 데몬으로 바꾸는 파일을 만들었습니다 .

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

로 서비스를 시작 start mailsender하고 중지 할 수 있습니다 stop mailsender. 나는 그것의 로그를 볼 수 /var/log/upstart/mailsender.log있으며 물론 PID 파일을 사용하여 모니터링 할 수 있습니다.

/var/mailsend디렉토리 를 작성한 다음 명령에 인수 -v /var/mailsend:/var/mailsend를 추가하여 Docker 컨테이너에서 디렉토리에 액세스 할 수 있도록해야 합니다 docker run.


아마도 mini_sendmail과 같은 것이 도움이 될 것입니까? 컨테이너 호스트 시스템의 컨테이너 격리 앱과 sendmail 서버 데몬 간의 브리지처럼 컨테이너에서 사용됩니다. cyberciti.biz/tips/… acme.com/software/mini_sendmail
Mikl

SMTP를 통해 Postfix에 이메일을 보내는 경우 Postfix가 이메일을 정리하지 않을 것이라고 생각합니다. 더 구성 가능한 MTA가 있거나 Postfix를 더 잘 구성하는 방법을 찾은 경우 작동합니다.
David Grayson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.