23
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

AWSサーバーレス連絡フォームの作り方💪(AWS Lambda、API Gateway、SES)

Last updated at Posted at 2020-07-08

AWS S3にサイトを安くて簡単にホスティングできますが、S3は静的なサイトしかホスティングできないですので、従来ならバックエンド処理が必要となるフォーム送信の実装などは難しそうですね。しかし、クラウド時代ではそんな心配はありません!ソリューションはサーバーレスアーキテクチャです!AWSはすでに色々なサーバーレス構築のツールを提供しています。

今回はユーザからお問い合わせやフィードバックを送信するたびに、任意な宛先に通知メールを送信するシンプルなサーバーレスメールサービスを一緒に作ります。AWS LambdaとAPI Gatewayを利用し、簡単なAWSサーバーレス構築を紹介します。

構成図はこんな感じです。
diagram.PNG

処理の流れとしては、ユーザーから連絡フォームより入力した情報を収集し、クライアント側のブラウザからAmazon API Gateway RESTfulサービスに投稿します。Amazon API Gatewayは、収集されたユーザー情報をAWS lambda関数に渡します。AWS Lambda関数は、Eメールを自動生成し、Amazon SESを使用してメールサーバーに転送します。

1.フォームを作成

  • index.htmlファイルを作成し、下記のコードを貼り付けます。
index.html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>連絡フォーム</title>
    <script src="script.js"></script>
    <link rel="stylesheet " href="style.css ">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js "></script>

</head>


<body>
    <h1>連絡フォーム</h1>
    <form id="contact-form" method="post">
        <h4>名前:</h4>
        <input type="text" id="name-input" placeholder="お名前を入力してください。" class="form-control" /><br />
        <h4>件名:</h4>
        <input type="subject " id="subject " " placeholder="お名前を入力してください。 " class="form-control " /><br />
        <h4>メール:</h4>
        <input type="email " id="email-input " placeholder="メールを入力してください。 " class="form-control " /><br />
        <h4>メッセージ:</h4>
        <textarea id="description-input " rows="3 " placeholder="メッセージを入力してください。 " class="form-control "></textarea><br />
        <div class="button-wrapper "><button type="button " onClick="submitToAPI(event) " class="btn btn-lg ">送信</button></div>

    </form>
</body>
</html>

ブラウザでプレビューを確認できます。こんな感じです。
basic-html-form.PNG

  • 見た目はあまり良くないですので、改善しましょう。style.cssを同じフォルダ内で作成し、下記のコードを貼り付けます。
style.css

* {
    box-sizing: border-box;
}

body {
    text-align: center;
    color: rgb(255, 255, 255);
    background-color: #194680;
    padding-top: 20px;
}

#contact-form {
    margin: auto;
    text-align: left;
    padding: 20px;
    max-width: 430px;
    border: white solid 2px;
    border-radius: 10px;
}

button {
    text-align: center;
    margin-top: 20px;
    font-size: 18px;
    border: white solid 2px;
    background-color: white;
    border-radius: 5px;
}

.button-wrapper {
    text-align: center;
}

input,
textarea {
    width: 380px;
}

textarea {
    height: 200px;
    padding: 10px;
}

input {
    height: 35px;
}

ブラウザではこんな感じになります。
styled-form.PNG

2. AWS Lambda関数の定義

  • AWS Lambda画面で新規関数を作成し、hello-worldのnodejsテンプレを選択します。
    lambda2.PNG

  • 基本的な情報の画面では関数を任意に名付けて、実行ロールは最初選択のままで進みます。
    lambda3.PNG

  • 次の画面の関数コードに下記のコードを切り替えます。

index.js

var AWS = require('aws-sdk');
var ses = new AWS.SES();

//宛先のメールアドレスを入力してください。
var RECEIVER = 'example-receiver@gmail.com';

//送信先のメールアドレスを入力してください。
//送信先のメールはAWSに認証登録する必要があります。
var SENDER = 'example-sender@gmail.com';

//クライアントへのレスポンスヘッダーを設定
var response = {
    "isBase64Encoded": false,
    "headers": {
        "Content-Type": 'application/json',
        "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,Accept",
        "Access-Control-Allow-Methods": "POST,GET,OPTIONS",
        "Access-Control-Allow-Origin": "*",
    },
    "statusCode": 200,
    "body": "{\"result\": \"テスト成功です!\"}"
};

exports.handler = function(event, context, callback) {
    console.log('受理したイベント:', event);
    sendEmail(event, function(err, data) {
        context.done(err, null);
    });
    callback(null, response);
};

//メール送信処理
function sendEmail(event, done) {
    var params = {
        Destination: {
            ToAddresses: [
                RECEIVER
            ]
        },
        Message: {
            Body: {
                Text: {
                    Data: '● お名前: ' + event.name + '\n● 件名: ' + event.subject + '\n● メール: \n' + event.email + '\n● 内容: \n' + event.desc,
                    Charset: 'UTF-8'
                }
            },
            Subject: {
                Data: event.name + 'からの連絡フォームが来ました!',
                Charset: 'UTF-8'
            }
        },
        Source: SENDER
    };
    ses.sendEmail(params, done);
    return {
        response,
        body: JSON.stringify(params),
        statusCode: 200
    }
}
  • 同じLambda管理画面で、上にスクロールし、アクセス権限のタブに切り替え、ロール名のリンクをクリックします。

lambda-policy.PNG

  • 当関数のIAMポリシーをSES権限を追加します。IAM画面で該当ポリシーをクリックしポリシーを編集 ->JSONのフォーマットに切り替えし、下記のコードを追加します。

lambda-policy3.PNG

{
  "Sid": "FormPolicy",
  "Effect": "Allow",
  "Action": "ses:SendEmail",
  "Resource": "*"
}

こんな感じです。
lambda-policy2.PNG

3. APIゲートウェイでAPI構築

  • AWSメインコンソールよりAPI Gateway管理画面にアクセスし、APIを作成をクリックします。
    api.PNG

  • 次の画面ではREST API構築をクリックします。

api2.PNG

  • 次の画面はREST APIの選択のままで、API名前を任意に付けます。

api2a.PNG

  • 次の画面は上にあるアクションをクリックし、メッソド作成をクリック、POSTを選択します。

api3.PNG

  • 右側の設定画面では、統合タイプLambdaで、Lambda関数は先ほど作成したものを選択します。

api4b.PNG

  • CORSエラーにならないように、CORS機能も有効にします。アクションのドロップダウンをCORS有効化をクリックし、設定はそのままで保存します。

api4c.PNG

  • API Gatewayの最新アップデートでは、ゲートウェイのレスポンスも設定しないと、CORSエラーが発生するため、設定しましょう。右のゲートウェイレスポンス → DEFAULT 4XX編集の順番にナビゲートします

api5a.PNG

  • レスポンスヘッダーに下記の値を追加し、保存します。
  Access-Control-Allow-Origin: '*'

こんな感じです。
api5b.PNG

これでAPIの構築は完了です。

4. SES送信用のメール検証登録

mail.PNG

verifiedの状態になったら、OKです!

  • Lambda画面に戻して、左上にあるテストで動作確認できます。lambda-test.PNG

  • サンプルテストJSONデータ:

{
  "name": "value1",
  "subject": "value2",
  "email": "test@test.com",
  "desc": "value3"
}

5.全コンポーネントを連携する

  • 最後のステップではすべてを繋ぎます!index.htmlと同じいフォルダでscript.jsを作成し、下記のコードを貼り付け、var URLurlの2ヶ所に先ほど設定したAPI GatewayのエンドポイントURLを差し替えます。
script.js

function submitToAPI(e) {
    e.preventDefault();
    //設定したAPI GatewayのエンドポイントURLをここに入れます。
    var URL = "API-GATEWAY-ENDPOINT-URL";

    //フォームの入力値をチェック
    var name = /[A-Za-z]{1}[A-Za-z]/;
    if (!name.test($("#name-input").val())) {
        alert("2文字以上記入してください。");
        return;
    }
    var subject = /[A-Za-z]{1}[A-Za-z]/;
    if (!subject.test($("#subject").val())) {
        alert("2文字以上記入してください。");
        return;
    }
    if ($("#email-input").val() == "") {
        alert("メールを入力してください。");
        return;
    }

    var email = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,6})?$/;
    if (!email.test($("#email-input").val())) {
        alert("メールアドレスは正しくありません。");
        return;
    }

    var name = $("#name-input").val();
    var subject = $("#subject").val();
    var email = $("#email-input").val();
    var desc = $("#description-input").val();
    var data = {
        name: name,
        subject: subject,
        email: email,
        desc: desc
    };

    $.ajax({
        type: "POST",
        //設定したAPI GatewayのエンドポイントURLをここに入れます。
        url: "API-GATEWAY-ENDPOINT-URL",
        dataType: "json",
        crossDomain: "true",
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(data),


        success: function() {
            // フォームをクリアし、送信成功のメッセージを表示する
            alert("メッセージが送信されました!");
            document.getElementById("contact-form").reset();
            location.reload();
        },
        error: function() {
            // 送信エラーのメッセージを表示する
            alert("メッセージ送信失敗!");
        }
    });
}

#6. 結論
フォームより受信するメールはこんな感じです。
demo.PNG

これでAmazon S3で静的Webサイトをホストしても、AWSアーキテクチャを利用し、ユーザよりサイト管理者へフォーム送信機能を実装できました!

初投稿です、、いかがでしょうか、、(´・ω・`)
コメント、フィードバックなど大変モチベーションになりますので、
是非よろしくお願いいたします!
それでは、また今度! (`・∀・´)ノ

23
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?