【AWS】簡単!berkshelfとchefを使ってPostfixからSESでメールを送ってみた

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは植木和樹です。先日Developers.IO AWS関連ブログ500本目記念として、弊社 望月が英語ブログを投稿しました。

How to send Email from PHP application via Amazon SES | Developers.IO

ブログではEC2からSESをリレーしてメール送信するためのPostfix設定方法を紹介しています。/etc/postfixにいくつかファイルを用意するだけで、意外と簡単にSESが利用できるようですね。

既存システムをAWSへ移行するにあたって、アプリケーションの改修を行わず、サーバーからメールを手軽に送りたいという需要は多いのではないでしょうか。ということで、誰でも簡単にSESが利用できるようChefでPostfixを設定してみました。

事前準備

次のものを事前に準備しておきます。今回はSESをSandbox環境で使用するため、利用するメールアドレスを事前に認証しておきます。本番運用環境で使用する際には、別途AWSへのプロダクション申請とドメイン認証が必要になります。

  • メールを送るEC2サーバー(これにPostfixを設定する)
  • SES SMTP credentials(SESと通信する権限を持ったIAMユーザーのアクセスキーとシークレットキー)
  • 認証された 送信元メールアドレス
  • 認証された 送信先メールアドレス
  • knife-solo + berkshelfがインストールされたローカルマシン

メールを送るEC2サーバー

適当なEC2サーバーを用意してください。Postfixはchef-soloで設定するのでssh(tcp/22)の通信をセキュリティグループで許可しておきます。

SES SMTP credentials

マネージメントコンソールのSESの画面から「Create My SMTP Credentials」をクリックして、クレデンシャルを作成します。

20131109_chef_postfix-relay-ses_008

IAM User名を入力して「Create」します。

20131109_chef_postfix-relay-ses_009

SESを利用するためのIAMユーザーが作成されました。クレデンシャルファイルをダウンロードし、ファイルに記載されているアクセスキーとシークレットアクセスキーを控えておきましょう。

20131109_chef_postfix-relay-ses_010

認証された 送信元メールアドレス

今回はSESをSandbox環境で使用するため送信元アドレスをSESに登録しておきます。まずはマネージメントのSESの画面を開きます。

20131109_chef_postfix-relay-ses_001

画面左側の「Verified Senders - Email Addresses」をクリックしたら、「Verify a New Email Address」をクリックします。

20131109_chef_postfix-relay-ses_002

登録するメールアドレスを入力し「Verify This Email Address」をクリックします。

20131109_chef_postfix-relay-ses_003

入力したメールアドレス宛に認証確認メールが送信されます。

20131109_chef_postfix-relay-ses_004

送られたメールを開き、中央のURLを開きます。(リンクをクリック)

20131109_chef_postfix-relay-ses_005

メールアドレスが登録されました。

20131109_chef_postfix-relay-ses_006

マネージメントコンソールに戻って画面を更新すると、メールアドレスが「verified」になっていることが確認できます。これでこのメールアドレスからメールを送ることができます。

後述しますがEC2からメールを送る際にはsendmailコマンドのコマンドラインで、このメールアドレスを指定することになります。

20131109_chef_postfix-relay-ses_007

認証された 送信先メールアドレス

Sandbox環境では送信先メールアドレスも事前に登録が必要です。先ほどの送信元メールアドレス登録と同じ手順でメールアドレスを登録してください。今回はテストのため送信元と送信先のアドレスは同じものを使用しています。

設定作業

OpscodeのPublic CookbooksからPostfixのCookbookが利用できます。つまり自分でCookbookを作る必要はありません。各環境に合わせたAttributeを設定するためのJSONファイルをたった1つ用意するだけです。しかも変更するのはアクセスキーとシークレットキーのみ。簡単です。

$ cd ~/work/
$ knife solo init .
$ vi Berksfile
$ vi roles/postfix_ses_server.json
$ berks install
$ knife solo prepare -i keypair.pem ec2-user@12.34.56.78
$ knife solo cook -i keypair.pem ec2-user@12.34.56.78 -o "role[postfix_ses_server]"

Berksfile

site :opscode

cookbook "postfix"

roles/postfix_ses_server.json

{
  "name": "postfix_ses_server",
  "default_attributes": {
    "postfix" : {
      "main" : {
        "smtp_sasl_password_maps" : "hash:/etc/postfix/sasl_passwd",
        "relayhost" : "email-smtp.us-east-1.amazonaws.com:25",
        "smtp_sasl_auth_enable" : "yes",
        "smtp_use_tls" : "yes",
        "smtp_tls_security_level" : "encrypt",
        "smtp_tls_note_starttls_offer" : "yes",
        "smtp_tls_CAfile" : "/etc/ssl/certs/ca-bundle.crt"
      },
      "sasl" : {
        "smtp_sasl_user_name" : "<your_access_key>",
        "smtp_sasl_passwd" : "<your_secret_key>"
      }
    }
  },
  "json_class": "Chef::Role",
  "description": "This is a Role for setting up a postfix server",
  "chef_type": "role",
  "run_list": [
    "recipe[postfix::sasl_auth]"
  ]
}

動作確認

EC2にsshでログインしてメールを送ってみましょう。-tオプションでメッセージヘッダーから宛先アドレスを指定します。-fオプションで送信元アドレスを指定します。

$ sendmail -tf ueki.kazuki@example.com
To: ueki.kazuki@example.com
Subject: Test from Postfix SES relay server

TEST
.

送信先アドレスのメールを受信してみましょう。

20131109_chef_postfix-relay-ses_011

成功です!無事届いています。

メールのヘッダーを確認すると、Message-IDReturn-PathはSESのものになっています。

20131109_chef_postfix-relay-ses_012

今回はSandbox環境で事前に送信先アドレスを登録したので問題ありませんでしたが、送信エラーでバウンスメールが返ってきた時にはSESで受け付け、処理をしてくれます。詳しくは以下のブログを参照してください。

Amazon SESでSPFとDKIMを用いて高信頼なメールを送る | Developers.IO

mailコマンドでメール送信

mailxパッケージがインストールされていれば、sendmailコマンドでなくmailコマンドでメールを送ることができます。シェルスクリプトからメールを送りたい場合には便利です。

$ mail -r ueki.kazuki@example.com \
  -s "TEST from mail" \
  ueki.kazuki@example.com <<_EOM_
TEST
_EOM_

Postfixを使うメリット

Postfixを使ってSESを利用するメリットはなんでしょう?

ひとつはsendmailmailコマンドを使ってメールを送ることができる点です。またPHPのmail()関数は、デフォルトでローカルのメールサーバー経由でメール送信をするので、その点でもお手軽です。

これ以外に、メール送信に失敗した場合にはキューに保存され再送してくれる点も使い勝手がいいのではないでしょうか。

(Postfixを停止する)
$ sudo service postfix status
master (pid  28090) is running...
$ sudo service postfix stop
Shutting down postfix:                                     [  OK  ]

(Postfixサービスが停止している状態でメールを送る)
$ sendmail -tf ueki.kazuki@example.com
To: ueki.kazuki@example.com
Subject: Test from Postfix SES relay server

TEST (must be queued)
.

(配信できなかったメールはキューに溜まっている)
$ sudo mailq
postqueue: warning: Mail system is down -- accessing queue directly
-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
977ED41F22      258 Sat Nov  9 02:31:57  ueki.kazuki@example.com
                                         ueki.kazuki@example.com

-- 0 Kbytes in 1 Request.

(Postfixを起動するとキューに溜まったメールが送信される)
$ sudo service postfix start
Starting postfix:                                          [  OK  ]
$ sudo mailq
Mail queue is empty

まとめ

OpscodeのPublic Cookbooksを使うことで、とても簡単にSESを利用したメール送信設定ができました。複数のEC2からメールを送ろうとすると、個別にEIPが必要だったり、逆引き設定や必要だったりといろいろ面倒です。

Amazon EC2 Eメール送信ベストプラクティス

いろいろ悩むよりもSESを使うのがベストプラクティスです。さらにSESの信頼性をあげるためにはSPFやDKIMの設定も忘れないようにしましょう。

<

p class="aligncenter">Amazon SESでSPFとDKIMを用いて高信頼なメールを送る | Developers.IO