LoginSignup
7
8

More than 5 years have passed since last update.

S3 + Cognito+Lambda+SNSでフォーム投稿内容をメール通知

Last updated at Posted at 2016-11-23

概要

S3にホストしたHTMLファイルから問い合わせ内容を投稿するとメールを飛ばす。基本的には下記をなぞらせていただきつつ、メール送信をSNS経由に変更。

S3 + Lambda + Cognitoを使って、簡単お問い合わせシステム構築

問い合わせ内容はS3にファイルとして保存、S3へのアップロード権限を付与するためにCognitoを利用。

S3のファイル保存をトリガーにLambdaを起動して、SNS経由でメール送信。

構成.PNG

sequence.PNG

S3

  • Bucketを作成
  • 静的ウェブサイトホスティングを有効に
    • インデックスドキュメント:index.html
  • アクセス許可 -> CORS設定の編集
    • ホストした静的ウェブサイト(別origin)からクロスドメインでPOSTできるようにするため
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>http://{静的ウェブサイトホスティングのエンドポイント}</AllowedOrigin>
        <AllowedMethod>PUT</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

Cognito

  • Federated Identities -> Create new identity pool
  • Enable access to unauthenticated identitiesをチェック
  • じどう作成されるRole(今回はUnauthenticate roleを利用する)に、S3へのput権限をつける
    • IAMのRoleからインラインポリシー -> ロールポリシーの作成
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::{bucket名}/*"
            ]
        }
    ]
}

S3に問い合わせフォーム本体をアップロード

SNS

  • Create new topics -> Create Subscription
    • Protocol: Email
    • Endpoint: 自身のメールアドレス
  • メール認証を済ませておく

Lambda

  • Roleの作成
    • サービスロール:AWS Lambda
    • ポリシーのアタッチ
      • AWSLambdaExecute
      • AmazonSNSFullAccess
      • s3の権限は、AWSLambdaExecuteに含まれているので不要
  • Functionの作成
    • Node.js -> s3-get-object

lambda.PNG

  • Bucket: 上記で作成したBucket
  • EventType: Object Created
  • Prefix: uploads(投稿フォームhtml上のSDK呼び出し時に指定しているKey)
  • EnableTriggerをチェック
  • 上記で作成したRoleを指定
  • なおLambda環境変数対応が発表されて実際に画面に指定する箇所ができていたので試してみた。が、環境変数を指定するとなぜか"Please correct the errors below."とエラーになり諦めた。。

'use strict';

console.log('Loading function');

const aws = require('aws-sdk');

const s3 = new aws.S3({ apiVersion: '2006-03-01' });

const sns = new aws.SNS({
   apiVersion: '2010-03-31',
   region: 'ap-northeast-1'
});

exports.handler = (event, context, callback) => {
    //console.log('Received event:', JSON.stringify(event, null, 2));

    // Get the object from the event and show its content type
    const bucket = event.Records[0].s3.bucket.name;
    const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));
    const params = {
        Bucket: bucket,
        Key: key
    };
    s3.getObject(params, (err, data) => {
        if (err) {
            console.log(err);
            const message = `Error getting object ${key} from bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.`;
            console.log(message);
            callback(message);
        } else {
            var json = JSON.parse(data.Body.toString());
            console.log('title:' + json.title);
            var message = '■日時\n' + json.date + '\n\n■件名\n' + json.title +
                '\n\n■メールアドレス\n' + json.mail + '\n\n■内容\n' + json.contents;
            sns.publish({
                Message: message,
                Subject: '問い合わせ['+ json.title + ']',
                TopicArn: "{SNSのARN}"
            }, function(err, data){
                if (err) {
                    context.fail('fail');
                } else {
                    callback(null, json.title);
                }
            });  
        }
    });
};

実行

  • S3の静的ウェブサイトホスティングのエンドポイントにブラウザでアクセス
  • 問い合わせ内容を適当に入力して「投稿」(なおメールアドレスは何にも使わないため適当でOK)

入力.PNG

  • こんな感じのメールが届くはず!
    mail.PNG

  • S3のBucketのuploads以下に入力内容を格納したファイルが作成されている

トラブルシューティング

  • s3 bucketに対するOPTIONSのrequestで403 Forbiddenが返ってきている場合
    • CORSに設定したAllowedOriginが、request headerのoriginと一致しているかを確認(http://に注意)
  • s3 bucketに対するPUTのrequestで403 Forbiddenが返ってきている場合
    • cognitoで作成されたUnauthenticate roleに対して、s3へのput権限が付与できているかを確認
  • lambdaからsnsへのpublishがエラーになる
    • lambda内で正しいregionが指定できているかを確認

参考

7
8
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
7
8