【メンバーズを支える仕組み】 AWS から届くメールを自動処理するサービスをつくってみた

Serverless Framework を利用して開発したサービスの中でも一番規模の大きいサービスの裏側について少しご紹介します。サービス開発によって得られたメリットも期待以上で、施策に対する振り返りの重要性を改めて感じました。
2021.06.25

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

本記事では、2020年6月末時点で 8,800 を超える弊社メンバーズの管理 AWS アカウントへ向けて AWS から配信されるメールを自動処理するために開発したサービスの裏側を少しだけご紹介いたします。 リリース日(2020年7月3日)からおよそ1年分の稼働データを確認してみると年間累計 34万3千通を超えるメールが処理されており月平均で3万弱程度のメールが処理されておりました!!

1-2-640x217.png

はじめに

こちらのブログでも触れていますが、弊社のサポートチームは下記の課題を抱えておりました(2019年12月当時)

  • AWS から配信されるメールのうち、メンバーズ顧客が利用している AWS リソースに関するメンテナンス等の通知を人手で選り分け、顧客へ案内している(より迅速に顧客へ案内したい)
  • AWS から配信されるメールのうち、メンバーズ顧客が利用している AWS アカウントのインシデント通知等を人手を介して、顧客へ案内している(より迅速に顧客へ案内したい)

この課題を解決するために、開発したサービスが本記事のテーマとなります。

AWS から届くメールを自動処理するサービスを開発してみた

注意事項

文章の読みやすさを優先し、「公式ドキュメントに従った適切な表記」ではなく「略称表記」で説明を進めさせていただきます。あしからずご了承ください。

公式ドキュメントに従った適切な表記 略称表記(※)
AWS アカウントのルートユーザーに関連付けられた E メールアドレス ルートメアド
AWS アカウントのルートユーザーに関連付けられた E メールアドレス宛に配信された E メール ルートメール

※ 筆者個人が用いている造語。公式ドキュメントに記載された正式な用語ではございません

ルートメールを自動処理するサービスが提供しているメインの機能

  • 顧客へ案内する必要要否の管理票(リスト)に基づき AWS アカウント利用者へ配信する必要のあるルートメールを送信専用アドレス(no-reply@classmethod.jp)を利用して顧客(AWS アカウント利用者)へ通知
  • メンバーズに加入している AWS アカウントに作成されたサポートケースの対応記録を、弊社ヘルプデスクシステム(Zendesk)へ記録するためチケット化
  • AWS から通知される高緊急度の対応要請(Abuse Report/Account Compromise/SES レビュープロセス)を、顧客(AWS アカウント利用者)へ迅速に通知するためヘルプデスクシステム(Zendesk)を利用してサポートチケット化し、サポートチームアドレス(support@classmethod.jp)を利用して顧客(AWS アカウント利用者)へ通知

サービス全体の構成

下記の AWS サービスを活用しています。

その他にも、下記のようなサービスを活用しています。

また、開発言語は Python を利用しており構成管理のため Serverless Framework を利用しています。 ソースコードの規模感は、Python コードが 2200行程度で YAML が 1000行程度です。

Step Functions ビジュアルワークフロー

筆者個人が開発したサービスの中でも一番規模の大きいワークフロー(ステートマシン)です。

2-3-640x221.png

ワークフローの流れ

  1. AWS から配信されたメールを Amazon SES で受信
  2. Amazon SES Eメール受信用の受信ルールセットに従ってメールが S3 に保存される
  3. 項番 2 の S3 オブジェクト作成イベントから Lambda が invoke される
  4. 項番 3 から呼び出された Lambda が Step Functions のステートマシンを起動
  5. ステートマシンから呼び出される Lambda(タスク)で S3 に保存された受信メール(S3 オブジェクト)を取得し、メールを解析
  6. 項番 5 の解析結果を元に、Choice ステートで以降の処理に分岐する

Choice ステート以降は、ビジネスロジック毎のタスク(Lambda 関数)を個別に作り込む実装フローになっています。

サービスの要となる技術要素 AWS Organizations

サービスリリース当初は、日々増減する多数の AWS アカウントを管理(ルートメアドと、AWS アカウントID のリレーション情報管理)する部分を人手に頼っていました。弊社のメンバーズでは AWS Organizations を活用していたため、AWS Organizations API として提供されている list_accounts を用いて ACTIVE ステータスの AWS アカウント情報を毎時チェックし DynamoDB テーブルに保持することで、AWS アカウントの管理工数を不要とすることができました。

該当処理のコードスニペットは、下記のように実装されており AWS Organizations 管理アカウントから全てのアクティブなメンバーアカウントを収集しています。

members = {}
:
snip
:
organizations = session.client('organizations')
res = organizations.list_accounts()
while(True):
    for account in res['Accounts']:
        if account['Status'] == 'ACTIVE':
            account_id = account['Id']
            members[account_id] = account['Email']
    if 'NextToken' not in res:
        break
    else:
        res = organizations.list_accounts(NextToken=res['NextToken'])

プロジェクトを振り返ってみた

2020年4月8日に作成された当時の企画書

企画書(といっても個人メモ)には、以下の記載がありました。

====

課題(問題点)

  • メール通知に必要な作業工数および関係者が多いため自動化したい
  • 原文をタイムリーに確認したい顧客の要望(期待)に答えられていない

期待する効果

  • 自動化による業務効率化(作業負荷軽減および対応工数削減等の改善)
  • 原文メールをタイムリーに受信したい顧客の要望を満たすことによる、顧客満足度の向上

====

サービスリリース以前は受信したメールを人手で処理していたため全てのメールをリアルタイムに処理することは現実的ではありませんでした。また、顧客へ向けて案内が必要なメールの配信対応も全て手作業かつ、海外(ドイツ&カナダ)チームへ作業を分担する等を背景に、1つのメールを処理する際の対応コストが相当高かったのも事実です。

サービスリリース前後の対応作業の変化

ほとんど人間に依存していた作業から、人間に依存する作業(案内要否の判断や、参考資料の作成、リトライ処理のキック)のみを残して、ほぼ機械による自動処理化に成功したのではないかと考えています。

作業 サービスリリース前 サービスリリース後
ルートメールのチェック ほぼ全て人力(一部自動処理されてた) 顧客へ案内する必要要否の管理票に含まれない新規パターンが届いたら毎時のジョブで検知され、SlackBot から通知される(※1)
顧客向けメール配信 メール種別毎にご案内メールを作文(日本&海外チーム共同)し、随時個別のメール配信スクリプトを用意して実行 顧客へ案内する必要要否の管理票に含まれたルートメールは、リアルタイムに顧客(AWS アカウント利用者)へ配信される(※2)

(※1)イメージ図

チェックが必要なメールを受信している場合

3-4-640x162.png

すべて処理されている場合

4-3.png

(※2)管理票に含まれない新規パターンの場合、案内要否を人間が判断し管理表を更新。顧客へのメール配信(リトライ)作業は、Slack コマンドを実行するだけ(リトライキューに溜まった S3 オブジェクトID リストを取得した StepFunctions が自動的にリトライ処理してくれる)

改めて振り返ってみると、期待する以上の効果をもたらしているのではないかと感じました。

施策(サービス開発)による効果を可視化してみた

サービス導入前後の成果を定量化して可視化することを目的に、年間累計 34万3千通のメールを(ほぼ)機械に自動処理させたことで得られたメリットを試算してみます。

前提条件

  • メール1通の処理に対して1分の工数が必要と仮定する(今回の目的に沿って妥当性は考慮しません。感覚値としては少なめの見積りという印象)

サービス導入前

  • 476時間/月の工数を消費(343,000分/年 ≒5,716時間/年 つまり ≒476時間/月)
  • この作業のために専任(フルタイム勤務)メンバーをアサインした場合、最低3名程度の雇用が必要(月間稼働時間を、単純計算 8時間 x 20稼働日とする)
  • サービススケールに伴った AWS アカウント数増加により、配信されるメール数自体が増加する可能性が高いため、メール受信件数に応じた増員計画も必要となる可能性が高い
  • 顧客向けメール配信作業は、対応フローが煩雑で関係者も多く(1回の作業あたり4名以上がアサインされていた)対応工数が作業都度上乗せされる

サービス導入後

  • サービス導入前に必要だったルートメールをチェックするメンバー(3名の専任メンバー)が不要
  • 顧客向けメール配信作業は、対応フローがシンプルかつ簡素化され1名で対応することも現実的なレベルに落とし込まれた
  • AWS フルマネージドサービスを活用したサービスかつスケーラビリティも確保されておりサービススケールに伴い、この作業を背景とした増員計画は不要

少なく見積もったとしても、年間3名分の作業工数が削減された可能性が高いと思われます。 また、これまで顧客へ提供できていなかった「タイムリーに顧客へメールを配信したい」という要望を満たしており、その結果メンバーズのサポート品質向上に貢献するサービスであることは明白かと思われます。 合わせて、AWS アカウントのインシデント検知時も即座に顧客へ通知する仕組みが整ったため、チームメンバーにより下記のようなサービス品質向上に繋げるための施策や取り組みが加速した印象を受けています。 このような取り組みも、当初想定していなかった副次的な効果ではないかと推測しています。

改めて振り返ってみると、当初期待した以上の効果をもたらしていそうだなと感心しました。(自画自賛)

さいごに

2020年2月下旬に開発プロジェクトをスタートさせ、2020年7月3日の本番リリース後も運用&機能追加開発&不具合修正を1年近く対応していた非常に思い入れのあるサービスとなりました。2021年5月末時点で同僚(オペレーションチーム所属メンバー)にサービスメンテナーを移譲し個人プロジェクトからチームプロジェクトに引き継いでおります。

今後も、弊社メンバーズのサポートビジネスを支えるサービスとして稼働し続けてくれることを切に願います。

ではでは