3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Posted at

概要

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":...
3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?