2012年10月9日火曜日

SESのバウンス情報をSNS(HTTP)で通知してPHPで処理

スズキです。

下記でバウンスメールなどを簡単に発生させる(テストする)ことができるようになりました。

"Amazon SES Mailbox Simulator"を試してみた
その時に、通知をメールだけでなく、SNSでも行えることがわかったので、よく
メルマガ配信機能など作るときに実装するバウンスメールの処理を、このSNSでできないか
試してみました。


上記の記事では、下記のSNSのトピックに通知が行われるようになっており、


その通知先(サブスクリプション)はメールとしていました。

実は、この通知先に次のようにHTTP(S)を利用することも可能です。


登録すると確認メッセージが送信され、そのメッセージ中のURLにアクセスすることで
その通知先が承認されます。


通知先がメールの時は確認メールを受信して本文中のURLをクリックすれば
よかったのですが、HTTP(S)の場合はそうはいかず、確認メッセージは指定した
通知先URLにPOSTで送られて来ます。

なので、通知先URLは下記のようなPHPを配置しておきました。
<?php 
$json = file_get_contents("php://input");
error_log($json);
?>

この状態で上記の確認メッセージをPHPが受信すると、以下のようにエラーログに
出力されます。
[Mon Oct 08 21:41:06 2012] [error] [client 27.0.1.155] {
  "Type"             : "SubscriptionConfirmation",
  "MessageId"        : "0812b051-affc-4fd4-ba19-5f273d85cce2",
  "Token"            : "2336412f37fb687f5d51e6e241d09c81d...",
  "TopicArn"         : "arn:aws:sns:us-east-1:81111815109...",
  "Message"          : "You have chosen to subscribe to t...",
  "SubscribeURL"     : "https://sns.us-east-1.amazonaws.c...",
  "Timestamp"        : "2012-10-08T12:41:06.238Z",
  "SignatureVersion" : "1",
  "Signature"        : "rm9LegteKP4lOljphEMqtliGfv/NO6DvS...",
  "SigningCertURL"   : "https://sns.us-east-1.amazonaws.c..."
}
この"SubscribeURL"にアクセスすると、下記のようなXMLが表示され、


次のように、無事、通知先(サブスクリプション)が有効になります。


そして、ようやくSESでバウンスメールを発生させてみます。


すると、今度はエラーログに下記のようなバウンスメールの情報が出力されることが
わかります。

[Mon Oct 08 22:00:41 2012] [error] [client 27.0.1.155] {
  "Type" : "Notification",
  "MessageId" : "463fbb0b-63ea-4a6d-90c5-33c8686e3bd1",
  "TopicArn" : "arn:aws:sns:us-east-1:811118151095:suz-lab-ses",
  "Message" : "{
    \\"notificationType\\":\\"Bounce\\",
    \\"bounce\\":{
      \\"bounceType\\":\\"Permanent\\",
      \\"reportingMTA\\":\\"dns; a194-13.smtp-out.amazonses.com\\",
      \\"bouncedRecipients\\":[{
        \\"emailAddress\\":\\"bounce@simulator.amazonses.com\\",
 \\"diagnosticCode\\":
   \\"smtp; 5.1.0 - Unknown address error 550-'5.1.1 user unknown' (delivery attempts: 0)\\",
 \\"status\\":\\"5.0.0\\",
 \\"action\\":\\"failed\\"
      }],
      \\"bounceSubType\\":\\"General\\",
      \\"timestamp\\":\\"2012-10-08T13:00:39.000Z\\",
      \\"feedbackId\\":\\"0000013a40768691-29692462-1148-11e2-9...\\"
    },
    \\"mail\\":{
      \\"timestamp\\":\\"2012-10-08T13:00:39.000Z\\",
      \\"source\\":\\"suzuki@suz-lab.com\\",
      \\"messageId\\":\\"0000013a40768169-3ba4f620-da2b-4b4a-95...\\",
      \\"destination\\":[\\"bounce@simulator.amazonses.com\\"]
    }
  }",
  "Timestamp" : "2012-10-08T13:00:40.691Z",
  "SignatureVersion" : "1",  
  "Signature" : "FDNBWbFhc5MXs+2tjw327zXhiKca3GLHbbVEN8vUmLAmnj60...",
  "SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleN...", 
  "UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action..."
}
あとは、この情報を、パースして、解析して、データベースに登録して、...
など、いつものバウンスメールの処理ロジックを実行するだけです。

図にすると、こんな感じでしょうか?

  1. メールを送信
  2. バウンスメールが返ってくる
  3. バウンスメールをユーザーに転送 / SNSのトピックに通知
  4. SNSがHTTP(S)でELBにアクセス
  5. ELBがHTTPでEC2にアクセス(ELBで"SSL Termination")
  6. バウンス情報を S3 / RDS / DynamoDB に保存
バウンス情報を処理するEC2は、"Auto Scaling"で必要に応じて増減させることもできます!

でも、SQSを通知先(サブスクリプション)にしたほうが、もっといいかも...
--------
http://www.suz-lab.com

0 コメント: