

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 自定义电子邮件发件人 Lambda 触发器
<a name="user-pool-lambda-custom-email-sender"></a>

当您为用户池分配自定义电子邮件发件人触发器时，如果用户事件要求 Amazon Cognito 发送电子邮件消息，则它会调用 Lambda 函数，而不是其原定设置行为。使用自定义发件人触发器，您的 AWS Lambda 函数可以通过您选择的方法和提供商向用户发送电子邮件通知。您的函数的自定义代码必须处理和传递用户池中的所有电子邮件消息。

此触发器适用于以下场景：您可能希望更好地控制用户池发送电子邮件消息的方式。您的 Lambda 函数可以自定义对 Amazon SES API 操作的调用，例如，当您想要管理多个经过验证的身份或跨 AWS 区域时。您的函数还可能将消息重定向到另一个传递媒介或第三方服务。

要了解如何配置自定义电子邮件发件人触发器，请参阅[激活自定义发件人 Lambda 触发器](user-pool-lambda-custom-sender-triggers.md#enable-custom-sender-lambda-trigger)。

## 自定义电子邮件发件人 Lambda 触发器源
<a name="trigger-source"></a>

下表显示了 Lambda 代码中自定义电子邮件触发器源的触发事件。


| `TriggerSource value` | 事件 | 
| --- | --- | 
| CustomEmailSender\$1SignUp | 用户注册，Amazon Cognito 随即发送欢迎消息。 | 
| CustomEmailSender\$1Authentication | 用户登录，Amazon Cognito 发送电子邮件 OTP 或 MFA 代码。 | 
| CustomEmailSender\$1ForgotPassword | 用户请求代码以重置其密码。 | 
| CustomEmailSender\$1ResendCode | 用户请求替换账号确认码。 | 
| CustomEmailSender\$1UpdateUserAttribute | 用户更新电子邮件地址或电话号码属性，而 Amazon Cognito 将发送代码用于验证该属性。 | 
| CustomEmailSender\$1VerifyUserAttribute | 用户创建新电子邮件地址或电话号码属性，而 Amazon Cognito 将发送代码用于验证该属性。 | 
| CustomEmailSender\$1AdminCreateUser | 您在用户池中创建新用户，而 Amazon Cognito 向其发送临时密码。 | 
| CustomEmailSender\$1AccountTakeOverNotification | Amazon Cognito 检测到接管用户账户的尝试并向用户发送通知。 | 

## 自定义电子邮件发件人 Lambda 触发器参数
<a name="custom-email-sender-parameters"></a>

Amazon Cognito 传递给此 Lambda 函数的请求是以下参数和 Amazon Cognito 添加到所有请求中的[常用参数](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared)的组合。

------
#### [ JSON ]

```
{
    "request": {
        "type": "customEmailSenderRequestV1",
        "code": "string",
        "clientMetadata": {
            "string": "string",
             . . .
            },
        "userAttributes": {
            "string": "string",
            . . .
         }
}
```

------

### 自定义电子邮件发件人请求参数
<a name="custom-email-sender-request-parameters"></a>

**类型**  
请求版本。对于自定义电子邮件发件人事件，此字符串的值始终为 `customEmailSenderRequestV1`。

**代码**  
您的函数可以解密并发送给您的用户的加密代码。

**clientMetadata**  
一个或多个键值对，您可以将它们作为自定义输入提供给自定义电子邮件发件人 Lambda 函数触发器。要将此数据传递给您的 Lambda 函数，您可以使用[AdminRespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html)和 [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html)API 操作中的 ClientMetadata 参数。Amazon Cognito 在传递给身份验证后函数的请求中不包含来自 ClientMetadata 参数[AdminInitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html)和 [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html)API 操作的数据。  
在具有以下触发源的事件中，Amazon Cognito 会向自定义电子邮件触发函数发送 `ClientMetadata`：  
+ `CustomEmailSender_ForgotPassword`
+ `CustomEmailSender_SignUp`
+ `CustomEmailSender_Authentication`
Amazon Cognito 不会在具有源 `CustomEmailSender_AccountTakeOverNotification` 的触发事件中发送 `ClientMetadata`。

**userAttributes**  
表示用户属性的一个或多个键值对。

### 自定义电子邮件发件人响应参数
<a name="custom-email-sender-response-parameters"></a>

Amazon Cognito 不需要自定义电子邮件发件人响应中有任何其他返回信息。您的 Lambda 函数必须解释事件并解密代码，然后传送消息内容。典型的函数会组装电子邮件消息并将其定向到第三方 SMTP 中继。

## 代码示例
<a name="custom-email-sender-code-examples"></a>

以下 Node.js 示例在您的自定义电子邮件发件人 Lambda 函数中处理电子邮件事件。此示例假设您的函数定义了两个环境变量。

**`KEY_ID`**  
要用于加密和解密用户代码的 KMS 密钥的 ID。

**`KEY_ARN`**  
要用于加密和解密用户代码的 KMS 密钥的 Amazon 资源名称 (ARN)。

**部署此函数**

1. 在开发者工作区中安装最新版本的 NodeJS。

1. 在您的工作区中新建一个 NodeJS 项目。

1. 使用 `npm init -y` 初始化您的项目。

1. 为 Lambda 函数 `touch index.mjs` 创建脚本。

1. 将以下示例的内容粘贴到 `index.mjs`。

1. 下载项目依赖关系， AWS Encryption SDK:`npm install @aws-crypto/client-node`.

1. 将项目目录压缩为文件 `zip -r my_deployment_package.zip .`。

1. [将该 ZIP 文件部署到函数](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-package.html)。

此函数示例会解密代码，并在注册事件中模拟向用户的电子邮件地址发送电子邮件消息。

```
import { KmsKeyringNode, buildClient, CommitmentPolicy } from '@aws-crypto/client-node';

// Configure the encryption SDK client with the KMS key from the environment variables
const { encrypt, decrypt } = buildClient(
    CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT
);

const generatorKeyId = process.env.KEY_ID;
const keyIds = [process.env.KEY_ARN];
const keyring = new KmsKeyringNode({ generatorKeyId, keyIds });

// Example function to simulate sending email.
// This example logs message details to CloudWatch Logs from your Lambda function.
// Update this function with custom logic that sends an email message to 'emailaddress' with body 'message'.
const sendEmail = async (emailAddress, message) => {
    // Log the destination with the email address masked.
    console.log(`Simulating email send to ${emailAddress.replace(/[^@.]/g, '*')}`);
    // Log the message with the code masked.
    console.log(`Message content: ${message.replace(/\b\d{6,8}\b/g, '********')}`);
    // Simulate API delay
    await new Promise(resolve => setTimeout(resolve, 100));
    console.log('Email sent successfully');
    return true;
};

export const handler = async (event) => {
    try {
        // Decrypt the secret code using encryption SDK
        let plainTextCode;
        if (event.request.code) {
            const { plaintext, messageHeader } = await decrypt(keyring, Buffer.from(event.request.code, 'base64'));
            plainTextCode = Buffer.from(plaintext).toString('utf-8');
        }

        // Handle different trigger sources
        if (event.triggerSource == 'CustomEmailSender_SignUp') {
            const emailAddress = event.request.userAttributes.email;
            const message = `Welcome! Your verification code is: ${plainTextCode}`;
            await sendEmail(emailAddress, message);
        }
        else if (event.triggerSource == 'CustomEmailSender_ResendCode') {
            // Handle resend code
        }
        else if (event.triggerSource == 'CustomEmailSender_ForgotPassword') {
            // Handle forgot password
        }
        else if (event.triggerSource == 'CustomEmailSender_UpdateUserAttribute') {
            // Handle update attribute
        }
        else if (event.triggerSource == 'CustomEmailSender_VerifyUserAttribute') {
            // Handle verify attribute
        }
        else if (event.triggerSource == 'CustomEmailSender_AdminCreateUser') {
            // Handle admin create user
        }
        else if (event.triggerSource == 'CustomEmailSender_Authentication') {
            // Handle authentication
        }
        else if (event.triggerSource == 'CustomEmailSender_AccountTakeOverNotification') {
            // Handle account takeover notification
        }

        return;
    } catch (error) {
        console.error('Error in custom email sender:', error);
        throw error;
    }
};
```