Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
7
Help us understand the problem. What is going on with this article?
@os1ma

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":...
7
Help us understand the problem. What is going on with this article?
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
os1ma
サーバサイド・インフラ中心のエンジニア。 日々、本を読んだりコードを書いたり勉強会を開いたりしてます (Twitter はじめました)

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
7
Help us understand the problem. What is going on with this article?