Lambda 함수를 사용하여 Amazon SNS를 통해 전송된 Amazon SES 알림을 DynamoDB에 저장하려면 어떻게 해야 하나요?

최종 업데이트 날짜: 2021년 2월 22일

Amazon Simple Notification Service(Amazon SNS)를 사용하여 Amazon Simple Email Service(Amazon SES)를 통해 전송되는 이메일에 대한 알림을 수신합니다. AWS Lambda 함수를 사용하여 이러한 알림을 Amazon DynamoDB 테이블에 저장하려면 어떻게 해야 하나요?

해결 방법

참고: 다음 예제 Lambda 함수를 템플릿으로 사용하여 메일 그룹을 호스팅하는 위치에 따라 CRM 또는 기타 대상에 데이터를 쓸 수 있습니다.

아직 설정하지 않았으면, Amazon SES로부터 알림을 수신하도록 구성된 Amazon SNS 주제가 있는 Amazon SES 계정(이메일 또는 도메인)을 설정합니다. 자세한 내용은 Amazon SNS를 사용하여 Amazon SES 알림 수신을 참조하세요.

그리고 나서 다음 작업을 수행합니다.

DynamoDB 테이블 생성

1.    다음 속성을 사용하여 DynamoDB에서 테이블을 생성합니다.
테이블 이름SESNotifications를 입력합니다.
기본 파티션 키SESMessageId를 입력합니다.
기본 정렬 키SnsPublishTime을 입력합니다.

2.    아래 표에 설명된 대로 보조 인덱스를 설정합니다. 이 구성을 통해 Lambda가 테이블을 쿼리하고 Amazon SES 보고서를 생성할 수 있습니다.

인덱스 이름 파티션 키 정렬 키
SESMessageType-Index SESMessageType(문자열) SnsPublishTime(문자열)
SESMessageComplaintType-Index SESComplaintFeedbackType(문자열) SnsPublishTime(문자열)

참고: 필요에 따라 보조 인덱스를 추가할 수 있습니다.

DynamoDB 테이블 생성에 대한 자세한 내용은 Amazon DynamoDB 시작하기를 참조하세요.

Lambda 함수의 IAM 역할에 DynamoDB 테이블을 호출할 수 있는 권한을 추가합니다.

다음을 수행하여 Lambda 함수가 DynamoDB:PutItem API를 호출할 수 있는 새 AWS Identity and Access Management(IAM) 역할을 생성합니다.

참고: 서로 다른 Lambda 함수에 대해 새로운 IAM 역할을 생성하고 사용하는 것이 가장 좋습니다. 여러 함수에서 역할을 재사용하지 마세요.

1.    IAM 콘솔의 왼쪽 탐색 창에서 [역할(Roles)]을 선택합니다.

2.    [역할 생성(Create Role)]을 선택합니다.

3.    [Select type of trusted entity]에서 [AWS service]를 선택합니다.

4.    사용 사례 선택에서 Lambda를 선택한 후 [다음: 권한(Next: Permissions)]을 선택합니다.

5.    연결 권한 정책에 대해 AWSLambdaBasicExecutionRole 관리형 정책 옆에 있는 확인란을 선택합니다. 그런 다음, [다음: 태그(Next: Tags)]를 선택합니다.

6.    (선택 사항) 사용 사례에 대한 역할에 IAM 태그를 추가합니다. 자세한 내용은 IAM 리소스 태그 지정을 참조하세요.

7.    [다음: 검토(Next: Review)]를 선택합니다.

8.    역할 이름*lambda_ses_execution을 입력합니다.

9.    [역할 생성(Create Role)]을 선택합니다.

10.    IAM 역할 보기로 돌아가서 생성한 역할을 선택합니다.

11.    [권한(Permissions)] 탭에서 [인라인 정책 추가(Add inline policy)]를 선택합니다.

12.    Visual editor 탭에서 [서비스 선택(Choose a service)]을 선택합니다.

13.    DynamoDB를 선택합니다. 그런 다음 [작업(Actions)]에서 검색 필드에 PutItem을 입력하고, 나타나는 드롭다운 목록에서 PutItem 옆에 있는 확인란을 선택합니다.

14.    리소스에서 [특정(Specific)]을 선택합니다. 그런 다음 [ARN 추가(Add ARN)]를 선택하고 생성한 DynamoDB 테이블의 ARN을 입력합니다.

15.    [Review policy]를 선택합니다.

16.    [이름(Name)]에 정책 이름을 입력합니다. 그런 다음 [정책 생성(Create policy)]을 선택합니다.

DynamoDB 테이블에 대한 액세스 권한을 부여하는 인라인 IAM 정책 예제

------------------------IAM Policy Begins---------------------------
{
    "Version": "2012-10-17",
    "Statement": [
         {
            "Sid": "Stmt1428510662000",
            "Effect": "Allow",
            "Action": [
                "DynamoDB:PutItem"
            ],
            "Resource": [
                "arn:aws:DynamoDB:us-east-1:12345678912:table/SESNotifications"
            ]
        }
    ]
}
------------------------IAM Policy Ends-----------------------------

Amazon SES 및 Amazon SNS 알림을 처리하는 Lambda 함수 생성

다음 샘플 코드를 사용하여 Lambda 함수를 생성한 후 이름을 sesnotificationscode라고 지정합니다. 함수를 생성할 때, 사용자가 생성한 lambda_ses_execution 역할을 해당 함수에 할당해야 합니다.

Amazon SES 및 Amazon SNS 알림을 처리하는 Lambda 함수 코드 예제

다음 예제 Lambda 함수 코드는 세 가지 유형의 Amazon SNS 알림을 확인합니다. 또한 이 함수는 연결된 Amazon SES 알림을 DynamoDB 테이블에 넣습니다. 알림 유형에 대한 자세한 내용은 Amazon SES의 Amazon SNS 알림 예제를 참조하세요.

중요: TableName 파라미터 SESNotifications를 DynamoDB 테이블의 이름으로 바꿉니다.

--------------------------Lambda Code Begins------------------------
console.log("Loading event");

var aws = require("aws-sdk");
var ddb = new aws.DynamoDB({ params: { TableName: "SESNotifications" } });

exports.handler = function (event, context, callback) {
  console.log("Received event:", JSON.stringify(event, null, 2));

  var SnsPublishTime = event.Records[0].Sns.Timestamp;
  var SnsTopicArn = event.Records[0].Sns.TopicArn;
  var SESMessage = event.Records[0].Sns.Message;

  SESMessage = JSON.parse(SESMessage);

  var SESMessageType = SESMessage.notificationType;
  var SESMessageId = SESMessage.mail.messageId;
  var SESDestinationAddress = SESMessage.mail.destination.toString();
  var LambdaReceiveTime = new Date().toString();

  if (SESMessageType == "Bounce") {
    var SESreportingMTA = SESMessage.bounce.reportingMTA;
    var SESbounceSummary = JSON.stringify(SESMessage.bounce.bouncedRecipients);
    var itemParams = {
      Item: {
        SESMessageId: { S: SESMessageId },
        SnsPublishTime: { S: SnsPublishTime },
        SESreportingMTA: { S: SESreportingMTA },
        SESDestinationAddress: { S: SESDestinationAddress },
        SESbounceSummary: { S: SESbounceSummary },
        SESMessageType: { S: SESMessageType },
      },
    };
    ddb.putItem(itemParams, function (err, data) {
      if (err) {
        callback(err)
      } else {
        console.log(data);
        callback(null,'')
      }
    });
  } else if (SESMessageType == "Delivery") {
    var SESsmtpResponse1 = SESMessage.delivery.smtpResponse;
    var SESreportingMTA1 = SESMessage.delivery.reportingMTA;
    var itemParamsdel = {
      Item: {
        SESMessageId: { S: SESMessageId },
        SnsPublishTime: { S: SnsPublishTime },
        SESsmtpResponse: { S: SESsmtpResponse1 },
        SESreportingMTA: { S: SESreportingMTA1 },
        SESDestinationAddress: { S: SESDestinationAddress },
        SESMessageType: { S: SESMessageType },
      },
    };
    ddb.putItem(itemParamsdel, function (err, data) {
      if (err) {
        callback(err)
      } else {
        console.log(data);
        callback(null,'')
      }
    });
  } else if (SESMessageType == "Complaint") {
    var SESComplaintFeedbackType = SESMessage.complaint.complaintFeedbackType;
    var SESFeedbackId = SESMessage.complaint.feedbackId;
    var itemParamscomp = {
      Item: {
        SESMessageId: { S: SESMessageId },
        SnsPublishTime: { S: SnsPublishTime },
        SESComplaintFeedbackType: { S: SESComplaintFeedbackType },
        SESFeedbackId: { S: SESFeedbackId },
        SESDestinationAddress: { S: SESDestinationAddress },
        SESMessageType: { S: SESMessageType },
      },
    };
    ddb.putItem(itemParamscomp, function (err, data) {
      if (err) {
        callback(err)
      } else {
        console.log(data);
        callback(null,'')
      }
    });
  }
};
------------------------Lambda Code Ends----------------------------

하나 이상의 Amazon SNS 주제에 대해 Lambda 함수 구독

아직 완료하지 않았으면, Amazon SNS 주제를 하나 이상 생성하고 해당 SNS 주제를 피드백 알림에 사용하도록 Amazon SES 이메일 도메인을 구성합니다. 그런 다음 Amazon SNS 콘솔 또는 Lambda 콘솔을 사용하여 다음을 수행합니다.

Amazon SNS 콘솔을 사용하여 Amazon SNS 주제에 대한 함수를 구독하는 방법

1.    Amazon SNS 콘솔의 왼쪽 탐색 창에서 [주제(Topics)]를 선택합니다. 그런 다음 반송 메일 알림에 대해 Amazon SES에서 사용되는 SNS 주제를 찾습니다. 예를 들어, ses_notifications_repo라는 SNS 주제를 찾습니다.

2.    SNS 주제의 ARN을 선택하여 [주제 세부 정보(Topic Details)] 페이지를 엽니다.

3.    [구독 생성(Create Subscription)]을 선택합니다.

4.    [프로토콜(Protocol)]에서 AWS Lambda를 선택합니다.

5.    [엔드포인트(Endpoint)]에 사용자가 생성한 Lambda 함수의 ARN을 입력합니다. 그런 다음, [구독 생성(Create Subscription)]을 선택합니다.

Lambda 콘솔을 사용하여 Amazon SNS 주제에 대한 함수를 구독하는 방법

1.    Lambda 콘솔에서 앞서 생성한 Lambda 함수를 선택합니다.

2.    구성 페이지의 [Designer] 창에서 [+트리거 추가(+Add trigger)] 버튼을 선택합니다.

3.    트리거 구성 드롭다운 목록에서 SNS를 선택합니다. [Designer] 아래에 구성 패널이 나타납니다.

4.    SNS 주제 드롭다운에서 함수를 구독할 SNS 주제를 선택합니다. 그런 다음 [추가(Add)] 버튼을 선택합니다.

이 Lambda 함수를 구독할 여러 알림 주제를 추가하려면 이 프로세스를 반복합니다.

Lambda 함수를 호출하는 Amazon SES 메시지를 전송하여 설정 테스트

테스트 메시지를 전송할 때 사용 가능한 메일박스 시뮬레이터 주소 중 하나를 사용하면 SES 전송 가능성 지표에 부정적인 영향을 미치지 않도록 합니다. 자세한 내용은 메일박스 시뮬레이터 사용을 참조하세요.

Amazon SES 메시지가 전송된 후 SES가 SNS 주제에 알림을 게시합니다. Amazon SNS는 이 알림을 SNS 이벤트 객체의 JSON 이스케이프 SES 이벤트 알림 객체로 Lambda에 전송합니다.

Lambda 콘솔을 사용하여 로컬 테스트를 위한 샘플 이벤트를 생성하려면 Amazon SES가 Amazon SNS에 게시하는 이벤트 데이터 예제를 참조하세요.

SES 반송 메일, 수신 거부, 전송 알림 예제는 Amazon SES가 Amazon SNS에 게시하는 이벤트 데이터 예제를 참조하세요.

DynamoDB에서 보고서를 다운로드하여 Amazon SES 알림을 확인합니다.

DynamoDB 테이블의 내용을 CSV 파일로 쿼리, 정렬, 다운로드하려면 다음을 수행합니다.

1.    DynamoDB 콘솔에서 SESNotifications 테이블을 선택합니다.

2.    [항목(Items)] 탭을 선택합니다.

3.    쿼리 또는 스캔 검색을 생성합니다. 자세한 내용은 데이터 쿼리 및 스캔에 대한 모범 사례를 참조하세요.

참고: DynamoDB 테이블 내보내기를 사용하여 Amazon Simple Storage Service(Amazon S3) 버킷에 파일을 정기적으로 다운로드하도록 예약할 수 있습니다. 자세한 내용은 Amazon S3로 DynamoDB 테이블 데이터 내보내기를 참조하세요.