ラベル ses の投稿を表示しています。 すべての投稿を表示
ラベル ses の投稿を表示しています。 すべての投稿を表示

2013年1月9日水曜日

SESってなんじゃ?(突然postfixでSMTPリレー)

先日、突然EC2からのメール送信が必要ということが発覚したときの顛末を書いてみます。

公開日当日に、突然以下のような内容のメールが届きました。

Dear EC2 Customer,
You recently reached a limit on the volume of email you were able to send out of SMTP port 25 on your instance:xxxxxxx

EC2内のMTAからメールを送信するプログラムでは、そのままだと、上記のようなメールが届き、メールの送信制限に引っかかります。

そのため、メールの上限解除申請フォームから解除申請とメールドメインの逆引き申請を行う必要がありました。

この時点で例えば以下の内容(メールアドレスやサーバー名などはサンプルです)で、メールを送ってみると、
# php -a
> mail("memorycraft@gmail.com", "Subject1", "Body", "From: server@memorycraft.jp");

この時点ではメールヘッダの内容は、例として以下のように、なっていました。
Return-Path: <root@ip-10-132-10-146.localdomain>
Received: from ip-10-132-10-146.localdomain (ec2-54-248-82-123.ap-northeast-1.compute.amazonaws.com. [54.248.82.123])
        by mx.google.com with ESMTP id qc4si62972240pbb.326.2013.01.08.08.20.17;
        Tue, 08 Jan 2013 08:20:17 -0800 (PST)
Received-SPF: neutral (google.com: 54.248.82.123 is neither permitted nor denied by best guess record for domain of root@ip-10-132-10-146.localdomain) client-ip=54.248.82.123;
Authentication-Results: mx.google.com; spf=neutral (google.com: 54.248.82.123 is neither permitted nor denied by best guess record for domain of root@ip-10-132-10-146.localdomain) smtp.mail=root@ip-10-132-10-146.localdomain
Received: by ip-10-132-10-146.localdomain (Postfix, from userid 0)
 id E5D5C1E1D; Wed,  9 Jan 2013 01:20:16 +0900 (JST)

Received-SPFとAuthentication-Resultsがneutralなのがまずそうです。
これらがpassになっていないと、メーラーによっては迷惑メールとして扱われてしまうことがあるようです。


一応申請したものの、すぐに解除されるわけではないので、次善策としてSESを利用するのはどうかという意見がありました。
そこで、まずプロダクション使用申請フォームからSESのプロダクション申請を行いました。
ただし、これもすぐには通らないので、既にプロダクションモードになっている別の社内アカウントのSESを一時的に使うことにしました。

まず、SESで送信元のメールアドレスを認証させるために、メールアドレスを登録します。



確認メールが送られてくるので、リンクをクリックして認証します。すると以下のような画面が現れます。



また、SESのAPIを使うようなプログラムの変更はなるべく避けたいのでメールを送信しているEC2内のpostfixからリレーしないといけません。
ここで、suz-labブログの記事「PostfixからSESにリレー(stunnel使わない編)」が助けてくれました。

それにしたがって設定していきます。
/etc/ssl/certs/ca-bundle.crtがあることを確認して、/etc/postfix/main.cfの末尾に以下を追記します。
relayhost = email-smtp.us-east-1.amazonaws.com:25
smtp_sasl_auth_enable = yes
smtp_sasl_security_options = noanonymous
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
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_passwordファイルを作ります。
SMTP用のIAMを作るためにAWS ConsoleのSESのSMTP Settingsから「Create My SMTP Credentials」ボタンでアクセスキーとシークレットキーを取得します。
muramasaさんによると、ここではIAMで普通に作成してもダメで、SESのSMTP Settingsから作成しないと行けないそうです。



そして、取得したアクセスキー、シークレットキーを元に、sasl_passwordファイルを作成します。
# echo "email-smtp.us-east-1.amazonaws.com:25 xxxxxxxxxxxxxxxxxxx:yyyyyyyyyyyyyyyyyyy" > /etc/postfix/sasl_password


sasl_passwordファイルを検索テーブルに設定します。
# postmap hash:/etc/postfix/sasl_passwd

再起動します。
# /etc/init.d/postfix restart

これでメールを送ってみます。
# php -a
> mail("memorycraft@gmail.com", "Subject2", "Body", "From: server@memorycraft.jp");


メールが届きません。
/var/log/mailogを見てみると、、
Jan  9 03:06:09 ip-10-132-134-107 postfix/smtp[11252]: warning: SASL authentication failure: No worthy mechs found
Jan  9 03:06:09 ip-10-132-134-107 postfix/smtp[11252]: 9CA2413E5: SASL authentication failed; cannot authenticate to server email-smtp.us-east-1.amazonaws.com[54.243.73.188]: no mechanism available

となっており、SASL認証に必要なライブラリが無いようです。
以下のように、ライブラリをインストールします。
# yum -y install cyrus-sasl-plain cyrus-sasl-md5

もう一度送信してみますが、メールは届きません。。

maillogには以下のようになっていました。
Jan  9 04:04:51 ip-10-132-10-146 postfix/qmgr[31664]: CE9C11E25: from=<root@ip-10-132-10-146.localdomain>, size=362, nrcpt=1 (queue active)
Jan  9 04:04:54 ip-10-132-10-146 postfix/smtp[31726]: CE9C11E25: to=<memorycraft@gmail.com>, relay=email-smtp.us-east-1.amazonaws.com[23.21.84.203]:25, delay=2.5, delays=0.03/0/1.6/0.87, dsn=5.0.0, status=bounced (host email-smtp.us-east-1.amazonaws.com[23.21.84.203] said: 554 Message rejected: Email address is not verified. (in reply to end of DATA command))

Email address is not verified. となっており、メールアドレスが認証されていないようです。 
これは、Fromヘッダでしか送信元を設定していないためで、Return-Path(エンベロープFrom)に送信元メールアドレスをセットしてあげる必要があるようです。


 この場合、送信コマンド側でMTAにReturnPathを渡します。 
PHPのmailコマンドの場合は以下のように第4引数で-fオプションを渡します。
# php -a
> mail("memorycraft@gmail.com", "Subject30", "Body", "From: server@memorycraft.jp", "-fserver@memorycraft.jp");

すると、正常に送信され、届いたメールのヘッダも以下のようにpassになりました。
Received-SPF: pass (google.com: domain of 0000013c1b944998-1b5393d9-728a-496a-8c9d-2bbf57427150-000000@amazonses.com designates 199.255.194.183 as permitted sender) client-ip=199.255.194.183;
Authentication-Results: mx.google.com; spf=pass (google.com: domain of 0000013c1b944998-1b5393d9-728a-496a-8c9d-2bbf57427150-000000@amazonses.com designates 199.255.194.183 as permitted sender) smtp.mail=0000013c1b944998-1b5393d9-728a-496a-8c9d-2bbf57427150-000000@amazonses.com
Return-Path: 0000013c1b944998-1b5393d9-728a-496a-8c9d-2bbf57427150-000000@amazonses.com


ちなみに、

cakePHPの場合
$config['additionalParameters'] = '-f '.$from_address;
$email = new CakeEmail();
$email->transportClass()->config($config);
$email->from(array($from_address=>'Information'))
->to($target)
->subject($mail_title)
->send($mail_message);


FuelPHPの場合
$email = Email::forge();
$email->from($from_address);
$email->to($target);
$email->subject($mail_title);
$email->return_path($from_address);
$email->body($mail_message);
$mail->send();

のようにするようです。
ひとまず解決し、ほっとしました。

意外と見落としがちなメール送信ですが、いざというとき、どの方法をとっても新規からではなんらかの申請が必要になり、即時反映は難しそうでした。
こういった場合のために、常に一時的なリレー用のSESを確保しておくのは有りかも知れません。

以上です。

2011年12月14日水曜日

SESってなんじゃ?(SMTPがサポートされました)

SESにSMTP機能がサポートされました。
メーラーでもSendmailやPostfixでも利用できるのは素晴らしいですね。
今回は試しにmiura@cloudpack.jpのメールアドレスで、GmailからSESを経由してHotmailにメール送信してみたいと思います。


SESの設定


AWSコンソールのSESタブを開くと、「SMTP Settings」というメニューが増えています。


これを開くと、SMTPサーバーの基本情報が表示されます。
Server Name: email-smtp.us-east-1.amazonaws.com
Port: 465
TLS: Yes
Authentication: Your SMTP credentials

Authenticationの欄にある通り、SMTPで送信するには、SMTP認証用のIAMユーザーを作る必要があり、画面中央の「Create My SMTP Credential」を押すと手順に従って設定できます。


ボタンを押すと、自動的にIAMタブに遷移し、「Create User for SMTP」というダイアログが開き、SMTP用のIAMユーザーを登録します。ここにSMTP用のIAMユーザー名を入力して、「Create」ボタンを押します。



すると、作成完了のダイアログが表示されます。
Credential情報は「Show User SMTP Security Credential」で表示されます。


Credential情報はファイルとして「Donwload Credential」でダウンロードし保管しておきます。
"Iam User Name","Smtp Username","Smtp Password"
"smtp-memorycraft","ACCESS_KEY******","SECRET_KEY******"


ダウンロードが終わり、ダイアログを閉じると再びSESタブに自動遷移します。
SESのダッシュボードを表示し、メール送信者を追加するために、「Verify a New Sender」をクリックします。



ここで、今回SMTPで送信したい送信者のメールアドレスを入力し、「Submit」をクリックます。



すると、そのメールアドレス宛に認証用のメールが届くので、認証リンクをクリックします。



AWSの画面が表示され、認証が完了した旨のメッセージが表示されています。これで送信者の認証が完了しました。


SESは無償では、認証したメールアドレスに対してしか送信できないため、テスト受信用のメールアドレスもこれと同様にして認証しておきます。(手順は同様なので、割愛します。)



メールクライアント( Gmail ) の設定


次にGmailのSMTP設定を行います。 「設定<アカウントとインポート」 タブの「名前」欄で送信者のメールアドレスを追加します。今回は既にGmail経由送信で設定済みだったので、「編集」で設定を変えてみます。



「次のステップ」を押すと、「Gmail経由で送信する」が選択されているので、「SMTPサーバー経由で送信する」のほうをクリックして選択します。すると、SMTPサーバー、ポート、ユーザー名、パスワード、接続プロトコルの入力欄が表示されます。
SESのSMTP Settingsに記載のあったように、SMTPサーバー名とポート、プロトコルを入力します。

Server Name: email-smtp.us-east-1.amazonaws.com
Port: 465
TLS: Yes
Authentication: Your SMTP credentials

また、ダウンロードしたcredential.csvに記載されている、Smtp UsernameとSmtp Passwordをユーザー名、パスワードに入力します。



ここで、「変更を保存」をクリックすると、有効性のチェックが始まるのですが、下記のようなエラーがでました。



どうやらTLS接続だとうまく設定できないようです。接続プロトコルをSSLにしたら、設定が成功したのでこのまま進みます。
登録が完了すると、「名前」欄が以下のような表示に変わり、AWSを使ったSMTP接続が設定されていることが確認できます。




それでは実際にメールを送信してみます。以下の内容のメールを「Verify User」で登録しておいたhotmailアドレス宛に送信します。



hotmail側を見てみると、、、


おおー、受け取れています!
アプリケーションなどでもSDKではなく、従来のSMTP送信でメール配信することができますね。

以上です。

2011年10月31日月曜日

SESってなんじゃ?(AWSコンソールにSESが登場)

今回はSESについてです。
アプリケーションを開発する際、ユーザーにメールを一斉送信するような場合が多い時に、メールサーバーの負荷やパフォーマンスに対するコストは忘れがちですが意外とかかり、そのため外部のメール配信専用のサービスを利用することも多いかと思います。
SESは一括メール送信のためのサービスで、EC2でEメールを配信する際には是非つかいたいサービスです。


そのSESがAWSコンソール上で管理できるようになりました。
早速触ってみたいと思います。


AWSコンソールを開くと、右側にSESのタブが表示されていることがわかります。
SESタブを選択すると、SESのダッシュボードが表示されます。



まずは、メールの送信者のメールアドレスを登録します。
「DashBoard」から「Verify a New Sender」のボタンを押すと、下のようにダイアログが表示されるので、送信者のEメールアドレスを入力して「Submit」を押します。


すると、入力したメールアドレスに、確認用のメールが送られる旨のメッセージが表示されます。


AWSサービスから、入力したメールアドレス宛に送信者確認のリンクが記載されたメールが届くので、リンクをクリックしてメールアドレスの実在確認を行います。


リンクをクリックすると、AWSサービスの画面がブラウザに表示され、認証が完了します。


AWSコンソールに戻り、左ペインの「Verified Senders」メニューをクリックすると、右ペインに先ほど登録した送信者のアドレスが表示されています。



 送信者アドレスの右に「Send Test Email」というテスト送信が出来るリンクがあるのでクリックしてみます。
すると、テスト送信用のダイアログが表示されます。
SESでのテスト送信は登録した送信者宛にしか送信できません。
ここでは、先ほどの認証された送信者アドレスの一覧から送信先を選択します。
また、件名と本文を入力し、「Send Test Email」をクリックします。


無事送信者アドレスに、メールが届きました。


 アプリケーションで動的にユーザーに送信するときなど、登録されていないメールアドレスに送信する場合には、「Dash Board」から、「Request Production Access」のボタンを押し、プロダクション環境での利用申請を行うことで、未登録アドレスへの送信が可能になります。





 また、「Dash Board」でメールの使用状況などの統計がわかり、管理しやすくなりました。
本日は以上です。