【问题标题】:How to send a custom message for CustomMessage_AdminCreateUser trigger?如何为 CustomMessage_AdminCreateUser 触发器发送自定义消息?
【发布时间】:2019-11-13 20:28:38
【问题描述】:

在为 CustomMessage_AdminCreateUser 触发器发送自定义电子邮件时,我成功更改了从 Amazon Cognito 收到的事件中的 emailSubject 属性,但似乎无法更改 emailMessage 属性。

从 Cognito 发送的电子邮件包含正确的自定义主题,但邮件根本没有自定义,并且始终是在 Cognito 池设置中设置的主题。

处理从 Cognito 接收到的事件的 lambda 处理程序成功地为这些触发器自定义消息:

  • CustomMessage_SignUp
  • CustomMessage_ResendCode
  • CustomMessage_ForgotPassword

但对于CustomMessage_AdminCreateUser 触发器,我似乎无法让它工作(至少不完全)。

我尝试将email_verified 用户属性设置为true,以查看该属性是否取决于成功将自定义邮件发送给创建的用户。此外,我尝试在 Docker 容器中运行 lambda 以查看返回到 Cognito 的最终事件的输出,但该事件包含正确的数据,电子邮件主题和电子邮件消息都是自定义的。

def lambda_handler(event, context):
    if event['userPoolId'] == os.getenv('cognitoPoolId'):
        if CustomMessageTriggerEnum.has_value(event.get('triggerSource')):
            custom_message_trigger = CustomMessageTriggerEnum(event.get('triggerSource'))

            if custom_message_trigger == CustomMessageTriggerEnum.CustomMessageAdminCreateUser:
                custom_message_trigger = CustomMessageAdminCreateUser(event)
            else:
                return None

            custom_response = custom_message_trigger.get_custom_response(
                custom_message_trigger.ACTION,
                custom_message_trigger.EMAIL_SUBJECT,
                custom_message_trigger.EMAIL_MESSAGE
            )
            event = custom_message_trigger.set_custom_response(**custom_response)

            return event
class CustomMessageAdminCreateUser(BaseCustomMessageTrigger):
    """ Custom message admin create user trigger """

    ACTION = "changepassword"
    EMAIL_SUBJECT = "Welcome to {service}"
    EMAIL_MESSAGE = "Your account has been created. <a href='{0}'>Click here</a> to set your password and start using {service}."

    def __init__(self, event):
        super().__init__(event)
class BaseCustomMessageTrigger():
    """ Base custom message trigger """
    def __init__(self, event):
        self.event = event

    def get_custom_response(self, action, email_subject, email_message):
        """ Gets custom response params as dictionary """
        request = self.event.get('request')
        custom_response = {}
        url = self.get_url(
            action=action,
            code=request.get('codeParameter'),
            email=urlencode({'email': request['userAttributes'].get('email')})
        )
        custom_response['emailSubject'] = email_subject
        custom_response['emailMessage'] = email_message.format(url)

        return custom_response

    def set_custom_response(self, **kwargs):
        """ Updates the event response with provided kwargs """
        response = self.event.get('response')
        response.update(**kwargs)

        return self.event

    def get_url(self, action, code, email):
        """ Used for constructing URLs. """
        rawUrl = 'https://{0}/{1}?code={2}&{3}'
        return rawUrl.format(domain, action, code, email)

【问题讨论】:

    标签: python amazon-web-services amazon-cognito amazon-cognito-triggers


    【解决方案1】:

    只是为了澄清电子邮件应该包含event.request.usernameParameterevent.request.codeParameter中的值。

    我发现 Cognito 忽略了我的电子邮件正文,因为令牌 {username} 丢失了,尽管 {####} 在那里。

    【讨论】:

    • 你是怎么发现的,是否有一些 cognito 日志记录?
    • @Townsheriff 抱歉,我不知道。我不记得了。我想我是通过反复试验找到的。我从 Kristine 的回答中了解到出了什么问题,并尝试了不同的排列方式,直到我意识到它想在电子邮件正文中查看这些值。
    【解决方案2】:

    您必须避免在响应参数上使用 urlencode,因为 Lambda 会添加占位符,稍后将被 Cognito 替换。

    【讨论】:

    • 谢谢,这解决了当前的问题,但是下一个问题是如果 Cognito 不能自行处理,如何对 username 字段中的特殊字符进行编码。 + 等特殊字符将被视为空格,此类电子邮件无效。
    【解决方案3】:

    我遇到了完全相同的问题。

    我的初始自定义消息:

    <html>
        <body>
          <p> Welcome. Follow the link below to unlock your account and set a new password.</p>
          <a href="http://localhost:3000/setNewPasswordcode_parameter=${event.request.codeParameter}&user_name=${event.userName}">Set Password</a>
        </body>
    </html>
    

    问题是您需要在模板中同时使用:event.request.codeParameterevent.request.usernameParameter(所以在我的初始代码案例中不是 event.userName)。

    除了 codeParameter 和 usernameParameter 必须只包含 URI 有效字符。因此,如果您的用户名是包含“@”符号的电子邮件地址,则不能在链接中使用它。

    解决方法:对于临时密码,您可以通过传入 TemporaryPassword 参数来确保在调用 adminCreateUser() 时仅使用 URI 有效字符。

    
    cognitoIdentityServiceProvider.adminCreateUser({ 
      UserPoolId,
      Username, 
      TemporaryPassword
    }).promise()
    
    

    对于链接,您可以使用event.userName - 这应该是 cognito 用户的子节点。只需确保在电子邮件中的其他位置包含event.request.usernameParameter。在我的情况下,我以Welcome, ${event.request.usernameParameter}!开始邮件

    【讨论】:

      【解决方案4】:

      CustomMessage_AdminCreateUser 触发器的一件重要事情是您必须在邮件emailMessage 中包含usernamepassword

      def get_url(self, action, code, email):
              """ Used for constructing URLs. """
              rawUrl = 'https://{0}/{1}?code={2}&{3}'
              return rawUrl.format(domain, action, code, email)
      

      请通过domainget_url方法。

      【讨论】:

      • usernamepassword 都作为查询参数包含在 URL 中,我可以从传递给 lambda 处理程序的 Cognito 事件访问这些字段,并使用它们按照我的方式格式化电子邮件想。您是否建议我必须在消息中明确包含它们,即使我只是希望用户能够单击链接而不是复制用户名和临时密码以完成注册?
      • 请通过 get_url 方法传递域。签名 get_url(self, action, code, email):没有 domain 作为 arg。你能分享一下cloudwatch日志吗?
      • 没有必要传递domain,因为它是一个通过环境变量设置的公共变量。 Cloudwatch 没有任何日志,我添加了自定义日志记录以查看事件中的最终 emailSubjectemailMessage 字段,这两个字段都完全符合它们应有的状态,但收到的消息不同。电子邮件主题也正确发送,但实际电子邮件信息不正确。
      • 没错,邮件已发送,邮件主题是预期的,但邮件信息不是。
      猜你喜欢
      • 2021-08-19
      • 1970-01-01
      • 2019-08-07
      • 2019-10-30
      • 2020-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多