【AWS】EC2インスタンスからPostfix + SESで外部へシステムメールを送信

はじめに

本サイトは、AWS上のEC2インスタンスに構築されています。
構築当初、EC2インスタンス上のシステム通信用に直接外部にメール送信をしようと試みていたのですが、設定調査の時間が取れず実はメールが送信できていない状態のままでした。(コンタクトフォームからご連絡いただいていた方がいたら申し訳ありません)

今回、きちんと通知メールを送信できるように、以下の設計方針でPostfixとAmazon Simple Email Service(以下SES)を組み合わせたサーバからのメール送信の基盤を構築しました。

[設計方針]

  • EC2インスタンス
    • EC2インスタンス上のアプリケーションは、OS標準のsendmailコマンドを利用して自ホストのPostfixをメールを送信する
    • アプリケーションの送信元メールアドレスは、SESに登録済みのGmailアドレスを使用する
    • Postfixは、ローカル配送対象以外の宛先のメールをSESへ外部配送する
    • PostfixとSES間のSMTP接続では、SMTP認証(SASL認証)を行い、接続後はSTARTTLSで通信を暗号化する
  • SES
    • SESは、Postfixから着信したメールの送信元メールアドレスを確認し、登録済みアドレスの場合はメールを外部へ配送する
    • 送信元と宛先のメールアドレスはGmailの同じメールアドレスを使用する(設定例ではtest@gmail.comと表記)
    • 送信元サーバとメールアドレスがマッチしていないので、メール受信時にGmailの迷惑メールフォルダに振り分けられる可能性があるが、許容して手動で迷惑メール除外を行う

前提条件

本作業の前提条件は以下の通りです。

  • EC2インスタンスのOSはAmazon Linux 2
  • AWS マネジメントコンソールには、SESの操作権限を持つIAMユーザでログイン
  • EC2インスタンス上の操作はroot権限を持つユーザで実施
  • SESの送信元メールアドレス用に、予め外部サービスのメールアカウントを作成しておく(今回はGmailを使用)

本設定を行うシステムの全体構成は以下の通りです。

SESの設定

AWS マネジメントコンソールから、SESのメール中継設定を行います。

送信元メールアドレスの登録

SESは、予め確認の取れたメールアドレスが送信元のメールしか中継を行いません。そのため、送信元メールアドレスがユーザ自身のものであることを証明する作業を行います。

Amazon SES コンソール (https://console.aws.amazon.com/ses/) にアクセスし、「Email Addresses」→「Verify a New Email Address」を押下します。

メールアドレスの新規登録画面が表示されるので、送信元として登録したいメールアドレスを入力し、「Verify This Email Address」を押下します。ここで登録するメールアドレスは、現時点で受信が可能なものを使用してください。

指定したメールアドレスに確認メールが送信された旨のメッセージが表示されるので、「Close」を押下して一旦登録画面を閉じます。

登録したメールアドレス宛に以下のメールが届くので開封します。

メール本文に確認用のURLリンクが記載されているので開きます。

検証に成功した旨のメッセージが表示されたことを確認し、同画面を閉じます。

Amazon SES コンソールの「Email Addresses」を開き、登録したメールアドレスが「verified」と表示されていることを確認します。これで、送信元メールアドレスを登録できました。

サンドボックス解除のリクエスト

前述の送信元メールアドレスを登録しただけでは、SESは登録した送信元メールアドレスにしかメールを送れません。これをサンドボックスと言います。
サンドボックスを解除して、外部のメールアドレス宛にメールを送ることができるように、AWSのサポートページからリクエストを行います。

Amazon SES コンソール (https://console.aws.amazon.com/ses/) にアクセスし、「Sending Statistics」→「Request a Sending Limit Increase」を押下します。

サポートケースの作成画面が表示されるので、「Create case」のセクションにて「Service limit increase」を選択します。

「Case classification」のセクションでは、「Limit type」を「SES 送信制限」に指定します。それ以外の項目は用途に応じて適宜記入します。

「Requests」のセクションでは、「リージョン」に送信元メールアドレスを登録したリージョンを選択します。「Limit」は「希望する一日あたりの送信クォータ」を選択し、「New limit value」には1日に送信し得る最大メール通数を記入します。

「Case description」には、サポートケースを起票する理由を記入します。ここまで完了したら、「Submit」を押下し、サポートケースを起票します。

AWS マネジメントコンソールの右上の「サポート」→「サポートセンター」を選択すると、起票したサポートケースを確認できます。

1日程すると、リクエストが承認されます。承認時は、AWSアカウントに登録しているメールアドレス宛に以下のメールが送信されます。これで、サンドボックス解除のリクエストは完了です。

SMTP認証情報の取得

EC2からSESのエンドポイントにSMTP接続を行うにはSMTP認証が必要です。SMTP認証用の認証情報(クレデンシャル)を取得します。

Amazon SES コンソール (https://console.aws.amazon.com/ses/) にアクセスし、「SMTP Settings」を押下します。
「Server Name:」の項目は、後ほどPostfixの設定の中で、SESエンドポイントの指定で使用するので情報を控えておきます。
「Create My SMTP Credentials」を押下します。

SESのSMTPユーザ用IAMユーザの名前を尋ねられるので、デフォルトのままにするか任意の名前を入力し、「作成」を押下します。

「認証情報のダウンロード」を押下します。なお、ここで認証情報をダウンロードせずに「閉じる」を押下してしまうと、二度と該当IAMユーザの認証情報を取得できなくなるので注意してください。

credentials.csvという名前のCSVファイルがダウンロードされるので、ファイルを開きます。「Smtp Username」と「Smtp Password」の列が、それぞれユーザ名とパスワードを示します。

上記を確認した後、「閉じる」を押下します。これで、SMTP認証情報の取得は完了です。

EC2インスタンスの設定

Postfixの設定

EC2インスタンス上のPostfixを設定します。root権限を持つユーザでログインします。

main.cfの設定

main.cfの設定は、/etc/postfix/main.cfをテキストエディタで直接編集することも可能ですが、今回は手順化しやすいようにpostconfコマンドでシェルから追加していきます。

メールのリレー先(中継サーバ)に、SESのエンドポイントを指定します。
SESのエンドポイントは、SMTP認証情報の取得の際に控えておいた情報を使用します。

# postconf -e "relayhost = [email-smtp.us-east-1.amazonaws.com]:587"

SASL認証の設定を追加します。

# postconf -e "smtp_sasl_auth_enable = yes" \
"smtp_sasl_security_options = noanonymous" \
"smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd"

TLSによる外部配送暗号化の設定を追加します。

# postconf -e "smtp_use_tls = yes" \
"smtp_tls_loglevel = 1" \
"smtp_tls_security_level = encrypt" \
"smtp_tls_note_starttls_offer = yes" \
"smtp_tls_CAfile = /etc/ssl/certs/ca-bundle.crt"

メール配送を許可する送信元ネットワークをループバックアドレスに限定し、オープンリレーを防止します。

# postconf -e "mynetworks = 127.0.0.0/8"

sasl_passwdの設定

viなどのテキストエディタで、SMTP認証情報を格納するファイルを開きます。ファイルが存在しない場合は新規作成します。

# vi /etc/postfix/sasl_passwd

SES用認証情報の取得で得られた認証情報を使用して、メール中継先のSESエンドポイントに対応するユーザ名とパスワードを指定します。ユーザ名とパスワードは:で連結して記載します。

[email-smtp.us-east-1.amazonaws.com]:587 <ユーザ名>:<パスワード>

認証情報が記載された重要なファイルなので、所有権とアクセス権を変更してrootユーザのみファイルを編集できるようにします。

# chown root:root /etc/postfix/sasl_passwd
# chmod 600 /etc/postfix/sasl_passwd

認証情報のハッシュマップDBを作成

先ほど作成したsasl_passwdのハッシュマップDBファイルを作成します。

# postmap hash:/etc/postfix/sasl_passwd

認証情報が記載された重要なファイルなので、所有権とアクセス権を変更してrootユーザのみファイルを編集できるようにします。

# chown root:root /etc/postfix/sasl_passwd.db
# chmod 600 /etc/postfix/sasl_passwd.db

設定の有効化

設定を有効化するため、postfixサービスを再起動します。

# systemctl restart postfix

メール送信テスト

EC2インスタンス上で以下のコマンドを実行し、外部へのメール送信をテストします。
送信元メールアドレスは、SESに登録したものを指定します。宛先メールアドレスは、自分が受信可能なものを指定します。
本文の最後のピリオドを入力した時点で、それまでの内容がメール送信されます。

# sendmail -f <送信元メールアドレス> <宛先メールアドレス>
From: <送信元メールアドレス>
Subject: <件名>
<本文>     
.

メール送信実施後、ログファイルに以下のログが表示されます。末尾から2行目で、smtpプロセスによるメール送信結果がstatus=sentと表示されていれば、送信は成功です。

# tail /var/log/maillog
(略)
Nov  9 14:58:36 ip-xx-xx-xx-xx postfix/pickup[2808]: B65B3C848CA: uid=0 from=<test@gmail.com>
Nov  9 14:58:36 ip-xx-xx-xx-xx postfix/cleanup[2813]: B65B3C848CA: message-id=<20191109145836.B65B3C848CA@ip-ip-xx-xx-xx-xx.ec2.internal>
Nov  9 14:58:36 ip-xx-xx-xx-xx postfix/qmgr[2809]: B65B3C848CA: from=<test@gmail.com>, size=300, nrcpt=1 (queue active)
Nov  9 14:58:36 ip-xx-xx-xx-xx postfix/smtp[2815]: Trusted TLS connection established to email-smtp.us-east-1.amazonaws.com[18.214.81.247]:587: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
Nov  9 14:58:37 ip-xx-xx-xx-xx postfix/smtp[2815]: B65B3C848CA: to=<test@gmail.com>, relay=email-smtp.us-east-1.amazonaws.com[18.214.81.247]:587, delay=16, delays=16/0.02/0.09/0.16, dsn=2.0.0, status=sent (250 Ok 0100016e50ac90c5-e5a0bfbd-f957-4deb-9ebc-634e37e035b4-000000)
Nov  9 14:58:37 ip-xx-xx-xx-xx postfix/qmgr[2809]: B65B3C848CA: removed

yossy へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です