

# Custom sender Lambda triggers
<a name="user-pool-lambda-custom-sender-triggers"></a>

The Lambda triggers `CustomEmailSender` and `CustomSMSSender` support third-party email and SMS notifications in user pools. You can choose SMS and email providers to send notifications to users from within your Lambda function code. When Amazon Cognito sends invitations, MFA codes, confirmation codes, verification codes, and temporary passwords to users, the events activate your configured Lambda functions. Amazon Cognito sends the code and temporary passwords (secrets) to your activated Lambda functions. Amazon Cognito encrypts these secrets with an Amazon KMS customer managed key and the Amazon Encryption SDK. The Amazon Encryption SDK is a client-side encryption library that helps you to encrypt and decrypt generic data.

**[CustomEmailSender](user-pool-lambda-custom-email-sender.md)**  
Amazon Cognito invokes this trigger to send email notifications to users. 

**[CustomSMSSender](user-pool-lambda-custom-sms-sender.md)**  
Amazon Cognito invokes this trigger to send SMS notifications to users.

## Encryption concepts
<a name="user-pool-lambda-custom-sender-triggers-resources"></a>

Amazon Cognito doesn't send users' codes in plaintext in the events that it sends to custom sender triggers. The Lambda functions must decrypt codes in the events. The following concepts are the encryption architecture that your function must use to get codes that it can deliver to users.

**Amazon KMS**  
Amazon KMS is a managed service to create and control Amazon KMS keys. These keys encrypt your data. For more information see, [What is Amazon Key Management Service?](/kms/latest/developerguide/overview.html).

**KMS key**  
A KMS key is a logical representation of a cryptographic key. The KMS key includes metadata, such as the key ID, creation date, description, and key state. The KMS key also contains the key material used to encrypt and decrypt data. For more information see, [Amazon KMS keys](https://docs.amazonaws.cn/kms/latest/developerguide/concepts.html#kms_keys).

**Symmetric KMS key**  
A symmetric KMS key is a 256-bit encryption key that doesn't exit Amazon KMS unencrypted. To use a symmetric KMS key, you must call Amazon KMS. Amazon Cognito uses symmetric keys. The same key encrypts and decrypts. For more information see, [Symmetric KMS keys](https://docs.amazonaws.cn/kms/latest/developerguide/concepts.html#symmetric-cmks). 

## Things to know about custom sender Lambda triggers
<a name="user-pool-lambda-custom-sender-triggers-things-to-know"></a>
+ To configure your user pools to use these Lambda triggers, you can use the Amazon CLI or SDK. These configurations aren't available from Amazon Cognito console.

  The `UpdateUserPool` operation sets Lambda configuration. Requests to this operation require all the parameters of your user pool *and* the parameters that you want to change. If you don't provide all relevant parameters, Amazon Cognito sets the values of any missing parameters to their defaults. As demonstrated in the Amazon CLI example that follows, include entries for all Lambda functions that you want to add to or keep in your user pool. For more information, see [Updating user pool and app client configuration](cognito-user-pool-updating.md).

  ```
      #Send this parameter in an 'aws cognito-idp update-user-pool' CLI command, including any existing 
      #user pool configurations. This snippet also includes a pre sign-up trigger for syntax reference. The pre sign-up trigger
      #doesn't have a role in custom sender triggers.
                
        --lambda-config "PreSignUp=lambda-arn, \
                         CustomSMSSender={LambdaVersion=V1_0,LambdaArn=lambda-arn}, \
                         CustomEmailSender={LambdaVersion=V1_0,LambdaArn=lambda-arn}, \
                         KMSKeyID=key-id"
  ```

  For requests that use the JSON body of `UpdateUserPool` the following `LambdaConfig` snippet assigns custom SMS and email sender functions.

  ```
  "LambdaConfig": {
     "KMSKeyID": "arn:aws:kms:us-east-1:111122223333:key/a6c4f8e2-0c45-47db-925f-87854bc9e357",
     "CustomEmailSender": {
        "LambdaArn": "arn:aws:lambda:us-east-1:111122223333:function:MyFunction",
        "LambdaVersion": "V1_0"
     },
     "CustomSMSSender": {
        "LambdaArn": "arn:aws:lambda:us-east-1:111122223333:function:MyFunction",
        "LambdaVersion": "V1_0"
     }
  ```
+ To remove a custom sender Lambda trigger with an `update-user-pool` Amazon CLI command, omit the `CustomSMSSender` or `CustomEmailSender` parameter from `--lambda-config`, and include all other triggers that you want to use with your user pool.

  To remove a custom sender Lambda trigger with an `UpdateUserPool` API request, omit the `CustomSMSSender` or `CustomEmailSender` parameter from the request body that contains the rest of your user pool configuration.
+ Amazon Cognito HTML-escapes reserved characters like `<` (`&lt;`) and `>` (`&gt;`) in your user's temporary password. These characters might appear in temporary passwords that Amazon Cognito sends to your custom email sender function, but don't appear in temporary verification codes. To send temporary passwords, your Lambda function must unescape these characters after it decrypts the password, and before it sends the message to your user.

## Activating custom sender Lambda triggers
<a name="enable-custom-sender-lambda-trigger"></a>

To use custom logic to send SMS or email messages for your user pool, set up custom sender triggers. The following procedure assigns a custom SMS trigger, a custom email trigger, or both to your user pool. After you add your custom sender trigger, Amazon Cognito always sends user attributes, including the phone number, and the one-time code to your Lambda function instead of the default behavior that sends an SMS or email message.

1. Create a [symmetric encryption key](https://docs.amazonaws.cn/kms/latest/developerguide/concepts.html#symmetric-cmks) in Amazon Key Management Service (Amazon KMS). Amazon Cognito generates secrets—temporary passwords, verification codes, authentication one-time passwords, and confirmation codes—then uses this KMS key to encrypt the secrets with [Amazon Encryption SDK](https://docs.amazonaws.cn/encryption-sdk/latest/developer-guide/introduction.html). You can then use the Amazon Encryption SDK in your Lambda function to decrypt the secrets and send them to the user in plaintext.

1. The IAM principal that creates or updates your user pool creates a one-time grant against the KMS key that Amazon Cognito uses to encrypt the code. Grant this principal `CreateGrant` permissions for your KMS key. For this example KMS key policy to be effective, the administrator who updates the user pool must be signed in with an assumed-role session for the IAM role `arn:aws:iam::111222333444:role/my-example-administrator-role`. 

   Apply the following resource-based policy, modified for your environment, to your KMS key.

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

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
       {
           "Effect": "Allow",
           "Principal": {
               "AWS": "arn:aws-cn:iam::111122223333:role/my-example-administrator-role"
           },
           "Action": "kms:CreateGrant",
           "Resource": "arn:aws-cn:kms:us-west-2:111122223333:key/1example-2222-3333-4444-999example",
           "Condition": {
               "StringEquals": {
                  "kms:EncryptionContext:userpool-id": "us-west-2_EXAMPLE"
               }
           }
       },
       {
           "Sid": "Allow Lambda to decrypt",
           "Effect": "Allow",
           "Principal": {
               "AWS": "arn:aws-cn:iam::111122223333:role/my-lambda-function-role"
           },
           "Action": "kms:Decrypt",
           "Resource": "*"
       }]
   }
   ```

------

1. Create a Lambda function for the custom sender trigger. Amazon Cognito uses the [Amazon encryption SDK](https://docs.amazonaws.cn/encryption-sdk/latest/developer-guide/introduction.html) to encrypt the secrets, temporary passwords and codes that authorize your users' API requests.

   1. Assign a [Lambda execution role](https://docs.amazonaws.cn/lambda/latest/dg/lambda-intro-execution-role.html) that has, at minimum, `kms:Decrypt` permissions for your KMS key.

   1. Compose Lambda function code to send your messages. The input event to your function contains a secret. In your function, decrypt the secret with the Amazon Encryption SDK and process any relevant metadata. Then send the code, your own custom message, and destination phone number to the custom API that delivers your message.

   1. Add the Amazon Encryption SDK to your Lambda function. For more information, see [Amazon Encryption SDK programming languages](https://docs.amazonaws.cn/encryption-sdk/latest/developer-guide/programming-languages.html). To update the Lambda package, complete the following steps.

      1. Export your Lambda function as a .zip file in the Amazon Web Services Management Console.

      1. Open your function and add the Amazon Encryption SDK. For more information and download links, see [Amazon Encryption SDK programming languages](https://docs.amazonaws.cn/encryption-sdk/latest/developer-guide/programming-languages.html) in the *Amazon Encryption SDK Developer Guide*.

      1. Zip your function with your SDK dependencies, and upload the function to Lambda. For more information, see [Deploying Lambda functions as .zip file archives](https://docs.amazonaws.cn/lambda/latest/dg/configuration-function-zip.html#configuration-function-create) in the *Amazon Lambda Developer Guide*.

1. Grant Amazon Cognito service principal `cognito-idp.amazonaws.com` access to invoke the Lambda function.

   The following Amazon CLI command grants Amazon Cognito permission to invoke your Lambda function:

   ```
   aws lambda add-permission --function-name lambda_arn --statement-id "CognitoLambdaInvokeAccess" --action lambda:InvokeFunction --principal cognito-idp.amazonaws.com
   ```

1. Generate an [UpdateUserPool](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_UpdateUserPool.html) API request with a `LambdaConfig` parameter that adds custom sender Lambda triggers. You can't add triggers of this type in the Amazon Cognito console. Custom sender triggers require `LambdaConfig` parameters of `KMSKeyID` and `CustomSMSSender` or `CustomEmailSender` (or both).

# Custom email sender Lambda trigger
<a name="user-pool-lambda-custom-email-sender"></a>

When you assign a custom email sender trigger to your user pool, Amazon Cognito invokes a Lambda function instead of its default behavior when a user event requires that it send an email message. With a custom sender trigger, your Amazon Lambda function can send email notifications to your users through a method and provider that you choose. The custom code of your function must process and deliver all email messages from your user pool.

This trigger serves scenarios where you might want to have greater control over how your user pool sends email messages. Your Lambda function can customize the call to Amazon SES API operations, for example when you want to manage multiple verified identities or cross Amazon Web Services Regions. Your function also might redirect messages to another delivery medium or third-party service.

To learn how to configure a custom email sender trigger, see [Activating custom sender Lambda triggers](user-pool-lambda-custom-sender-triggers.md#enable-custom-sender-lambda-trigger).

## Custom email sender Lambda trigger sources
<a name="trigger-source"></a>

The following table shows the triggering events for custom email trigger sources in your Lambda code.


| `TriggerSource value` | Event | 
| --- | --- | 
| CustomEmailSender\$1SignUp | A user signs up and Amazon Cognito sends a welcome message. | 
| CustomEmailSender\$1Authentication | A user signs in and Amazon Cognito sends an email OTP or MFA code. | 
| CustomEmailSender\$1ForgotPassword | A user requests a code to reset their password. | 
| CustomEmailSender\$1ResendCode | A user requests a replacement account-confirmation code. | 
| CustomEmailSender\$1UpdateUserAttribute | A user updates an email address or phone number attribute and Amazon Cognito sends a code to verify the attribute. | 
| CustomEmailSender\$1VerifyUserAttribute | A user creates a new email address or phone number attribute and Amazon Cognito sends a code to verify the attribute. | 
| CustomEmailSender\$1AdminCreateUser | You create a new user in your user pool and Amazon Cognito sends them a temporary password. | 
| CustomEmailSender\$1AccountTakeOverNotification | Amazon Cognito detects an attempt to take over a user account and sends the user a notification. | 

## Custom email sender Lambda trigger parameters
<a name="custom-email-sender-parameters"></a>

The request that Amazon Cognito passes to this Lambda function is a combination of the parameters below and the [common parameters](https://docs.amazonaws.cn/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared) that Amazon Cognito adds to all requests.

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

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

------

### Custom email sender request parameters
<a name="custom-email-sender-request-parameters"></a>

**type**  
The request version. For a custom email sender event, the value of this string is always `customEmailSenderRequestV1`.

**code**  
The encrypted code that your function can decrypt and send to your user.

**clientMetadata**  
One or more key-value pairs that you can provide as custom input to the custom email sender Lambda function trigger. To pass this data to your Lambda function, you can use the ClientMetadata parameter in the [AdminRespondToAuthChallenge](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) and [RespondToAuthChallenge](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) API actions. Amazon Cognito doesn't include data from the ClientMetadata parameter in [AdminInitiateAuth](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html) and [InitiateAuth](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) API operations in the request that it passes to the post authentication function.  
Amazon Cognito sends `ClientMetadata` to custom email trigger functions in events with the following trigger sources:  
+ `CustomEmailSender_ForgotPassword`
+ `CustomEmailSender_SignUp`
+ `CustomEmailSender_Authentication`
Amazon Cognito doesn't send `ClientMetadata` in trigger events with source `CustomEmailSender_AccountTakeOverNotification`.

**userAttributes**  
One or more key-value pairs that represent user attributes.

### Custom email sender response parameters
<a name="custom-email-sender-response-parameters"></a>

Amazon Cognito doesn't expect any additional return information in the custom email sender response. Your Lambda function must interpret the event and decrypt the code, then deliver the message contents. A typical function assembles an email message and directs it to a third-party SMTP relay.

## Code example
<a name="custom-email-sender-code-examples"></a>

The following Node.js example processes an email message event in your custom email sender Lambda function. This example assumes your function has two environment variables defined.

**`KEY_ID`**  
The ID of the KMS key that you want to use to encrypt and decrypt your users' codes.

**`KEY_ARN`**  
The Amazon Resource Name (ARN) of the KMS key that you want to use to encrypt and decrypt your users' codes.

**To deploy this function**

1. Install the latest version of NodeJS in your developer workspace.

1. Create a new NodeJS project in your workspace.

1. Initialize your project with `npm init -y`.

1. Create the script for the Lambda function: `touch index.mjs`.

1. Paste the contents of the below example into `index.mjs`.

1. Download the project dependency, Amazon Encryption SDK: `npm install @aws-crypto/client-node`.

1. Zip the project directory into a file: `zip -r my_deployment_package.zip .`.

1. [Deploy the ZIP file to your function](https://docs.amazonaws.cn/lambda/latest/dg/nodejs-package.html).

This example function decrypts the code and, for sign-up events, simulates sending an email message to the user's email address.

```
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;
    }
};
```

# Custom SMS sender Lambda trigger
<a name="user-pool-lambda-custom-sms-sender"></a>

When you assign a custom SMS sender trigger to your user pool, Amazon Cognito invokes a Lambda function instead of its default behavior when a user event requires that it send an SMS message. With a custom sender trigger, your Amazon Lambda function can send SMS notifications to your users through a method and provider that you choose. The custom code of your function must process and deliver all SMS messages from your user pool.

This trigger serves scenarios where you might want to have greater control over how your user pool sends SMS messages. Your Lambda function can customize the call to Amazon SNS API operations, for example when you want to manage multiple origination IDs or cross Amazon Web Services Regions. Your function also might redirect messages to another delivery medium or third-party service.

To learn how to configure a custom email sender trigger, see [Activating custom sender Lambda triggers](user-pool-lambda-custom-sender-triggers.md#enable-custom-sender-lambda-trigger).

## Custom SMS sender Lambda trigger sources
<a name="trigger-source"></a>

The following table shows the triggering event for custom SMS trigger sources in your Lambda code.


| `TriggerSource value` | Event | 
| --- | --- | 
| CustomSMSSender\$1SignUp | A user signs up and Amazon Cognito sends a welcome message. | 
| CustomSMSSender\$1ForgotPassword | A user requests a code to reset their password. | 
| CustomSMSSender\$1ResendCode | A user requests a new code to confirm their registration. | 
| CustomSMSSender\$1VerifyUserAttribute | A user creates a new email address or phone number attribute and Amazon Cognito sends a code to verify the attribute. | 
| CustomSMSSender\$1UpdateUserAttribute | A user updates an email address or phone number attribute and Amazon Cognito sends a code to verify the attribute. | 
| CustomSMSSender\$1Authentication | A user signs in and Amazon Cognito sends an SMS OTP or MFA code. | 
| CustomSMSSender\$1AdminCreateUser | You create a new user in your user pool and Amazon Cognito sends them a temporary password. | 

## Custom SMS sender Lambda trigger parameters
<a name="custom-sms-sender-parameters"></a>

The request that Amazon Cognito passes to this Lambda function is a combination of the parameters below and the [common parameters](https://docs.amazonaws.cn/cognito/latest/developerguide/cognito-user-pools-working-with-lambda-triggers.html#cognito-user-pools-lambda-trigger-syntax-shared) that Amazon Cognito adds to all requests.

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

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

------

### Custom SMS sender request parameters
<a name="custom-sms-sender-request-parameters"></a>

**type**  
The request version. For a custom SMS sender event, the value of this string is always `customSMSSenderRequestV1`.

**code**  
The encrypted code that your function can decrypt and send to your user.

**clientMetadata**  
One or more key-value pairs that you can provide as custom input to the custom SMS sender Lambda function trigger. To pass this data to your Lambda function, you can use the ClientMetadata parameter in the [AdminRespondToAuthChallenge](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_AdminRespondToAuthChallenge.html) and [RespondToAuthChallenge](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) API actions. Amazon Cognito doesn't include data from the ClientMetadata parameter in [AdminInitiateAuth](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_AdminInitiateAuth.html) and [InitiateAuth](https://docs.amazonaws.cn/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) API operations in the request that it passes to the post authentication function.

**userAttributes**  
One or more key-value pairs that represent user attributes.

### Custom SMS sender response parameters
<a name="custom-sms-sender-response-parameters"></a>

Amazon Cognito doesn't expect any additional return information in the response. Your function can use API operations to query and modify your resources, or record event metadata to an external system.

## Code example
<a name="custom-sms-sender-code-examples"></a>

The following Node.js example processes an SMS message event in your custom SMS sender Lambda function. This example assumes your function has two environment variables defined.

**`KEY_ID`**  
The ID of the KMS key that you want to use to encrypt and decrypt your users' codes.

**`KEY_ARN`**  
The Amazon Resource Name (ARN) of the KMS key that you want to use to encrypt and decrypt your users' codes.

**To deploy this function**

1. Install the latest version of NodeJS in your developer workspace.

1. Create a new NodeJS project in your workspace.

1. Initialize your project with `npm init -y`.

1. Create the script for the Lambda function: `touch index.mjs`.

1. Paste the contents of the below example into `index.mjs`.

1. Download the project dependency, Amazon Encryption SDK: `npm install @aws-crypto/client-node`.

1. Zip the project directory into a file: `zip -r my_deployment_package.zip .`.

1. [Deploy the ZIP file to your function](https://docs.amazonaws.cn/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 SMS.
// This example logs message details to CloudWatch Logs from your Lambda function.
// Update this function with custom logic that sends an SMS message to 'phoneNumber' with body 'message'.
const sendSMS = async (phoneNumber, message) => {
    // Log the destination with the phone number masked.
    console.log(`Simulating SMS send to ${phoneNumber.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('SMS 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 == 'CustomSMSSender_SignUp') {
            const phoneNumber = event.request.userAttributes.phone_number;
            const message = `Welcome! Your verification code is: ${plainTextCode}`;
            await sendSMS(phoneNumber, message);
        }
        else if (event.triggerSource == 'CustomSMSSender_ResendCode') {
            // Handle resend code
        }
        else if (event.triggerSource == 'CustomSMSSender_ForgotPassword') {
            // Handle forgot password
        }
        else if (event.triggerSource == 'CustomSMSSender_UpdateUserAttribute') {
            // Handle update attribute
        }
        else if (event.triggerSource == 'CustomSMSSender_VerifyUserAttribute') {
            // Handle verify attribute
        }
        else if (event.triggerSource == 'CustomSMSSender_AdminCreateUser') {
            // Handle admin create user
        }
        return;
    } catch (error) {
        console.error('Error in custom SMS sender:', error);
        throw error;
    }
};
```

**Topics**
+ [

## Custom SMS sender Lambda trigger sources
](#trigger-source)
+ [

## Custom SMS sender Lambda trigger parameters
](#custom-sms-sender-parameters)
+ [

## Code example
](#custom-sms-sender-code-examples)
+ [

## Evaluate SMS message capabilities with a custom SMS sender function
](#sms-to-email-example)

## Evaluate SMS message capabilities with a custom SMS sender function
<a name="sms-to-email-example"></a>

A custom SMS sender Lambda function accepts the SMS messages that your user pool would send, and the function delivers the content based on your custom logic. Amazon Cognito sends the [Custom SMS sender Lambda trigger parameters](#custom-sms-sender-parameters) to your function. Your function can do what you want with this information. For example, you can send the code to an Amazon Simple Notification Service (Amazon SNS) topic. An Amazon SNS topic subscriber can be an SMS message, an HTTPS endpoint, or an email address.

To create a test environment for Amazon Cognito SMS messaging with a custom SMS sender Lambda function, see [amazon-cognito-user-pool-development-and-testing-with-sms-redirected-to-email](https://github.com/aws-samples/amazon-cognito-user-pool-development-and-testing-with-sms-redirected-to-email) in the [aws-samples library on GitHub](https://github.com/aws-samples). The repository contains Amazon CloudFormation templates that can create a new user pool, or work with a user pool that you already have. These templates create Lambda functions and an Amazon SNS topic. The Lambda function that the template assigns as a custom SMS sender trigger, redirects your SMS messages to the subscribers to the Amazon SNS topic. 

When you deploy this solution to a user pool, all messages that Amazon Cognito usually sends through SMS messaging, the Lambda function instead sends to a central email address. Use this solution to customize and preview SMS messages, and to test the user pool events that cause Amazon Cognito to send an SMS message. After you complete your tests, roll back the CloudFormation stack, or remove the custom SMS sender function assignment from your user pool.

**Important**  
Don't use the templates in [amazon-cognito-user-pool-development-and-testing-with-sms-redirected-to-email](https://github.com/aws-samples/amazon-cognito-user-pool-development-and-testing-with-sms-redirected-to-email) to build a production environment. The custom SMS sender Lambda function in the solution *simulates* SMS messages, but the Lambda function sends them all to a single central email address. Before you can send SMS messages in a production Amazon Cognito user pool, you must complete the requirements shown at [SMS message settings for Amazon Cognito user pools](user-pool-sms-settings.md).