Help us understand the problem. What is going on with this article?

AWS Lambda + API Gateway で作るサーバーレス問い合わせ機能

静的ページ用の問い合わせ機能を、AWS Lambda + API Gateway (+ Amazon SES) でサーバーレスに実装する手順を整理します。

GitHubのソースコードはこちら

手順

設計の全体像は、クライアントから API Gateway の POST メソッドを呼び出し、それをトリガーに Lambda 関数を発火させて、SES の送信用メールアドレスで管理者にメール通知をおこなう感じです。

1. Amazon SES

まずは問い合わせ内容を通知するためのメールアドレスの設定です。

メールアドレスの追加・認証

Amazon SESの管理画面で、送信用のメールアドレスを追加し、届いたメールから認証を完了させます。

ドメイン用 DKIM の設定

設定したアドレスからSESでメールを送信する時に、送信元アドレスとして xxx@xxx.com via amazon.com のように via amazon.com と表記されることがあります。

この via amazon.com を消すために DKIM の設定をします。

Amazon SESの管理画面から送信用アドレスの詳細ページにいき、「DKIM」のCNAMEの値を入手します。

スクリーンショット 2020-04-23 22.33.56.png

このCNAMEの3つをメールアドレスのドメインのDNSレコードに追加します。

2. AWS Lambda

続いて、問い合わせ通知の処理を AWS Lambda で実装します。

IAMロール

まずは IAMの管理画面で今回の Lambda に適用するロールを作成します。

ロールは以下のJSONで規定します。


{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    }
    ,{
       "Effect": "Allow",
       "Action": ["ses:Send*"],
       "Resource":"*"
     }
  ]
}

Lambda 関数の作成

Lambda の管理画面で新しい関数を作成します。アクセス権限には、先ほど作成したロールを割り当てます。

index.js の更新

index.js を次のように更新します。region:Source はご自身の情報に修正してください。

index.js
'use strict'
const SDK = require('aws-sdk')

exports.handler = (event, context, callback) => {
    const ses = new SDK.SES({ region: 'ap-southeast-2' })
    const email = {
        // From
        Source: "YOUR_EMAIL_ADDRESS",
        // To
        Destination: { ToAddresses: [event.form.to] },
        Message: {
            Subject: { Data: event.form.subject },
            Body: {
                Text: { Data: event.form.body }
            },
        },
    };
    ses.sendEmail(email, callback);
};

3. API Gateway

最後に API Gateway で、問い合わせを受け付けるエンドポイントを作ります。

API の新規作成

上で作成した Lambda 関数のページの「トリガーを追加」で API Gateway の REST API を新規作成します。

リソースの追加

作成後、同 REST API のページに自動的に移動します。

「アクション > リソースの追加」で、/send など、任意のリソースを追加します。

POST メソッドの追加

「アクション > メソッドの追加」で、追加したリソースに POST メソッドを追加します。

POST メソッドの設定

リクエストマッピングテンプレート

POST メソッドの詳細ページ「統合リクエスト > マッピングテンプレート」で application/json のマッピングテンプレートを追加します。テンプレートの記載内容は次の通りです。

application/json
{
    "form": $input.json('$')
}
レスポンスヘッダー

POST メソッドの詳細ページ「メソッドレスポンス > 200 のレスポンスヘッダー」で Access-Control-Allow-Origin というヘッダーを追加します。

その後、「統合レスポンス > ヘッダーのマッピング」で次のように値をセットします。

レスポンスヘッダー マッピングの値
Access-Control-Allow-Origin '*'

上記設定がないと、僕の環境下では、クライアントから呼び出した時に

No 'Access-Control-Allow-Origin' header is present on the requested resource

のエラーが出ました。この Access-Control-Allow-Origin の設定で解決できました。

API のデプロイ

「アクション > API のデプロイ」で、任意のステージ(v1 など)に REST API をデプロイします。

ステージの「URL の呼び出し」にエンドポイントの記載があります。

POST https://xxxxxx.execute-api.YOUR_REGION.amazonaws.com/v1/YOUR_API_NAME/send

このエンドポイントで作成した POST メソッドを呼び出せます。

4. クライアントでの呼び出し

静的ページから POST リクエストで API Gateway のエンドポイントを呼ぶことで、Lambda 関数が発火します。

jQuery で利用する場合、次のように呼び出します。

function submitContact(url, to, subject, body) {
  const jsonData = JSON.stringify({
    'to':      to,
    'subject': subject,
    'body':    body
  })

  $.ajax({
    type: "POST",
    url:   url,
    async: true,
    contentType: 'application/json',
    dataType: 'json',
    data: jsonData,
    error: function(data) { 
      console.log(data)
    },
    success: function(data) {
      console.log(data)
    }
  })
}

References

kskinaba
Amazon, eBay, Shopify等、Eコマース関連のバックエンドを主に開発してます。最近は専らShopifyアプリの開発に励んでます。業務のご依頼・ご相談はお気軽にメールください 😃 Ruby / Rails / Next.js/ TypeScript / Vue.js / Go | 兵庫県西宮市出身 | Mediumでも記事書いてます↓
https://medium.com/@kei178
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした