ホストのPostfixを使用してDockerコンテナーからメールを送信する


18

Ubuntu 14.04(Linux)サーバーを実行しています。サーバーにPostfixOpenDKIMを非常にうまくインストールして設定しました。私は、次のようなコマンドを使って自分自身に電子メールを送信することができecho hi | sendmail root、および接尾/ opendkimは、次のようなヘッダを追加しますMessage-IdDateDKIM-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によってスパムと誤認1)を投稿してください
masegaloeh

私が送信しようとしたメールには、Toヘッダー、Subjectヘッダー、および1行の本文が含まれていました。Postfixがmilterを介して実行した後、どのヘッダーを持っているかをどのように判断するかわかりませんが、どのように知っていますか?ここでは、GmailのではPostfixによって処理され、拒否された方法は/ var / log / syslogの上映で出力されます: gist.github.com/DavidEGrayson/fbf65c8290c049a1f262
デビッド・グレイソン

回答:


8

実用的なソリューションがあるため、ここでは、Telnetでpostfix(SMTP)を使用する場合とsendmail(非SMTP)を使用する場合の異なる動作について説明します。

参考までに、OpenDKIMはMilterメカニズムを使用してpostfixによって呼び出されます。この公式ドキュメントを介して、postfixでのmilterの実装方法に関する情報を入手できます。こちらが後置のmilterフックの図です。

             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電子メールは、milterに挿入される前にクリーンアップによって処理されます。クリーンアップデーモンは:不足しているヘッダーの追加を担当していました:,へ:,メッセージ-IDから、(はResent-):,および日:。そのため、元のメールに不完全なヘッダーが含まれていたとしても、OpenDKIM milterにメールを挿入すると、メールのヘッダーは完全になります。

  • SMTPメールは、クリーンアップ処理が行われる前にOpenDKIM milterに注入されます。したがって、元のメールのヘッダーが不完全な場合、opendkimはメールへの署名を拒否する場合があります。投稿者:ヘッダが必須でした(参照RFC 6376)および電子メールはそれを持っていない場合、OpenDKIMは、電子メールに署名し、あなたに警告を与えることを拒否します

    can't determine message sender; accepting
    

私はdockerを使用しないので、コンテナ内のsendmail / pickupの制限がわからない。David Graysonの回避策は、OpenDKIMがメッセージに署名することを保証するのに十分安全だと思います。


それは啓発的でした。ありがとうございました。残念ながら、現在のソリューション(回答で説明)よりも優れたソリューションはまだありません。
デビッドグレイソン14

明らかな理由はFrom:、メールにヘッダーを追加するようにアプリを修正したことです:)
masegaloeh 14

しかし、私はMessage-Idあまり知らないものを追加する必要があり、おそらく間違っているでしょう...クリーンアップデーモンにそれを任せる方が簡単だと思われます。
デビッドグレイソン14

実際、RFC 6376が述べたように、Message-IDは必須ではありませんでした。デフォルトでは、必須ヘッダーはFromヘッダーのみでした。しかし、あなたがあなた自身のメッセージIDを生成する場合は、次のような勧告を使用することができ、このIETFドラフト
masegaloeh

6

setにあるpostfix configのinet_interfacesdocker bridge(docker0)を指す必要があります/etc/postfix/main.cf

inet_interfaces = <docker0_ip>

Dockerからのメールの送信、postfixのインストール、ホストへの送信の詳細な内部作業の詳細


リンクをありがとう!私にとって重要なのは172.17.0.0/16mynetworksin /etc/postfix/main.cfやのようなものを追加することでしたservice postfix restart
JSchirrmacher

5

私は現在同じ問題に取り組んでいるので、これは半分の答え、または少なくとも半分のテスト済みのものです。誰かが私が見逃したものを肉付けするのを手伝ってくれることを望んでいます。

OP(David Grayson)からの答えは、ポストドロップメールスプールの再発明のように思えますが、そのメールスプールを使用することは有望なアプローチのように聞こえるので、ここに行きました。

postfixが提供する/ usr / bin / sendmail互換性インターフェースは、sgid postdropであるpostdropにメールを渡し、メールを/ var / spool / postfix / maildropのmaildropキューに保存できるようにします。これは、Dockerコンテナで発生するはずです。postfixの残りの部分は、コンテナで実行する必要はないはずです。

したがって、私は/ var / spool / postfix / maildropと/ var / spool / postfix / publicをマウントするホストです。メールドロップキューディレクトリをマウントしているため、ホスト環境の/ var / spool / postfix / maildropにメールを配信できます。私が搭載されているので/var/spool/postfix/publicmaildrop信号を送ることができるpickupキューからメールを収集します。残念ながら、私がそれを気にしない限り、uidとgidが関係します。つまり、ホストディレクトリでのピックアップはスプールファイルを読み取れません。

それでも、これはうまくいくようです:

$ 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インストールは1つだけです。これらの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 runコマンドに引数を追加して、Dockerコンテナからアクセスできるようにする必要があります。


たぶん、mini_sendmailのようなものが役立つでしょうか?コンテナー隔離されたアプリとコンテナーホストシステム上のsendmailサーバーデーモンとの間のブリッジのように、コンテナーで使用されます。cyberciti.biz/tips/... acme.com/software/mini_sendmail
Mikl

SMTPを介してメールをPostfixに送信している場合、Postfixがメールをクリーンアップするとは思わない。おそらく、より構成可能なMTAがある場合(またはPostfixをより適切に構成する方法を見つけた場合)は機能します。
デビッドグレイソン14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.