Amazon SESで受信したメールをRedashで検索できるようにしてみた

こんにちはSREチームの宮後(@miya10kei)です。最近、テレビ📺からプロジェクター📽️に乗り換えて大満足しています🤗

みなさんのサービスでは送受信したメールの検索はどうしてますか?
サービスを運用していると「メールが届いてない」という問い合わせを受けることはあるあるではないかと思います。今回は送受信したメールを永続化し、検索できるようにした仕組みを紹介します。

背景

Park Directでは日々多くのメールを送受信しており、業務上メールはとても重要な要素になっています。また、システムにも貸主様と借主様がメールのやり取りをする機能があるため、メールが届いていない、UIに表示されないなどの問い合わせが一定の頻度で発生しています。その問い合わせはサクセスチームだけで調査が完結せず、サクセスチームから依頼された開発チームで調査が行われています。そのため、メールの送受信状況をサクセスチームと開発チームがどちらも簡単に検索できる仕組みを構築することで運用負荷を低減することができると考えました。(仕組みを作るまではEML形式のメールをS3から探し当てていました🥲)

メール検索の仕組み

まずは全体構成をお見せしてから詳細を紹介していきます。 Park Directではメールの受信にAmazon Simple Email Service(以下、Amazon SES)を利用しており、受信ルール機能を使って後続の永続化処理を実行しています。

全体構成

送信メールの記録方法

システムからの送信メールは宛先にAmazon SES宛のメールアドレスをBCCに設定することで受信できるようにしています。利用するメールサービスにもよりますがメールの送信通数で料金が発生する場合、コストが2倍かかってしまいます。そのためベストな案ではないですが、思いついた方法としてはベターな案でしたので採用しました。

メールの永続化方法

受信したメールはS3とDynamoDBの2箇所で永続化しています。

永続化先 説明
S3 受信したメールをそのままEML形式で永続化
DynamoDB Lambdaでパースした結果をカラム分割して永続化
こちらに対して検索をおこなう

もともとS3への永続化をおこなっていたのですが検索性が非常に悪いという課題があったため新たにDynamoDBへの永続化をおこなうことにしました。 永続化先としてRDSも検討しましたが、利用頻度に対してかかるコストを考慮してDynamoDBを採用しました。(RDSは起動時間ベースで課金されるので...💰)

DynamoDBのデータ構造と設定

データ構造

Lambdaでパースしたメールは以下のカラムに分割して永続化しています。

項目 説明 備考
To 送信先メールアドレス パーティションキー
From 送信元メールアドレス
Date 送信日時 ソートキー
Bcc BCCメールアドレス
Subject 件名
Message-ID Message-IDヘッダーの値
In-Reply-To In-Reply-Toヘッダーの値
References Referencesヘッダーの値
Body 本文
S3_Key 永続されたS3オブジェクトキー名
TTL 1年後のUnixTime Time to Live

グローバルセカンダリインデックス(GSI)

Fromをパーティションキー、Dateをソートキーに指定したGSIを作成することで送信元メールアドレスでも検索できるようにしています。

キャパシティーモード

キャパシティーモードはオンデマンドモードを採用しています。プロビジョニングモードと比較しましたが、発生するリクエスト数をもとに計算するとオンデマンドモードの方がコストが安あがりだったためこちらにしました。 (24時間365日で継続的にリクエストが発生するものではないので計算するまでもなかったかもです😅)

Redashからの検索

ニーリーではBIツールとしてRedashを使用しており、サクセスチームのメンバーもRedashの使用に慣れています。そのため、RedashからDynamoDBを検索する形でUIを提供することにしました。
現在はToアドレスとFromアドレスの2カラムをキーにして検索できるようにしています。(今後要望に応じてGSIを追加し他のカラムでの検索を可能にするかもしれません)以下は検索に使用しているDQLです。

SELECT
  date,
  to_address,
  from_address,
  subject,
  body,
  in_reply_to,
  message_id,
  referrences,
  s3_key
FROM mail_table
WHERE 
  to_address = '{{ to_address }}'
  AND date BETWEEN '{{ date_from }}' AND '{{ date_to}}'
ORDER BY date DESC;

SELECT
  date,
  to_address,
  from_address,
  subject,
  body,
  in_reply_to,
  message_id,
  referrences,
  s3_key
FROM mail_table
WHERE 
  from_address = '{{ from_address }}'
  AND date BETWEEN '{{ date_from }}' AND '{{ date_to}}'
USING from_address-date-index – ココでGSLを指定しています
ORDER BY date DESC;

Mail ManageのE メールアーカイブ機能

2024年5月にAmazon SESに受信メール機能を強化するMail Managerが追加されました。Mail Manageには「E メールアーカイブ」という機能があり、受信したメールをアーカイブしマネジメントコンソール上から任意の条件で検索することができます。
ユースケースとしてマネジメントコンソールからの検索が許容可能であれば十分に選択肢に入ってくる機能かと思います。

Eメールアーカイブ

※ To/From/Cc/件名などで検索でき、任意の期間永続化することも可能です。

さいごに

今回は送受信メールの検索性を向上させた仕組みを紹介しました。 この仕組みを導入してからは、社内でメールについての問い合わせがあった際にスムーズに検索して回答できるようになったと実感しています。

同じ悩みを持っている方がいたら是非参考にしてみてください!