Python
AWS
cognito
serverless

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

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

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

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

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

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

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

AWS Lambda トリガーのリクエストおよびレスポンスパラメータ

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ファンクションを指定します。

スクリーンショット 2018-02-03 20.03.27.png

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

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

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

スクリーンショット_2018-02-03_20_27_35.png

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

以上です。