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](https://console.aws.amazon.com/ses)のサイドバーから`Email Addresses`を開く
2. `Verify a New Email Address`をクリックし使用するメールアドレス入力
3. 届いたメールのURLから検証を完了

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

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

```console
$ 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
```

とりあえずデプロイ

```console
$ sls deploy
```

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

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

> Go Serverless v1.0! Your function executed successfully!

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

AWS SDKをインストール

```console
$ 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から使うには上記の記述が必要
詳細は[公式](https://serverless.com/framework/docs/providers/aws/guide/iam/#the-default-iam-role)を確認

再度デプロイ

```console
$ 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を叩く際に、下記のようなボディーを記述

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

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