😶‍🌫️

AWS Step Functionsを使用したサーバーレスな問い合わせフォームの実装

2024/11/09に公開

はじめに

この記事では、
AWS Step Functionsを使ってサーバーレスな問い合わせフォームを作る方法を紹介します。
今回の構成は以下の通りです。

  • フロントエンド: S3で静的ホスティング
  • バックエンド: API Gateway + Step Functions + SES (Simple Email Service)

よくある構成としてStep FunctionsでなくLambdaを使った場合がありますが、
Lambdaだとコードを少なからず書く必要があることと、
ランタイムの管理も必要になってきます。
その点、Step Functionsはノンコードで実装できるのでより手軽に実装できます。

実装の構成

アーキテクチャ概要

今回の問い合わせフォームは、以下の構成で実装しています。

  1. フロントエンド

    • S3バケット: HTML、CSS、JavaScriptファイルを保存し、静的なウェブサイトとしてホスティングします。
  2. バックエンド

    • API Gateway: フロントエンドからのリクエストを受け取り、Step Functionsをトリガーします。
    • Step Functions: 問い合わせの処理フローを管理します。
    • SES (Simple Email Service): 問い合わせ内容をメールとして管理者に送信します。

全体の流れは以下の通りです。

[ユーザー] → (1) [フロントエンド (S3)] → (2) [API Gateway] → (3) [Step Functions] → (4) [SES (メール送信)]

alt text

実装手順

1. フロントエンドの作成

問い合わせフォームはHTMLとJavaScriptで作成し、S3にホスティングします。
ホスティング設定は割愛します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>お問い合わせフォーム</title>
    <style>
        /* スタイリングは省略 */
    </style>
</head>
<body>
    <div class="container">
        <h2>お問い合わせフォーム</h2>
        <form id="contactForm">
            <div class="form-group">
                <label for="name">お名前</label>
                <input type="text" id="name" name="name" required>
            </div>
            <div class="form-group">
                <label for="email">メールアドレス</label>
                <input type="email" id="email" name="email" required>
            </div>
            <div class="form-group">
                <label for="message">メッセージ</label>
                <textarea id="message" name="message" rows="5" required></textarea>
            </div>
            <button type="submit" class="btn">送信</button>
        </form>
    </div>

    <script>
        document.getElementById("contactForm").addEventListener("submit", function(event) {
            event.preventDefault();
            
            const name = document.getElementById("name").value;
            const email = document.getElementById("email").value;
            const message = document.getElementById("message").value;
            
            const data = {
                name: name,
                email: email,
                message: message
            };

            // API Gatewayのエンドポイントにリクエストを送信
            fetch("API Gatewayのエンドポイント", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify(data)
            }).then(response => {
                if (response.ok) {
                    alert("お問い合わせありがとうございました。");
                } else {
                    alert("メッセージの送信に失敗しました。");
                }
            }).catch(error => {
                console.error("エラー:", error);
                alert("エラーが発生しました。");
            });
        });
    </script>
</body>
</html>

2. SESの設定

SES (Simple Email Service) を使って問い合わせ内容を管理者にメールで通知します。
サンドボックス解除をしていない場合は、送信元メールアドレスを確認する必要があります。

  • 送信元アドレスの検証: SESコンソールから送信元アドレスの確認を行います。
  • 受信設定: 管理者が受信するメールアドレスを設定します。

3. Step Functionsのワークフロー

Step Functionsでは問い合わせ内容の処理フローを定義します。
SES APIを使います。

手順詳細
Step Functionsへ移動し、「ステートマシンの作成」をクリック
alt text

Blankのままで「選択」をクリック
alt text

検索ボックスにses v2 sendで検索し、SendEmailをドラッグ
(V1の方がAPIリソースに書く内容は単純になりますが、ここではV2を選んでいます。)
alt text

APIパラメータの箇所に下記JSONを入力。(必要に応じて適宜変更してください。)
alt text

{
  "FromEmailAddress": "SESで認証したメールアドレス",
  "Destination": {
    "ToAddresses": [
      "受信可能なメールアドレス"
    ]
  },
  "Content": {
    "Simple": {
      "Subject": {
        "Data.$": "$.nameform"
      },
      "Body": {
        "Text": {
          "Data.$": "$.message"
        }
      }
    }
  }
}

ロールのアクセス許可画面がでますが、そのまま「確認」をクリック
alt text

上部のタブから設定に移り、「IAMで表示」をクリックします。
alt text

「ポリシーをアタッチ」をクリック
alt text

SESfullを付与します。(full権限は不要なので最小権限で設定される際は適宜権限を調整してください。)
alt text

以上でStep Functionsの作成は完了です。

4. API Gatewayの設定

フロントエンドからのリクエストを受け取るために、API Gatewayを設定します。
REST APIを作成し、POSTメソッドを有効にしてCORSの設定も忘れずに行います。

  • エンドポイントの作成: API Gatewayで問い合わせ用のPOSTエンドポイントを作成します。
  • Step Functionsのトリガー: リクエストを受け取ったらStep Functionsをトリガーするように設定します。

手順詳細

API GatewayでREST APIを選択
alt text

API名は任意の名前で「APIを作成」
alt text

「リソースの作成」をクリック
alt text

パスに任意の名前をつけ、CORSにチェックをつけて「リソースの作成」をクリック
alt text

/sendの下にOPTIONSが作成されており、統合レスポンスにCORSの設定がされています。
alt text

「メソッドを作成」をクリック
alt text

メソッドタイプ:POST
統合タイプ:AWSのサービス
AWSのサービス:Step Functions
HTTPメソッド:POST
アクション名:StartExecution(任意の名前でOK)
実行ロール:APIGatewayToStepFunctions(事前にAWSStepFunctionsFullAccessを付与したロールを作成)
確認ができたら「メソッド作成」をクリック
alt text
alt text

統合リクエストの編集をクリック
alt text

最下部のマッピングテンプレートにVTLを記入。
(VTLの記載方法はもっと良い例があるかと思います。)
適宜message内で出力したいメッセージ本文に変更してください。
ここでは下記の形式でメールが送られます。
名前:$nameform
本文:$message

#set($nameform = $input.path('$.name'))
#set($email = $input.path('$.email'))
#set($message = "名前:${nameform}\\n本文:${input.path('$.message')}")
{
  "input": "{\"nameform\": \"$nameform\", \"email\": \"$email\", \"message\": \"$message\"}",
  "name": "MyExecution-$context.requestTimeEpoch",
  "stateMachineArn": "作成したStep FunctionsのARNを記載"
}

alt text

POSTのCORS設定をします。
メソッドレスポンスから「レスポンスを作成」をクリック
alt text

ヘッダー名にAccess-Control-Allow-Originを記載し「保存」をクリック
alt text

統合レスポンスの編集をクリック、'*'を記載し、「保存」をクリック
alt text

「APIをデプロイ」をクリック
alt text

ステージ名「dev」を記載し、「デプロイ」をクリック
alt text

記載されているURLをS3に配置したファイルに記載し完了。
alt text

5. テスト

ここまでの設定ができていればFormから送信したデータがメールで送られてきます。
実際に実行して確認してみてください。

正常に実行できているとStep Functionsの実行履歴で「成功」が表示されます。
alt text

まとめ

今回は、Step Functionsを使ったサーバーレスな問い合わせフォームを実装する手順を紹介しました。
あまりネットでは記載がなかったので試しに実装してみました。
この実装だとメールの本文をマッピングテンプレートで作成する必要があるため、集計用などの単純なメッセージなら簡単に用意できますが、
凝ったメッセージを作成する場合はLambdaで行った方が分かりやすく調整がし易い印象です。

問い合わせフォームは一度作ったきりで放置されがちなのでランタイムの管理などを考えるとStep Functionsもありかなと思いました。

ここまで読んでいただきありがとうございます!

GitHubで編集を提案

Discussion