Cognitoユーザープールからの送信メールをカスタマイズする

サービスの認証にCognitoユーザープールを使用する際、**確認コード**や、**初回ログインパスワード**などをメールでお知らせする場合があると思います。

Cognitoのデフォルト設定だとこんなメールが届きます。

```
Your confirmation code is 927173
```
```
Your username is xxxx and temporary password is xxxxxx.
```

この**メールタイトル、本文をカスタマイズする方法**です。

### カスタムメッセージが設定できるイベント

公式ドキュメントからの抜粋です。
以下がカスタムメッセージが設定できるイベントの一覧です。

[AWS Lambda トリガーのリクエストおよびレスポンスパラメータ
](https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html#cognito-user-pools-lambda-trigger-parameters)

| triggerSource 値 | トリガーイベント |
|:--|:--|
| CustomMessage_AdminCreateUser | カスタムメッセージ – 新規ユーザーに一時パスワードを送信するため. |
| CustomMessage_ResendCode | カスタムメッセージ – 既存ユーザーに確認コードを再送するため. |
| CustomMessage_ForgotPassword | カスタムメッセージ - 忘れたパスワードのリクエスト用の確認コードを送信するため. |
| CustomMessage_UpdateUserAttribute | カスタムメッセージ - ユーザーの E メールまたは電話番号が変更されると、このトリガーは確認コードをそのユーザーに自動的に送信します。他の属性には使用できません。 |
| CustomMessage_VerifyUserAttribute | カスタムメッセージ – ユーザーが手動で新しい E メールや電話番号の認証コードをリクエストすると、このトリガーからユーザーに認証コードが送信されます。 |
| CustomMessage_Authentication | カスタムメッセージ - 認証時に MFA コードを送信するため. |

今回はtriggerSource値が**CustomMessage_AdminCreateUser**の場合（Cognitoユーザープールのポリシーに**「管理者のみにユーザーの作成を許可する」**を設定していて、**管理者がユーザーを作成した際にユーザーに送信されるメール**）のカスタマイズを例にします。

# 手順
1. Lambdaファンクションの作成
2. Cognitoユーザープールに1.で作成したファンクションを登録

# 1. Lambdaファンクションの作成
Python3.6での例です。
ファンクションのIAMロールにはCloudwatchログ出力権限の付与だけでOKです。以下IAMポリシーの例です。

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

Lambdaファンクションで受け取るイベントをログ出力するとこのような感じ。

```
{
    "version": "1",
    "region": "ap-northeast-1",
    "userPoolId": "ap-northeast-1_xxxxxxxxx",
    "userName": "hogee",
    "callerContext": {
        "awsSdkVersion": "aws-sdk-js-2.176.0",
        "clientId": "CLIENT_ID_NOT_APPLICABLE"
    },
    "triggerSource": "CustomMessage_AdminCreateUser",
    "request": {
        "userAttributes": {
            "sub": "bf6e9c66-0a69-476e-bfd8-724d38e6555f",
            "cognito:email_alias": "hoge@example.com",
            "email_verified": "True",
            "cognito:user_status": "FORCE_CHANGE_PASSWORD",
            "name": "hoge",
            "email": "hoge@example.com"
        },
        "codeParameter": "{####}",
        "usernameParameter": "{username}"
    },
    "response": {
        "smsMessage": "None",
        "emailMessage": "None",　# ここをカスタムした本文に変える
        "emailSubject": "None"　# ここをカスタムしたタイトルに変える
    }
}
```

このイベントをそのまま`return event`とするとデフォルト設定が適用されたメールが送られます。カスタマイズするには`response`のフィールド内をカスタマイズしたい内容に書き換えてリターンします。

```cognito_custom_message.py
# -*- coding:utf-8 -*-

def handler(event, context):
    if event['triggerSource'] == 'CustomMessage_AdminCreateUser':
        customed_event = custom_message_admin_create_user(event)

    return customed_event


def custom_message_admin_create_user(event):

    email_message = '''
{username} 様
<br>
<br>
管理者から招待されました。
<br>
<br>
ログインメールアドレス：{mail}
<br>
初回ログインパスワード：{password}
'''.format(username='{username}',
           mail=event['request']['userAttributes']['email'],
           password='{####}')

    event['response']['emailSubject'] = '仮パスワード発行のお知らせ'
    event['response']['emailMessage'] = email_message

    return event
```
`{username}`にユーザーネーム、`{####}`にパスワードが入ってメールが送信されることになります。
triggerSourceによって本文に含めなくてはいけないコードパラメータは異るため先ほどの公式ドキュメントで確認してください。
triggerSourceが`CustomMessage_AdminCreateUser`の場合、メッセージ本文に`{username}`と`{####}`が入っていないとエラーになります。

もし追加で他のカスタムメッセージイベントにも対応したい場合、`handler()`で

```
    elif event['triggerSource'] == 'CustomMessage_ForgotPassword':
        customed_event = custom_message_forgot_password(event)
```
とやると対応できます。

# 2. Cognitoユーザープールに1.で作成したファンクションを登録

Lambdaファンクション作成後はCognitoユーザープールのコンソールにいき、**トリガー**→**カスタムメッセージ**から作成したLambdaファンクションを指定します。

<img width="1265" alt="スクリーンショット 2018-02-03 20.03.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/99248/54dd49da-bf0d-00d1-37b9-7259a8039352.png">

serverless frameworkではこのようになります。

```serverless.yml
<略>
functions:
  cognitoCustomMessage:
    handler: functions/cognito_custom_message.handler
    role: CognitoCustomMessageRole
    events:
      - cognitoUserPool:
          pool: UserPool
          trigger: CustomMessage
resources:
  Resources:
    CognitoUserPoolUserPool:
      <以下略>
```

設定後、アプリケーションからユーザーを登録してみると、

<img width="497" alt="スクリーンショット_2018-02-03_20_27_35.png" src="https://qiita-image-store.s3.amazonaws.com/0/99248/ed045298-6478-b8ff-3e5f-7426caa6b2d7.png">

カスタマイズされたメールが届きました。

以上です。