Customizing Cognito verification emails with HTML using AWS Lambda

This has become very common to use AWS Cognito as an authentication system in modern days. Using Cognito, when a user signs up or gets an invitation from another user, he gets an email with password and verification codes. But the email is in simple plain text. But we can easily configure a lambda function that can customize and beautify this email according to our needs.

To configure the lambda, first, we have to understand the states when we can actually trigger a lambda from Cognito. These states are (source):

  1. CustomMessage_SignUp : Custom message — To send the confirmation code post-sign-up.
  2. CustomMessage_AdminCreateUser : Custom message — To send the temporary password to a new user.
  3. CustomMessage_ResendCode : Custom message — To resend the confirmation code to an existing user.
  4. CustomMessage_ForgotPassword : Custom message — To send the confirmation code for Forgot Password request.
  5. CustomMessage_UpdateUserAttribute : Custom message — When a user’s email or phone number is changed, this trigger sends a verification code automatically to the user. Cannot be used for other attributes.
  6. CustomMessage_VerifyUserAttribute : Custom message — This trigger sends a verification code to the user when they manually request it for a new email or phone number.
  7. CustomMessage_Authentication : Custom message — To send MFA code during authentication.

For convenience, we will only focus on the first two and hope that you can easily configure for the others. Now let’s configure the lambda.

Go to the Lambda console and click create a function and give it a name and node version then create it. Now for the code part, follow the below:

'use strict';
exports.handler = async (event, context, callback) => {
  const email = event.request.userAttributes.email;
  const link = `https://example.com?userName=${email}&confirmation_code=${event.request.codeParameter}`;
  const name = event.request.userAttributes.name;
     const template = (name,link) => `<html>
    <body style="background-color:#333; font-family: PT Sans,Trebuchet MS,sans-serif; ">
      <div style="margin: 0 auto; width: 600px; background-color: #fff; font-size: 1.2rem; font-style: normal;font-weight: normal;line-height: 19px;" align="center">
        <div style="padding: 20;">
            <p style="Margin-top: 20px;Margin-bottom: 0;">&nbsp;</p>
            <p style="Margin-top: 20px;Margin-bottom: 0;">&nbsp;</p>
            <img style="border: 0;display: block;height: auto; width: 100%;max-width: 373px;" alt="Animage" height="200" width="300"  src="https://publish.example.com/main-logo.png" />
            <p style="Margin-top: 20px;Margin-bottom: 0;">&nbsp;</p>
            <h2
                style="font-size: 28px; margin-top: 20px; margin-bottom: 0;font-style: normal; font-weight: bold; color: #000;font-size: 24px;line-height: 32px;text-align: center;">Hi ${name}</h2>
            <p style="Margin-top: 20px;Margin-bottom: 0;">&nbsp;</p>
            <p style="Margin-top: 20px;Margin-bottom: 0;font-size: 16px;line-height: 24px; color: #000">Your registration request was successfully approved. Click below to complete the registration</p>
            <p style="Margin-top: 20px;Margin-bottom: 0;">&nbsp;</p>
                <div style="Margin-left: 20px;Margin-right: 20px;Margin-top: 24px;">
                    <div style="Margin-bottom: 20px;text-align: center;">
                        <a
                            style="border-radius: 4px;display: block;font-size: 14px;font-weight: bold;line-height: 24px;padding: 12px 24px 13px 24px;text-align: center;text-decoration: none !important;transition: opacity 0.1s ease-in;color: #ffffff !important;box-shadow: inset 0 -2px 0 0 rgba(0, 0, 0, 0.2);background-color: #3b5998;font-family: PT Sans, Trebuchet MS, sans-serif; letter-spacing: 0.05rem;"
                            href="${link}">CLICK HERE TO VERIFY YOUR EMAIL</a>
                        </div>
                </div>
        </div>
      </div>
    </body>
  </html>`;
  
  const templateInvite = (name,email,code)=> `<html>
  <body
    style="
      background-color: #333;
      font-family: PT Sans, Trebuchet MS, sans-serif;
    "
  >
    <div
      style="
        margin: 0 auto;
        width: 600px;
        background-color: #fff;
        font-size: 1.2rem;
        font-style: normal;
        font-weight: normal;
        line-height: 19px;
      "
      align="center"
    >
      <div style="padding: 20">
        <img
          style="
            border: 0;
            display: block;
            height: auto;
            width: 100%;
            max-width: 373px;
          "
          alt="Animage"
          height="200"
          width="300"
          src="https://publish.example.com/main-logo.png"
        />
        <h2
          style="
            font-size: 28px;
            margin-top: 20px;
            margin-bottom: 0;
            font-style: normal;
            font-weight: bold;
            color: #000;
            font-size: 24px;
            line-height: 32px;
            text-align: center;
          "
        >
          Hi ${name}
        </h2>
        <p
          style="
            margin-top: 20px;
            margin-bottom: 0;
            font-size: 16px;
            line-height: 24px;
            color: #000;
          "
        >
          Here is your temporary login details
        </p>
        <div style="display: inline-block; margin: 0 auto">
          <h2
            style="
              margin-top: 20px;
              margin-bottom: 0;
              font-size: 16px;
              line-height: 24px;
              color: #000;
              text-align: left;
            "
          >
            user_name: ${email}
          </h2>
          <h2
            style="
              margin-top: 20px;
              margin-bottom: 0;
              font-size: 16px;
              line-height: 24px;
              color: #000;
              text-align: left;
            "
          >
            temporary_password: ${code}
          </h2>
        </div>
      </div>
    </div>
  </body>
</html>
`;
  if (event.triggerSource === "CustomMessage_SignUp") {
    event.response = {
        emailSubject: "Publish | Confirm your email",
        emailMessage: template(name, link)
    };
  }else if(event.triggerSource==='CustomMessage_AdminCreateUser'){
      event.response = {
        emailSubject: "Publish | Your temporary account details",
        emailMessage: templateInvite(name,event.request.usernameParameter,event.request.codeParameter)
    };
  }
  console.log(event.response);
  callback(null, event);
};

Let’s go through the code. The event in the lambda will contain all the things we need for an email. event.triggerSource will contain the states described above. So based on this trigger source, we will construct different email template. You can see in the code that two functions template and templateInvite actually return some HTML code as a string. One thing to remember that you should use inline CSS in the HTML, otherwise there may be some problems. Another thing to notice that, for the CustomMessage_AdminCreateUser state, always use the email addresses from the event.request.usernameParameter, otherwise Cognito will throw a silent error and you will not be able to debug what is actually happened. And always include only the body tag of the HTML. You can see in the code I have done that.

Now, let’s configure the Cognito to call this lambda whenever a new user is registered. Go to your Cognito user pool console, and click on the Trigger from the menu tab. Now select the lambda function in the Custom message menu just like below:

Selecting the lambda in the Cognito trigger

Now you will see whenever a new user registers or gets a new invitation, he will get your customize mail. You can actually customize the message for the SMS also in the event.response.smsMessage parameter.

Custom email for confirm signup
Custom email for the invitation
Picture of Abul Hasnat

Abul Hasnat

Software Development Engineer

Hire Exceptional Developers Quickly

Share this blog on

Hire Your Software Development Team

Let us help you pull out your hassle recruiting potential software engineers and get the ultimate result exceeding your needs.

Contact Us Directly

Address:

Plot # 272, Lane # 3 (Eastern Road) DOHS Baridhara, Dhaka 1206

Talk to Us
Scroll to Top