NEWS ABOUT Solution WORKS TEAM BLOG お問い合わせ JP EN

サーバレスでお問い合わせフォームを実装してみる (2)

こんにちは、システムエンジニアの今井です。

前回のブログ「サーバレスでお問い合わせフォームを実装してみる(1)」の続きです。

(導入編)「サーバーレスとは本当にサーバーがないこと?」
(1)サーバーレスでお問い合わせフォームを実装してみる(フォームとAPIの作成)
→(2)サーバーレスでお問い合わせフォームを実装してみる(フォームからAPIへ値の送信)
(3)サーバレスでお問い合わせフォームに記載された内容をDBに保存してみる1
(4)サーバレスでお問い合わせフォームに記載された内容をDBに保存してみる2

前回作成したフォームとAPIを連携させて、お問い合わせフォームとして動作させるまでを解説します。
スライド2-2

1. API GatewayのURLをHTMLに反映(貼り付けて再アップロード)

フォームをSubmitした際にデータが送信される先に API GatewayのURLを設定します。
以前アップロードしたフォームのhtmlファイルにはURLが記載されていないため、ファイルを編集してから再アップロードします。

まずはAPI GatewayのURLを取得します。

(1)Lambda のページを開きます。
https://ap-northeast-1.console.aws.amazon.com/lambda/home

def210207_1907

(2)「ContactSend」をクリックします。
def210207_1907_2

(3)「API Gateway」をクリックします。
def210129_1837

(4)API Gatewayの「詳細」をクリックします。
def210129_1838

(5)APIエンドポイントのURLをコピーします。
def210130_1842_2

「index.html 17行目」に貼り付けます。

<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, width=device-width">
<title>test</title>
</head>
<body>
<form id="contact_form">
会社名:<input type="text" name="company" value="" required /><br/>
メールアドレス:<input type="email" name="email" value="" required /><br/>
<input type="button" id="send" value="送 信"/>
</form>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
var target_url = '【ここにAPI Gateway のURLを貼り付けます】';
~~~~ 以下省略 ~~~~

 

次に、既にアップロードされている index.html ファイルを削除します。

(1)Amazon S3のページを開きます。
https://s3.console.aws.amazon.com/s3/
def210207_1908

(2)「contact-example」をクリックします。
def210207_1908_2
(3)index.html にチェックを入れて「削除」をクリックします。
def210131_1845

(4)「完全に削除」と入力し、「オブジェクトの削除」をクリックします。
(※別のファイルを削除してしまわないように注意してください)
def210131_1846

(5)ファイルが削除できました。
def210131_1847

(6)アップロードをクリックします。
def210131_1847

(7)編集したindex.html ファイルを範囲にドラッグアンドドロップします。
def210131_1848

(8)「アップロード」をクリックして確定します。
def210129_1818

(9)ファイルがアップロードできました。
def210129_1819

続いて、htmlファイルは非公開になっているためアクセス権限を付与します。

(10)「index.html」をクリックします。
def210201_1891

(11)「アクセス許可」をクリックします。
def210201_1892_2

(12)全員(公開アクセス)の「読み込み」をチェックします。
def210201_1897_2

(13)「変更の保存」をクリックします。
def210201_1898_2

「index.html」の差し替えが完了しました。(見た目上の変化はありません)

def210202_1902

2. CORSの設定

API Gatewayは許可されたページ以外からのアクセスを拒否する設定になっています。(クロスオリジンアクセスポリシー)
そのため、さきほどアップロードしたフォームからのアクセスを許可する必要があります。

(1)S3のページを開きます。
https://s3.console.aws.amazon.com/s3/home

def210131_1853

(2)「contact-example」をクリックします。
def210131_1853_2

(3)「index.html」をクリックします。
def210131_1854_2

(4)オブジェクトのURLをコピーします。(例:https://【文字列】.s3-ap-northeast-1.amazonaws.com/index.html)
def210131_1850_2

(5)「API Gateway」のページを開きます。
https://ap-northeast-1.console.aws.amazon.com/apigateway/main/apis

def210212_1899

(6)「ContactSend-API」をクリックします。
def210212_1899_2

(7)「CORS」をクリックします。
def210212_1900_2

未設定の状態ではすべてのアクセスが許可されていません。
def210212_1901

(8)設定をクリックします。
def210212_1901_2

(9)「Access-Control-Allow-Origin」にさきほどコピーしたオブジェクトURLの「ドメイン部分」を貼り付けます。
(オブジェクトURL:https://【文字列】.s3-ap-northeast-1.amazonaws.com/index.html)
(ドメイン部分:https://【文字列】.s3-ap-northeast-1.amazonaws.com)

def210212_1902_2

(10)「追加」をクリックします。
def210212_1902_3

(11)「Access-Control-Allow-Methods」に「POST」を設定します。
def210212_1903_2

(12)「保存」をクリックします。
def210212_1903_4

フォームからのアクセスが許可されました。
def210212_1904

3. Lambdaの動作確認

Lambdaのプログラムをテスト用のコードに変更して動作確認をしてみます。

(1)Lambda のページを開きます。
https://ap-northeast-1.console.aws.amazon.com/lambda/home

def210212_1915

(2)「ContactSend」をクリックします。
def210212_1915_2

(3)スクロールして main.pyをダブルクリックします。
def210212_1916_2

(4)コードのエディタにテスト用のコードを貼り付けます。
def210212_1916_2

「テスト用のコード main.py」

import boto3
import json

print('Loading function')

def respond(err, res=None):
    return {
        'statusCode': '400' if err else '200',
        'body': err.message if err else json.dumps(res),
        'headers': {
            'Content-Type': 'application/json',
        },
    }


def lambda_handler(event, context):

    body = {'result':1}
    return respond(None, body)

(5)「デプロイ」をクリックします。
def210131_1883_2

(6)「API Gateway」のURLにアクセスしてみます。
「{“result”: 1}」というエラーではない正常なレスポンスを返すことができました。
def210212_1917

ここまでの手順でフォームも動作するようになります。
index.htmlにアクセスしてみます。
def210202_1901

フォーム項目を入力して送信します。
def210212_1906

フォームが正しく動作するようになりました。
def210212_1907

テスト用のコードでは、問い合わせの内容を内容を確認することができないため、問い合わせフォームから入力された内容をメールで受信できるように作り変えていきます。

4. SESでメール送信(SESで送受信できるメールアドレスを追加)

メールの送信にはSESというサービスを利用します。LambdaからSESを使ってメール送信してみます。
スライド2-2-2

まずはSESの設定を行います。

(1)SESのページを開きます。
https://ap-northeast-1.console.aws.amazon.com/ses/home
def210212_1918

(2)「Email Address」をクリックします。
def210212_1918_2

(3)「Verify a New Email Address」をクリックします。
def210212_1930_2

(4)問い合わせを受信したいメールアドレスを入力し「Verify This Email Address」をクリックします。
def210212_1931_2

(5)メールアドレスの確認待ちの状態になります。
def210212_1932_2

(6)受信トレイを確認すると確認用のメールが届いています。確認用のURLをクリックします。
def210212_1933_2

(7)SESの一覧画面に戻ると Verified(確認済み)になりました。
def210212_1934_2
次にLambdaからSESにアクセスできるようにロールに権限を追加します。

(1)IAM のページを開きます。
https://console.aws.amazon.com/iam/home

def210129_1820

(2)ロールをクリックします。
def210129_18202

(3)「contact-example-role」をクリックします。
def210212_1924_2

(4)「ポリシーをアタッチします」をクリックします。
def210212_1925_2

(5)ポリシーのフィルタに「AmazonSESFullAccess」と入力して絞り込みます。
def210212_1927_2

(6)チェックを入れて「ポリシーのアタッチ」をクリックします。
def210212_1928_2

ロールにSESにアクセスするために必要なポリシーが追加されました。
def210212_1938_2
最後にLambdaのコードを更新して、問い合わせがあった際にメールが送信されるようにします。

(1)Lambdaのページを開きます。
https://ap-northeast-1.console.aws.amazon.com/lambda/home

def210212_1940

(2)「ContactSend」をクリックします。
def210212_1940_2

(3)スクロールしてエディタに「Lambdaメール送信用コード」を貼り付けます。
def210212_1942_2

「Lambdaメール送信用コード」

import json
import boto3
from urllib.parse import parse_qs
import time
import base64

MAILTO = 'xxxxxxxx@gmail.com'
MAILFROM = 'xxxxxxxx@gmail.com'

def respond(err, res=None):
    return {
        'statusCode': '400' if err else '200',
        'body': err.message if err else json.dumps(res),
        'headers': {
            'Content-Type': 'application/json',
        },
    }

def sendmail(to, subject, body):
    client = boto3.client('ses', region_name='ap-northeast-1')
    response = client.send_email(
        Source=MAILFROM,
        ReplyToAddresses=[MAILFROM],
        Destination= {
            'ToAddresses': [
                to
            ]
        },
        Message={
            'Subject': {
                'Data':subject,
                'Charset':'UTF-8'
            },
            'Body':{
                'Text':{
                    'Data':body,
                    'Charset':'UTF-8'
                }
            }
        }
    )

print('Loading function')

def lambda_handler(event, context):
    print("Received event: " + json.dumps(event))

    try:
        param = base64.b64decode(event['body'])
        param = param.decode("UTF-8")
        param = parse_qs(param)

        company = param['company'][0]
        email = param['email'][0]
        
        ipaddress = event['requestContext']['http']['sourceIp']
        useragent = event['requestContext']['http']['userAgent']
        now = time.time()
        
        mailbody = """
        送信日時 = {0}
        ブラウザ = {1}
        IPアドレス = {2}
        会社名 = {3}
        email = {4}
        """.format(now, useragent, ipaddress, company, email)
        
        subject = company + '様よりお問い合わせがありました'

        sendmail(MAILTO, subject, mailbody)
        
        body = {'result':1}
        return respond(None, body)
    except:
        import traceback
        traceback.print_exc()
        body = {'result':0}
        return respond(None, body)

(4)「Deploy」をクリックして適用します。
def210212_1942_3
フォームを開いて動作確認してみましょう。
def210212_1943
def210212_1944
def210212_1945

受信トレイを確認するとお問い合わせメールが届いています。
def210212_1946_2
ここまでの手順でお問い合わせの基本機能が実現できました。

次回ですが、メールの送信に失敗した場合に備えて、問い合わせ内容をデータベースに保存する処理を追加してみます。