AWS SESで送信したメールの結果(配信・バウンス・苦情)をAWS SNS経由でAWS SQSに保存します。AWS SQSに保存した結果をさらにAPI経由で取り出したかったのですが、種別(配信・バウンス・苦情)によってJSON形式が異なっていたのでパースに手間取りました。それぞれの形式について記載します。

このAWS SES + AWS SNS + AWS SQSのバウンスメールの処理フローについては今回は書かないので下記のフォーラムを見てください。また、いずれどこかでやった記事を書きたいと思います。

Announcement: バウンス(Bounce)と苦情(Complaint)処理の自動化について

目次

  1. 概要
  2. AWS SQS保存メッセージ(JSON)
    1. 共通(JSON root)
    2. バウンス
    3. 苦情
    4. 配信
  3. AWS SQSに保存されているサンプル

概要


AWS SQSにAWS SNS経由で送信したメールの結果(配信・バウンス・苦情)を通知した場合にAWS SQSにはJSON形式でメッセージが保存されます。AWS SQSに保存されているJSONのMessageというキーに大元のAWS SESからの通知メッセージがJSON(をエスケープしたもの)形式で保存されます(要するに、ネストしたJSON形式で保存されます)

が、このMessageキーにネストしているJSON形式が種類(配信・バウンス・苦情)によって違います。というのをやり始めてから気づきました。で、公式ドキュメントAmazon SES への Amazon SNS 通知のコンテンツにそれぞれのJSONは記載されているのですが、種類が多いのとAWS SQSに保存されているrootからのネストしたJSONではなくて、AWS SNS送信時のJSONしか記載されていません。要するにパースするときに確認し辛かったので自分用のドキュメントとして書き残しときます。

なお、バウンスが何かとかはそのうち自分向けに書くつもりです。今回は書きません。

下記のJSONはC#でパースできたのでたぶんあってると思います。

AWS SQS保存メッセージ(JSON)


以下のJSONのうち、一部のキーの値は前述の公式ドキュメントから引用してます。
また、mailキー部の値については省略してますが、こちらもJSONが保存されています。

共通(JSON root)

AWS SQSに格納されているJSONです。下記のJSONのMessageキーにAWS SNS(大元はAWS SES)のJSONが保存されます。そのJSONが(配信・バウンス・苦情)によって形式が異なります。

1
2
3
4
5
6
7
8
9
10
11
{
"Type" : "Notification",
"MessageId" : "***************************",
"TopicArn" : "arn:aws:sns:us-west-2:**************:****",
"Message" : "AWS SNSからのメッセージ JSONをエスケープしたもの(配信・バウンス・苦情)で異なる",
"Timestamp" : "2016-11-08T07:46:15.902Z",
"SignatureVersion" : "1",
"Signature" : "**************************",
"SigningCertURL" : "******************",
"UnsubscribeURL" : "******************"
}

バウンス

バウンスの場合、前述のJSON rootのMessageキーに下記のJSONが格納されます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"notificationType": "Bounce",
"bounce": {
"bounceType": "Permanent",
"bounceSubType": "General",
"bouncedRecipients": [
{
"status": "5.0.0",
"action": "failed",
"diagnosticCode": "smtp; 550 user unknown",
"emailAddress": "recipient1@example.com"
},
{
"status": "4.0.0",
"action": "delayed",
"emailAddress": "recipient2@example.com"
}
],
"reportingMTA": "example.com",
"timestamp": "2012-05-25T14:59:38.605Z",
"feedbackId": "000001378603176d-5a4b5ad9-6f30-4198-a8c3-b1eb0c270a1d-000000"
},
"mail" : "JSONオブジェクト"
}

苦情

苦情の場合、前述のJSON rootのMessageキーに下記のJSONが格納されます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"notificationType": "Complaint",
"complaint": {
"userAgent": "AnyCompany Feedback Loop (V0.01)",
"complainedRecipients": [
{
"emailAddress": "recipient1@example.com"
}
],
"complaintFeedbackType": "abuse",
"arrivalDate": "2009-12-03T04:24:21.000-05:00",
"timestamp": "2012-05-25T14:59:38.623Z",
"feedbackId": "000001378603177f-18c07c78-fa81-4a58-9dd1-fedc3cb8f49a-000000"
},
"mail": "JSONオブジェクト"
}

配信

配信の場合、前述のJSON rootのMessageキーに下記のJSONが格納されます。

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"notificationType": "Delivery",
"delivery": {
"timestamp": "2014-05-28T22:41:01.184Z",
"processingTimeMillis": 546,
"recipients": [
"success@simulator.amazonses.com"
],
"smtpResponse": "250 ok: Message 64111812 accepted",
"reportingMTA": "a8-70.smtp-out.amazonses.com"
},
"mail": "JSONオブジェクト"
}

AWS SQSに保存されているサンプル


では最後にAWS SQSに保存されているJSONをrootから記述してみたいと思います。(mailキーの値は省略してます)
バウンスで書きましたが下記のようになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{  
"Type":"Notification",
"MessageId" : "***************************",
"TopicArn":"arn:aws:sns:us-west-2:**************:****",
"Message":{
"notificationType":"Bounce",
"bounce":{
"bounceType":"Permanent",
"bounceSubType":"General",
"bouncedRecipients":[
{
"status":"5.0.0",
"action":"failed",
"diagnosticCode":"smtp; 550 user unknown",
"emailAddress":"recipient1@example.com"
},
{
"status":"4.0.0",
"action":"delayed",
"emailAddress":"recipient2@example.com"
}
],
"reportingMTA":"example.com",
"timestamp":"2012-05-25T14:59:38.605Z",
"feedbackId":"000001378603176d-5a4b5ad9-6f30-4198-a8c3-b1eb0c270a1d-000000"
},
"mail":"JSONオブジェクト"
},
"Timestamp":"2016-11-08T07:46:15.902Z",
"SignatureVersion":"1",
"Signature":"**************************",
"SigningCertURL":"******************",
"UnsubscribeURL":"******************"
}

あとはこいつを煮るなり焼くなりするだけです。