Node.js
AWS
ses
ServerlessFramework

Serverless FrameworkでAmazon SES使ってみた。


Amazon Simple Email Service(SES)とは

Amazonが提供するEメール送信サービス


Serverless Frameworkとは

サーバレスなアプリケーションを開発するツール

GUIでポチポチしなくてすみ、素早く開発ができる


前提

Serverless Frameworkがインストールされている

AWSアカウントを持っていて、AWS CLIでprofile等の設定もできている

IAMにはAmazonSESFullAccess等のSESを利用できるポリシーが設定されている


前準備

AWSコンソールでSimple Email Serviceを開き、送信元、送信先にするメールアドレスを登録、検証を済ませる

SESを提供しているリージョンは現時点では下記の3つ


  • 米国東部(バージニア北部)

  • 米国西部 (オレゴン)

  • 欧州 (アイルランド)

手順

1. 上記3つのリージョンの内のどれかでSimple Email ServiceのサイドバーからEmail Addressesを開く

2. Verify a New Email Addressをクリックし使用するメールアドレス入力

3. 届いたメールのURLから検証を完了

検証済みのメールアドレスでしかメールの送受信を行えない。不特定多数にメールを送信する場合は申請を行う必要がある


Lambda関数作成

適当な場所でServerless Frameworkのcreateコマンドを使ってプロジェクトを作成

$ sls create -t aws-nodejs -p プロジェクト名

プロジェクトフォルダに移動

現時点でのプロジェクトフォルダの中身


  • .gitignore

  • handler.js

  • package.json

  • serverless.yml

handler.js:Lambda関数の内容を記述

serverless.yml:設定ファイル

serverless.ymlをにeventを追記、これによりAmazon API Gatewayが設定される


serverless.yml

service: プロジェクト名

provider:
name: aws
runtime: nodejs8.10

functions:
hello:
handler: handler.hello
events:
- http:
path: hello
method: get


とりあえずデプロイ

$ sls deploy

ターミナルに表示されたエンドポイントを施行

下記が表示されてたら成功


Go Serverless v1.0! Your function executed successfully!



Amazon SESをつかったメール送信機能の作成

AWS SDKをインストール

$ yarn init

$ yarn add aws-sdk

handler.jsを以下のように書き換え


handler.js

'use strict';

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

module.exports.sendMail = (event, context, callback) => {
const ses = new AWS.SES({region: 'us-east-1'}); //メールを登録したリージョン
const data = JSON.parse(event.body);

const params = {
Source: 'sender@example.com',
Destination: {
ToAddresses: ['destination@example.com'], //配列で記述
},
Message: {
Subject: {
Data: '挨拶',
Charset: 'utf-8',
},
Body: {
Html: {
Data: `
<html>
<head>
<style>
body {
font-size: 14px;
color: #484848;
}
</style>
</head>
<body>
<h1>こんにちは</h1>
</body>
</html>
`
,
Charset: 'UTF-8',
},
},
},
};

ses.sendEmail(params, (err, result) => {
if (err) {
console.error(err);
callback(null, {
statusCode: err.statusCode || 501,
headers: {
'Content-Type': 'text/plain',
'Access-Control-Allow-Origin': '*',
},
body: "Couldn't send contact mail",
});
} else {
const response = {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify(result),
};

callback(null, response);
}
});
};


Sourceに送信元メールアドレスを設定

ToAddressesで送信先メールアドレスを設定

送信先メールアドレスは配列で指定する必要がある

どちらも検証済みのメールアドレスのみ使用可能

13行目のMessageからがメールの内容になる

serverless.ymlも書き換え


serverless.yml

service: プロジェクト名

provider:
name: aws
runtime: nodejs8.10
iamRoleStatements:
- Effect: 'Allow'
Action:
- ses:SendEmail
Resource: '*'

functions:
sendMail:
handler: handler.sendMail
events:
- http:
path: send-mail
method: post
cors: true


iamRoleStatementsによって特定の許可ステートメントを設定する。SESをLambdaから使うには上記の記述が必要

詳細は公式を確認

再度デプロイ

$ sls deploy

エンドポイントを施行

メールが届いたら成功

届かなかったら、CloudWatchでエラーを確認


メールの内容をリクエストボディーに応じて変える

LambdaではAPIを叩いた時にAPI Gatewayからeventを受け取り、その中のbodyからリクエストボディーを参照することができる

handler.jsを下記のように変更


handler.js

'use strict';

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

module.exports.sendMail = (event, context, callback) => {
const ses = new AWS.SES({region: 'us-east-1'});
const data = JSON.parse(event.body);

const params = {
Source: 'sender@example.com',
Destination: {
ToAddresses: [data.email],
},
Message: {
Subject: {
Data: data.title,
Charset: 'utf-8',
},
Body: {
Html: {
Data: `
<html>
<head>
<style>
body {
font-size: 14px;
color: #484848;
}
</style>
</head>
<body>
<h1>
${data.body}</h1>
</body>
</html>
`
,
Charset: 'UTF-8',
},
},
},
};

ses.sendEmail(params, (err, result) => {
if (err) {
console.error(err);
callback(null, {
statusCode: err.statusCode || 501,
headers: {
'Content-Type': 'text/plain',
'Access-Control-Allow-Origin': '*',
},
body: "Couldn't send contact mail",
});
} else {
const response = {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
body: JSON.stringify(result),
};

callback(null, response);
}
});
};


APIを叩く際に、下記のようなボディーを記述

{

"email":"destination@example.com",
"title":"ダミー件名",
"body":"ダミー本文"
}

メールの内容がリクエストボディーの内容になっていたら成功