Amazon SESでメールを受信してS3に保存する方法


イントロダクション

Amazon Simple Email Service (Amazon SES)で受信したメールを、
自動的にS3に保存します。

SESは受信したタイミングでLambdaを起動してDynamoDBやRDSに直接保存することも可能です。
しかし、DynamoDBのキャパシティ制限や障害によるメールの取りこぼしを防ぐために、 一旦S3に保存することにしました。

そして、S3への保存をトリガーにLambdaを起動すれば、データのロストが発生しないシステムになります。

Terraform

全体の設定

SESは利用可能なリージョンが少ないので、
SES用とその他の用途のAWSプロバイダーを別々に定義しています。

variable "aws_region" {
  type = "string"
  default = "ap-northeast-1"
}
variable "aws_region_ses" {
  type = "string"
  default = "us-east-1"
}
variable "aws_s3_bucket_mailbox" {
  type = "string"
  default = "保存先のBucket名"
}
variable "receiver_address" {
  type = "string"
  default = "受信メールアドレス"
}

terraform {
  backend "s3" {
    bucket = "terraform"
    key    = "example-terraform-ses-s3/state/terraform.tfstate"
    region = "ap-northeast-1"
  }
}

# SESとその他の用途でリージョンを分けるためにproviderを分ける
provider "aws" {
  region = "${var.aws_region}"
}
provider "aws" {
  alias = "ses"
  region = "${var.aws_region_ses}"
}

S3のポリシー定義

既存のS3バケットを使う設定にしていますが、
新しいバケットを作成して使うことももちろん可能です。

# 既存のバケットを使用する
data "aws_s3_bucket" "mailbox" {
  bucket = "${var.aws_s3_bucket_mailbox}"
}

# S3バケットへSESからのPutを可能にする
resource "aws_s3_bucket_policy" "mailbox" {
  bucket = "${data.aws_s3_bucket.mailbox.id}"
  policy = "${data.aws_iam_policy_document.mailbox.json}"
}

data "aws_iam_policy_document" "mailbox" {
  statement {
    effect = "Allow"
    principals {
      type = "Service"
      identifiers = ["ses.amazonaws.com"]
    }
    actions = [
      "s3:PutObject"
    ]
    resources = ["${data.aws_s3_bucket.mailbox.arn}/*"]
  }
}

SESのルールセット

# 新しいルールセットを作成
resource "aws_ses_receipt_rule_set" "main" {
  provider = "aws.ses"
  rule_set_name = "s3"
}

resource "aws_ses_receipt_rule" "main" {
  provider = "aws.ses"
  name          = "s3"
  rule_set_name = "${aws_ses_receipt_rule_set.main.rule_set_name}"
  recipients    = ["${var.receiver_address}"]
  enabled       = true
  scan_enabled  = true
  s3_action {
    bucket_name = "${data.aws_s3_bucket.mailbox.id}"
    object_key_prefix = "mailbox/${var.receiver_address}"
    position = 1
  }
}

# ルールセットをアクティブにする
resource "aws_ses_active_receipt_rule_set" "main" {
  provider = "aws.ses"
  rule_set_name = "${aws_ses_receipt_rule_set.main.rule_set_name}"
}

See also