LoginSignup
5
3

More than 5 years have passed since last update.

S3+Lambda+SESでのフォーム作成

Last updated at Posted at 2017-09-25

S3+Cognito+Lambda+SESでのフォーム作成

WEBページをS3+CloudFrontに移したので問い合わせフォームが使えなくなり、せっかくなのでAWSの機能を組み合わせてみようと思ったところ

先人の方が作っていたようなので、AWSのドキュメントと突き合わせつつ作成
*ついでにIE5の時代で止まっていたJavaScriptの勉強しなおしも兼ねて…

regionはSESのみus-east、後のサービスは東京に統一して作成。

以下、参考先から弄ったところを列挙

Lambdaの設定

設定

Lambda側ではinquiry_ + .txtのものがPutされた場合に関数が走るよう設定を行う

ポリシー

Lambda上で関数を作成する際のポリシー作成でSES権限を付与してもses.SendBounceの権限で作成される為、ses.SendEmailで送ろうとしている場合、当然許可はされず送信は出来ない
そのため、ポリシー選択でAmazonSESの権限は追加せず、S3の権限のみを選択し、関数を作成
その後、ses.sendEmailの権限を付与するカスタムポリシーを作成し、IAMロールに追加する

SES
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1505896993000",
            "Effect": "Allow",
            "Action": [
                "ses:SendEmail"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

フォームのJS

index.js
    'use strict';
    const $id = function (id) { return document.getElementById(id); };

    AWS.config.region = 'ap-northeast-1'; // リージョン
    AWS.config.credentials = new AWS.CognitoIdentityCredentials({
      IdentityPoolId: 'ap-northeast-1:xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
    });
    AWS.config.credentials.get(function (err) {
      if (err) {
        return alert('初期化に失敗しました。')
      }
    });

    const upload = function () {

      AWS.config.region = "ap-northeast-1";
      const s3BucketName = "inquiry.example.com";
      const date = new Date();

      const mail_param = {
        "name": $id("name").value
        , "kana": $id("kana").value
        , "company": $id("company").value
        , "tel": $id("tel").value
        , "mail": $id("mail").value
        , "date": date.toLocaleString("ja")
      };

      const s3 = new AWS.S3({ params: { Bucket: s3BucketName } });
      const blob = new Blob([JSON.stringify(mail_param)], { type: 'text/plain' });

      s3.putObject(
        {
          Key: `inquiry_${date.getTime()}.txt`
          , ContentType: "text/plain"
          , Body: blob
          , ACL: "private"
        },
        function (err, data) {
          if (err) {
            console.log(err, err.stack);
            return alert(err.message);
          } else {
            location.assign("./thanks.html");
          }
        }
      );
    };

LambdaのJS

mail.js
'use strict';

console.log('Loading function');

const aws = require('aws-sdk');
const s3 = new aws.S3({ apiVersion: '2006-03-01' });
const ses = new aws.SES({ apiVersion: '2010-12-01', region: 'us-east-1' });

exports.handler = (event, context, callback) => {
    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 {
            const json = JSON.parse(data.Body.toString());
            console.log(`title:${json.title}`);

            const message = `
                名前: ${json.name}(${json.kana})            
                会社: ${json.company}
                TEL:  ${json.tel}
                MAIL: ${json.mail}
                問合せ日時:
                ${json.date}
                `

            const params = {
                Destination: {
                    ToAddresses: [process.env.TOADDRESS]
                },
                Message: {
                    Body: {
                        Text: {
                            Charset: "UTF-8",
                            Data: message
                        }
                    },
                    Subject: {
                        Charset: "UTF-8",
                        Data: "フォームからのお問い合わせ"
                    }
                },
                Source: process.env.SOURCEADDRESS
            };
            ses.sendEmail(params, function (err, data) {
                if (err) console.log(err, err.stack);
                else console.log(data);
            });

        }
    });
};

引っかかったところ

S3への書き込み権限エラー

S3にアップロードする際に、権限のエラーでアップロードが出来ない
ARNはバケットのプロパティからコピーした筈だから…とハマる

エラー時のポリシー
policy.before
"Resource": [
       "arn:aws:s3:::inquiry.example.com"
]

ARNをS3のバケットに対してのものと勘違いし、バケットのARNをそのままコピペした所
ファイルに対しての権限が無いため、アップロードがエラーに…

修正したポリシー
policy.after
"Resource": [
       "arn:aws:s3:::inquiry.example.com/*"
]
5
3
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
5
3