AmazonSESの送信結果を取得するために、今回はAmazonSNSをトリガーとして、LambdaからDyanamoDBに保存する仕組みを作っていきたいと思います。
この方法はAWSのサポートでもありましたので、今回はそれを試してみます。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/lambda-sns-ses-dynamodb/
前提として、AmazonSESに関しては既に設定済としています。
こちら、[ブログ](https://ksysnote.com/uncategorized/aws-ses-sns-lambda-dynamodb/)でも公開しております。DynamoDBの設定
まずは、DynamoDBのコンソールからテーブルを「SESNotifiations」という名前で作成します。
- テーブル名に「SESNotifications」
- パーティションキーに「SESMessageId」
- ソートキーに「SESMailSendTime」
LambdaのIAMロールを設定
IAMロールの作成
次にLambda関数に付与する権限を作成するために、IAMコンソールからロールを作成していきます。
- 信頼されたエンティティの種類から「AWSサービス」を選択
- ユースケースの選択から「Lambda」を選択
Attachアクセス権限ポリシー
ロールにアタッチするポリシーを選択します。
- 「AWSLambdaBasicExecutionRole」を選択
タグの追加
今回はタグ無しで次へ
確認
ロール名を「lambda-ses-execution」としてロールを作成します。
インラインポリシーの追加
作成したロールを選択して、DynamoDBへアクセスできるようにインラインポリシーを追加していきます。
ロールの一覧から「lambda-ses-execution」を選択して、「インラインポリシーの追加」をクリックします。
ポリシーの作成
DynamoDBへの書き込み権限を与えるために「ビジュアルエディタ」から権限を設定していきます。
- サービスから「DyanamoDB」を選択
- アクションから「書き込み」の「PutItem」を選択します
- リソースの「ARNの追加」をクリックします。
- 「ARNの追加」から先程作成したDynamoDBの「ARN」を設定します。
Lambda関数
それでは、実際に関数を作成していきます。ここでは、先程IAMで作成したロールを選択します。
- 関数名に「sesnotificationscode」
- ランタイムは「Node.js 12.x」を選択
- 実行ロールは、先程作成した「lambda-ses-execution」を選択する
コード
SES通知の内容には「mailオブジェクト」「bonceオブジェクト」「deliveryオブジェクト」「complaintオブジェクト」があります。
その中身を解析してDynamoDBに保存していきます。
SES通知の内容についてもこちらを参照にして下さい。
https://docs.aws.amazon.com/ja_jp/ses/latest/DeveloperGuide/notification-contents.html
console.log('Loading event');
var aws = require('aws-sdk');
var ddb = new aws.DynamoDB({params: {TableName: 'SESNotifications'}});
exports.handler = function(event, context)
{
console.log('Received event:', JSON.stringify(event, null, 2));
var SESMessage = event.Records[0].Sns.Message
SESMessage = JSON.parse(SESMessage);
var SESMessageId = SESMessage.mail.messageId;
var SESMailSendTime = SESMessage.mail.timestamp;
var SESMessageType = SESMessage.notificationType;
var SESMailObject = JSON.stringify(SESMessage.mail);
var SESMailAddress = SESMessage.mail.destination.toString();
var LambdaReceiveTime = new Date().toString();
if (SESMessageType == 'Bounce')
{
var SESBounceObject = JSON.stringify(SESMessage.bounce);
var SESbounceType = SESMessage.bounce.bounceType;
var SESbounceSubType = SESMessage.bounce.bounceSubType;
var SESBounceFeedbackId = SESMessage.bounce.feedbackId;
var itemParams = {
Item: {
SESMessageId: {S: SESMessageId},
SESMailSendTime: {S: SESMailSendTime},
SESMailAddress: {S: SESMailAddress},
SESMessageType: {S: SESMessageType},
SESBounceObject: {S: SESBounceObject},
SESbounceType: {S: SESbounceType},
SESbounceSubType: {S: SESbounceSubType},
SESBounceFeedbackId: {S: SESBounceFeedbackId}
}};
ddb.putItem(itemParams, function(err, data)
{
if(err) { context.fail(err)}
else {
console.log(data);
context.succeed();
}
});
}
else if (SESMessageType == 'Delivery')
{
var SESDeliveryObject = JSON.stringify(SESMessage.delivery);
var SESDeliveryTime = SESMessage.delivery.timestamp;
var SESProcessingTimeMillis = SESMessage.delivery.processingTimeMillis.toString();
var itemParamsdel = {
Item: {
SESMessageId: {S: SESMessageId},
SESMailSendTime: {S: SESMailSendTime},
SESMailAddress: {S: SESMailAddress },
SESMessageType: {S: SESMessageType},
SESDeliveryObject: {S: SESDeliveryObject},
SESProcessingTimeMillis: {N: SESProcessingTimeMillis},
SESDeliveryTime: {S: SESDeliveryTime}
}};
ddb.putItem(itemParamsdel, function(err, data)
{
if(err) { context.fail(err)}
else {
console.log(data);
context.succeed();
}
});
}
else if (SESMessageType == 'Complaint')
{
var SESComplaintObject = JSON.stringify(SESMessage.complaint);
var SESComplaintFeedbackType = SESMessage.complaint.complaintFeedbackType;
var SESComplaintFeedbackId = SESMessage.complaint.feedbackId;
var itemParamscomp = {
Item: {
SESMessageId: {S: SESMessageId},
SESMailSendTime: {S: SESMailSendTime},
SESComplaintFeedbackType: {S: SESComplaintFeedbackType},
SESComplaintFeedbackId: {S: SESComplaintFeedbackId},
SESMailAddress: {S: SESMailAddress },
SESMessageType: {S: SESMessageType},
SESComplaintObject: {S: SESComplaintObject}
}};
ddb.putItem(itemParamscomp, function(err, data)
{
if(err) { context.fail(err)}
else {
console.log(data);
context.succeed();
}
});
}
};
SNSトピック
SNSトピックの作成
続いて、Lambda関数のトリガーとなるSNSトピックを「ses_notifications_repo」という名称で作成していきます。
トリガーの設定
Lambdaコンソールの「トリガーを追加」から、先程作成したSNSのトピックを選択すると簡単に設定がされます。
SES Notificationの設定
最後にSESからSNSのトピックを設定していきます。
SESコンソールのEamail Addressで今回対象となるメール選択して、NotificationsからSNSトピックの「ses_notifications_repo」を選択します。Bounes、Complaints、Deliveriesのそれぞれで設定します。
これで、SESから送信したメールの通知結果を、SNSがトリガーとなってLambda関数を実行して、DynamoDBに保存する仕組みができました。
テスト
「Send Test Email」からテスト配信をして、DynamoDBに保存されるか確認していきます。
toに宛先を指定すると確認することができます。
- 正常な配信の確認・・・success@simulator.amazonses.com
- バウンス ・・・bounce@simulator.amazonses.com
- 苦情 ・・・complaint@simulator.amazonses.com
https://docs.aws.amazon.com/ja_jp/ses/latest/DeveloperGuide/send-email-simulator.html