Help us understand the problem. What is going on with this article?

SESのトラッキングデータをKinesis経由でS3に保存するまでをTerraformで実施

More than 1 year has passed since last update.

概要

SESでの開封・クリックのトラッキングについてはいくつか記事がありますが、それをTerraformで実現したという情報はあまり見当たらないのでまとめました。

SESはトラッキングデータをCloudWatch、Kinesis Firehose、SNSに送ることができます。
今回はKinesis Firehose経由でS3に保存します。

Untitled Diagram (1).png

SESでの開封・クリックの取得の仕組み

開封・クリックのトラッキングには、HTMLメールを使用する必要があります。
開封のトラッキングは、HTMLメールの末尾に画像が添付されることで実現されます。
クリックのトラッキングは、メール内のリンクがSESによって自動的に書き換えられ、あるURLを経由したリダイレクトとなることで実現されます。

variable.tfの記述

variables.tfに変数を定義します。

variable "name_prefix" {
  default = "ses-tracking"
}

variable "s3_bucket" {
  default = "xxx"
}

main.tfの記述

Provider

SESが利用できるリージョンを指定します。

# ######## #
# Provider #
# ######## #

provider "aws" {
  version = "~> 1.51"
  region  = "us-east-1"
}

S3

# ## #
# S3 #
# ## #

resource "aws_s3_bucket" "bucket" {
  bucket        = "${var.s3_bucket}"
  acl           = "private"
  force_destroy = true
}

CloudWatch Logs

Kinesis FirehoseのエラーログをCloudWatch Logsに出力するよう、ロググループとログストリームを作成します。

# ############### #
# CloudWatch Logs #
# ############### #

resource "aws_cloudwatch_log_group" "cloudwatch_log_group" {
  name = "${var.name_prefix}-cloudwatch-log-group"
}

resource "aws_cloudwatch_log_stream" "cloudwatch_log_stream" {
  name           = "${var.name_prefix}-cloudwatch-log-stream"
  log_group_name = "${aws_cloudwatch_log_group.cloudwatch_log_group.name}"
}

Kinesis Firehose

S3とCloudWatch Logの権限を与えて、Kinesis Firehoseを作成します。
動作確認を素早く行うため、buffer_intervalを最短の60に設定します。

# ####### #
# Kinesis #
# ####### #

resource "aws_kinesis_firehose_delivery_stream" "firehose" {
  name        = "${var.name_prefix}-kinesis-firehose"
  destination = "s3"

  s3_configuration {
    role_arn        = "${aws_iam_role.firehose_role.arn}"
    bucket_arn      = "${aws_s3_bucket.bucket.arn}"
    buffer_size     = 5
    buffer_interval = 60
    cloudwatch_logging_options {
      enabled = true
      log_group_name = "${aws_cloudwatch_log_group.cloudwatch_log_group.name}"
      log_stream_name = "${aws_cloudwatch_log_stream.cloudwatch_log_stream.name}"
    }
  }

}

resource "aws_iam_role" "firehose_role" {
  name               = "${var.name_prefix}-firehose-role"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "firehose.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_role_policy" "firehose_role_policy" {
  name   = "${var.name_prefix}-firehose-role-policy"
  role   = "${aws_iam_role.firehose_role.id}"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": [
        "s3:AbortMultipartUpload",
        "s3:GetBucketLocation",
        "s3:GetObject",
        "s3:ListBucket",
        "s3:ListBucketMultipartUploads",
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::${aws_s3_bucket.bucket.bucket}",
        "arn:aws:s3:::${aws_s3_bucket.bucket.bucket}/*"
      ]
    },
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": [
        "logs:PutLogEvents"
      ],
      "Resource": [
        "${aws_cloudwatch_log_stream.cloudwatch_log_stream.arn}:*"
      ]
    }
  ]
}
EOF
}

SES Configuration Set

Kinesis Firehoseの権限を与えて、SESのConfiguration SetとEvent Destinationを作成します。
matching_typesは必要なものだけ指定しましょう。
メール送信時にこのConfiguration Setを利用することで、トラッキングが行われます。

resource "aws_ses_configuration_set" "ses_configuration_set" {
  name = "${var.name_prefix}-ses-configuration-set"
}

resource "aws_ses_event_destination" "kinesis" {
  name                   = "${var.name_prefix}-event-destination-kinesis"
  configuration_set_name = "${aws_ses_configuration_set.ses_configuration_set.name}"
  enabled                = true

  matching_types         = ["send", "reject", "bounce", "complaint", "delivery", "open", "click", "renderingFailure"]

  kinesis_destination = {
    stream_arn = "${aws_kinesis_firehose_delivery_stream.firehose.arn}"
    role_arn   = "${aws_iam_role.ses_role.arn}"
  }

  depends_on = ["aws_iam_role_policy.ses_role_policy"]
}

resource "aws_iam_role" "ses_role" {
  name               = "${var.name_prefix}-ses-role"
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ses.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_role_policy" "ses_role_policy" {
  name   = "${var.name_prefix}-ses-role-policy"
  role   = "${aws_iam_role.ses_role.id}"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": [
        "firehose:PutRecord",
        "firehose:PutRecordBatch"
      ],
      "Resource": "${aws_kinesis_firehose_delivery_stream.firehose.arn}"
    }
  ]
}
EOF
}

Terraform実行

$ terraform init
$ terraform apply

※ aws_ses_event_destinationの作成に失敗することがあります。その場合、再度 terraform apply を実行してください。

送信テスト

AWS CLIを使った以下のシェルスクリプトで送信テストができます。
Configuration Setを指定するのがポイントです。
前述の通り、開封・クリックのトラッキングが可能なのはHTMLメールのみです。
tagsについては、あとでデータを分析する際に利用できます。

#!/bin/bash -eux

TO=xxx
FROM=xxx

SUBJECT='TEST'
TEXT='hello world'
HTML="<h1>hello world</h1><a href='https://www.amazon.co.jp'>Amazon</a>"

CONFIGRATION_SET='ses-tracking-ses-configuration-set'

aws --region us-east-1 ses send-email \
    --to $TO \
    --from $FROM \
    --subject $SUBJECT \
    --text $TEXT \
    --configuration-set-name $CONFIGRATION_SET \
    --tags Name=tag1,Value=value1 \
    --html "$HTML"

S3に溜まったデータ

S3には以下のようにデータが保存されていきます。

{"eventType":"Send","mail":...
{"eventType":"Click","mail":...
{"eventType":"Open","mail":...
{"eventType":"Delivery","mail":...
os1ma
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした