Verificación de correo electrónico personalizado con Mailjet

Antes de comenzar, use el selector Elección de un tipo de directiva para elegir el tipo de directiva que va a configurar. Azure Active Directory B2C ofrece dos métodos para definir el modo en que los usuarios interactúan con las aplicaciones: por medio de flujos de usuario predefinidos o de directivas personalizadas totalmente configurables. Los pasos necesarios en este artículo son diferentes para cada método.

Use el correo electrónico personalizado en Azure Active Directory B2C (Azure AD B2C) para enviar mensajes personalizados a los usuarios que se registran para usar las aplicaciones. Mediante el proveedor de correo electrónico de terceros Mailjet, puede usar su propia plantilla de correo electrónico, dirección De: y asunto, además de admitir la localización y la configuración personalizada de la contraseña de un solo uso (OTP).

Esta característica está disponible solo para directivas personalizadas. En los pasos de configuración, elija Directiva personalizada en el selector anterior.

La verificación del correo electrónico personalizado requiere el uso de un proveedor de correo electrónico de terceros, como Mailjet, SendGrid o SparkPost, una API REST personalizada o cualquier proveedor de correo electrónico basado en HTTP (incluido el suyo propio). En este artículo se describe cómo configurar una solución que usa Mailjet.

Creación de una cuenta de Mailjet

Si aún no tiene una, empiece por configurar una cuenta de Mailjet (los clientes de Azure pueden desbloquear 6 000 mensajes de correo electrónico con un límite de 200 correos electrónicos al día).

  1. Siga las instrucciones de configuración para crear una cuenta de Mailjet.
  2. Para poder enviar correo electrónico, registre y valide la dirección de correo electrónico o el dominio del remitente.
  3. Desplácese hasta la página de administración de claves de API. Anote la clave de API y la clave secreta para usarlas en un paso posterior. Cuando se crea la cuenta, se generan las dos claves automáticamente.

Importante

Mailjet ofrece a los clientes la capacidad de enviar correos electrónicos desde direcciones IP compartidas y direcciones IP dedicadas. Al usar direcciones IP dedicadas, tiene que mejorar su propia reputación de manera adecuada con un calentamiento de la dirección IP. Para obtener más información, consulte ¿Cómo se realiza el calentamiento de la dirección IP?

Creación de la clave de directiva de Azure AD B2C

A continuación, almacene la clave de API de Mailjet en una clave de directiva de Azure AD B2C que servirá de referencia para las directivas.

  1. Inicie sesión en Azure Portal.
  2. Si tiene acceso a varios inquilinos, seleccione el icono Configuración en el menú superior para cambiar al inquilino de Azure AD B2C desde el menú Directorios y suscripciones.
  3. Elija Todos los servicios en la esquina superior izquierda de Azure Portal, y busque y seleccione Azure AD B2C.
  4. En la página de introducción, seleccione Identity Experience Framework.
  5. Seleccione Claves de directiva y, luego, Agregar.
  6. En Opciones, elija Manual.
  7. Escriba un nombre para la clave de directiva. Por ejemplo, MailjetApiKey. Se agregará el prefijo B2C_1A_ automáticamente al nombre de la clave.
  8. En Secreto, escriba la clave de la API de Mailjet que guardó previamente.
  9. En Uso de claves, seleccione Firma.
  10. Seleccione Crear.
  11. Seleccione Claves de directiva y luego Agregar.
  12. En Opciones, elija Manual.
  13. Escriba un nombre para la clave de directiva. Por ejemplo, MailjetSecretKey. Se agregará el prefijo B2C_1A_ automáticamente al nombre de la clave.
  14. En Secreto, escriba la clave secreta de Mailjet que guardó previamente.
  15. En Uso de claves, seleccione Firma.
  16. Seleccione Crear.

Creación de una plantilla de Mailjet

Con la cuenta de Mailjet creada y la clave de API de Mailjet almacenada en una clave de directiva de Azure AD B2C, cree una plantilla transaccional dinámica de Mailjet.

  1. En el sitio de Mailjet, abra la página Transactional Templates (Plantillas transaccionales) y seleccione Create Template (Crear plantilla nueva).

  2. Seleccione By coding it in HTML (Con codificación HTML) y después seleccione Code from scratch (Codificar desde cero).

  3. Escriba un nombre de plantilla único, como por ejemplo, Verification email, y después seleccione Create (Crear).

  4. En el editor de HTML, pegue la siguiente plantilla HTML o use la suya propia. Los parámetros {{var:otp:""}} y {{var:email:""}} se reemplazarán dinámicamente con el valor de la contraseña de un solo uso y la dirección de correo electrónico del usuario.

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en"><head id="Head1">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>Contoso demo account email verification code</title><meta name="ROBOTS" content="NOINDEX, NOFOLLOW">
       <!-- Template B O365 -->
       <style>
           table td {border-collapse:collapse;margin:0;padding:0;}
       </style>
    </head>
    <body dir="ltr" lang="en">
       <table width="100%" cellpadding="0" cellspacing="0" border="0" dir="ltr" lang="en">
            <tr>
               <td valign="top" width="50%"></td>
               <td valign="top">
                  <!-- Email Header -->
                  <table width="640" cellpadding="0" cellspacing="0" border="0" dir="ltr" lang="en" style="border-left:1px solid #e3e3e3;border-right: 1px solid #e3e3e3;">
                   <tr style="background-color: #0072C6;">
                       <td width="1" style="background:#0072C6; border-top:1px solid #e3e3e3;"></td>
                       <td width="24" style="border-top:1px solid #e3e3e3;border-bottom:1px solid #e3e3e3;">&nbsp;</td>
                       <td width="310" valign="middle" style="border-top:1px solid #e3e3e3; border-bottom:1px solid #e3e3e3;padding:12px 0;">
                           <h1 style="line-height:20pt;font-family:Segoe UI Light; font-size:18pt; color:#ffffff; font-weight:normal;">
                            <span id="HeaderPlaceholder_UserVerificationEmailHeader"><font color="#FFFFFF">Verify your email address</font></span>
                           </h1>
                       </td>
                       <td width="24" style="border-top: 1px solid #e3e3e3;border-bottom: 1px solid #e3e3e3;">&nbsp;</td>
                   </tr>
                  </table>
                  <!-- Email Content -->
                  <table width="640" cellpadding="0" cellspacing="0" border="0" dir="ltr" lang="en">
                   <tr>
                       <td width="1" style="background:#e3e3e3;"></td>
                       <td width="24">&nbsp;</td>
                       <td id="PageBody" width="640" valign="top" colspan="2" style="border-bottom:1px solid #e3e3e3;padding:10px 0 20px;border-bottom-style:hidden;">
                           <table cellpadding="0" cellspacing="0" border="0">
                               <tr>
                                   <td width="630" style="font-size:10pt; line-height:13pt; color:#000;">
                                       <table cellpadding="0" cellspacing="0" border="0" width="100%" style="" dir="ltr" lang="en">
                                           <tr>
                                               <td>
    
       <div style="font-family:'Segoe UI', Tahoma, sans-serif; font-size:14px; color:#333;">
           <span id="BodyPlaceholder_UserVerificationEmailBodySentence1">Thanks for verifying your {{var:email:""}} account!</span>
       </div>
       <br>
       <div style="font-family:'Segoe UI', Tahoma, sans-serif; font-size:14px; color:#333; font-weight: bold">
           <span id="BodyPlaceholder_UserVerificationEmailBodySentence2">Your code is: {{var:otp:""}}</span>
       </div>
       <br>
       <br>
    
                                                   <div style="font-family:'Segoe UI', Tahoma, sans-serif; font-size:14px; color:#333;">
                                                   Sincerely,
                                                   </div>
                                                   <div style="font-family:'Segoe UI', Tahoma, sans-serif; font-size:14px; font-style:italic; color:#333;">
                                                       Contoso
                                                   </div>
                                               </td>
                                           </tr>
                                       </table>
                                   </td>
                               </tr>
                           </table>
    
                       </td>
    
                       <td width="1">&nbsp;</td>
                       <td width="1"></td>
                       <td width="1">&nbsp;</td>
                       <td width="1" valign="top"></td>
                       <td width="29">&nbsp;</td>
                       <td width="1" style="background:#e3e3e3;"></td>
                   </tr>
                   <tr>
                       <td width="1" style="background:#e3e3e3; border-bottom:1px solid #e3e3e3;"></td>
                       <td width="24" style="border-bottom:1px solid #e3e3e3;">&nbsp;</td>
                       <td id="PageFooterContainer" width="585" valign="top" colspan="6" style="border-bottom:1px solid #e3e3e3;padding:0px;">
    
                       </td>
    
                       <td width="29" style="border-bottom:1px solid #e3e3e3;">&nbsp;</td>
                       <td width="1" style="background:#e3e3e3; border-bottom:1px solid #e3e3e3;"></td>
                   </tr>
                  </table>
    
               </td>
               <td valign="top" width="50%"></td>
           </tr>
       </table>
    </body>
    </html>
    
  5. Expanda Edit subject (Editar asunto) en la parte superior izquierda.

    1. En Subject (Asunto), escriba un valor predeterminado para el asunto. Mailjet usa este valor cuando la API no contiene un parámetro de asunto.
    2. En Name (Nombre), escriba el nombre de la empresa.
    3. En Address (Dirección), seleccione su dirección de correo electrónico.
    4. Seleccione Guardar.
  6. En la parte superior derecha, seleccione Save & Publish (Guardar y publicar) y después Yes, publish changes (Sí, publicar cambios).

  7. Anote el valor de Template ID (Identificador de la plantilla) de la plantilla que creó para usarlo en un paso posterior. Este identificador se especifica al agregar la transformación de notificaciones.

Importante

En los pasos siguientes se muestra cómo compilar los archivos XML de directiva personalizados. Se recomienda usar una directiva personalizada de verificación de correo electrónico personalizado de ejemplo disponible en GitHub. DisplayControl_TrustFrameworkExtensions.xml usa TrustFrameworkExtensions.xml como su archivo base, por lo tanto, asegúrese de incluir los archivos TrustFrameworkBase.xml, TrustFrameworkLocalization.xml y TrustFrameworkExtensions.xml del paquete de inicioSocialAndLocalAccounts en la directiva.

Incorporación de tipos de notificaciones de Azure AD B2C

En la directiva, agregue los siguientes tipos de notificaciones al elemento <ClaimsSchema> dentro de <BuildingBlocks>.

Estos tipos de notificaciones son necesarios para generar y verificar la dirección de correo electrónico mediante un código de contraseña de un solo uso (OTP).

<!--
<BuildingBlocks>
  <ClaimsSchema> -->
    <ClaimType Id="Otp">
      <DisplayName>Secondary One-time password</DisplayName>
      <DataType>string</DataType>
    </ClaimType>
    <ClaimType Id="emailRequestBody">
      <DisplayName>Mailjet request body</DisplayName>
      <DataType>string</DataType>
    </ClaimType>
    <ClaimType Id="VerificationCode">
      <DisplayName>Secondary Verification Code</DisplayName>
      <DataType>string</DataType>
      <UserHelpText>Enter your email verification code</UserHelpText>
      <UserInputType>TextBox</UserInputType>
    </ClaimType>
  <!-- 
  </ClaimsSchema>
</BuildingBlocks> -->

Incorporación de la transformación de notificaciones

A continuación, necesita una transformación de notificaciones para generar una notificación de cadena JSON que será el cuerpo de la solicitud enviada a Mailjet.

La estructura del objeto JSON se define mediante los identificadores de la notación de puntos de InputParameters y TransformationClaimTypes del objeto InputClaims. Los números de la notación de puntos implican matrices. Los valores provienen de los valores de InputClaims y de las propiedades "value" de InputParameters. Para más información sobre las transformaciones de notificaciones de JSON, consulte Transformaciones de notificaciones de JSON.

Agregue la siguiente transformación de notificaciones al elemento <ClaimsTransformations> dentro de <BuildingBlocks>. Realice las siguientes actualizaciones en el XML de la transformación de notificaciones:

  • Actualice el valor Messages.0.TemplateID de InputParameter con el identificador de la plantilla transaccional de Mailjet que creó anteriormente en Creación de la plantilla de Mailjet.
  • Actualice el valor de dirección de Messages.0.From.Email. Use una dirección de correo electrónico válida para evitar que el correo electrónico de verificación se marque como correo no deseado.
  • Actualice el valor del parámetro de entrada de la línea de asunto Messages.0.Subject con una línea de asunto adecuada para su organización.
<!-- 
<BuildingBlocks>
  <ClaimsTransformations> -->
    <ClaimsTransformation Id="GenerateEmailRequestBody" TransformationMethod="GenerateJson">
      <InputClaims>
        <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="Messages.0.To.0.Email" />
        <InputClaim ClaimTypeReferenceId="otp" TransformationClaimType="Messages.0.Variables.otp" />
        <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="Messages.0.Variables.email" />
      </InputClaims>
      <InputParameters>
        <!-- Update the template_id value with the ID of your Mailjet template. -->
        <InputParameter Id="Messages.0.TemplateID" DataType="int" Value="1234567"/>
        <InputParameter Id="Messages.0.TemplateLanguage" DataType="boolean" Value="true"/>

        <!-- Update with an email appropriate for your organization. -->
        <InputParameter Id="Messages.0.From.Email" DataType="string" Value="my_email@mydomain.com"/>

        <!-- Update with a subject line appropriate for your organization. -->
        <InputParameter Id="Messages.0.Subject" DataType="string" Value="Contoso account email verification code"/>
      </InputParameters>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="emailRequestBody" TransformationClaimType="outputClaim"/>
      </OutputClaims>
    </ClaimsTransformation>
  <!--
  </ClaimsTransformations>
</BuildingBlocks> -->

Incorporación de definición de contenido de DataUri

Bajo las transformaciones de notificaciones dentro de <BuildingBlocks>, agregue el siguiente elemento ContentDefinition para hacer referencia al URI de datos de la versión 2.1.2:

<!--
<BuildingBlocks> -->
  <ContentDefinitions>
   <ContentDefinition Id="api.localaccountsignup">
      <DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:2.1.2</DataUri>
    </ContentDefinition>
    <ContentDefinition Id="api.localaccountpasswordreset">
      <DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:2.1.2</DataUri>
    </ContentDefinition>
  </ContentDefinitions>
<!--
</BuildingBlocks> -->

Creación de un elemento DisplayControl

Para verificar la dirección de correo electrónico con un código de verificación que se envía al usuario, se utiliza un control de visualización de verificación.

Este control de visualización de ejemplo está configurado para:

  1. Recopilar el tipo de notificación de dirección email del usuario.

  2. Con la acción SendCode, generar un código OTP y enviar un correo electrónico con este código al usuario.

    Send verification code email action

  3. Esperar a que el usuario proporcione el tipo de notificación verificationCode con el código que se le envía.

  4. Devolver el valor de email al perfil técnico autoafirmado que tiene una referencia a este control de visualización.

En las definiciones de contenido, todavía dentro de <BuildingBlocks>, agregue el siguiente elemento DisplayControl de tipo VerificationControl a la directiva.

<!--
<BuildingBlocks> -->
  <DisplayControls>
    <DisplayControl Id="emailVerificationControl" UserInterfaceControlType="VerificationControl">
      <DisplayClaims>
        <DisplayClaim ClaimTypeReferenceId="email" Required="true" />
        <DisplayClaim ClaimTypeReferenceId="verificationCode" ControlClaimType="VerificationCode" Required="true" />
      </DisplayClaims>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="email" />
      </OutputClaims>
      <Actions>
        <Action Id="SendCode">
          <ValidationClaimsExchange>
            <ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="GenerateOtp" />
            <ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="SendOtp" />
          </ValidationClaimsExchange>
        </Action>
        <Action Id="VerifyCode">
          <ValidationClaimsExchange>
            <ValidationClaimsExchangeTechnicalProfile TechnicalProfileReferenceId="VerifyOtp" />
          </ValidationClaimsExchange>
        </Action>
      </Actions>
    </DisplayControl>
  </DisplayControls>
<!--
</BuildingBlocks> -->

Incorporación de perfiles técnicos de OTP

El perfil técnico GenerateOtp genera un código para la dirección de correo electrónico. El perfil técnico VerifyOtp verifica el código asociado a la dirección de correo electrónico. Puede cambiar la configuración del formato y la expiración de la contraseña de un solo uso. Para más información sobre los perfiles técnicos de OTP, consulte Definición de un perfil técnico de una contraseña de un solo uso en una directiva personalizada de Azure AD B2C.

Nota:

Los códigos OTP generados por el protocolo Web.TPEngine.Providers.OneTimePasswordProtocolProvider están vinculados a la sesión del explorador. Esto significa que un usuario puede generar códigos OTP únicos en distintas sesiones del explorador que son válidos para sus sesiones correspondientes. Por el contrario, un código OTP que genere el proveedor de correo electrónico integrado es independiente de la sesión del explorador, por lo que si un usuario genera un nuevo código OTP en una nueva sesión del explorador, este reemplaza el código OTP anterior.

Agregue los siguientes perfiles técnicos al elemento <ClaimsProviders>.

<!--
<ClaimsProviders> -->
  <ClaimsProvider>
    <DisplayName>One time password technical profiles</DisplayName>
    <TechnicalProfiles>
      <TechnicalProfile Id="GenerateOtp">
        <DisplayName>Generate one time password</DisplayName>
        <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.OneTimePasswordProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
        <Metadata>
          <Item Key="Operation">GenerateCode</Item>
          <Item Key="CodeExpirationInSeconds">600</Item>
          <Item Key="CodeLength">6</Item>
          <Item Key="CharacterSet">0-9</Item>
          <Item Key="NumRetryAttempts">5</Item>
          <Item Key="NumCodeGenerationAttempts">10</Item>
          <Item Key="ReuseSameCode">false</Item>
        </Metadata>
        <InputClaims>
          <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="identifier" />
        </InputClaims>
        <OutputClaims>
          <OutputClaim ClaimTypeReferenceId="otp" PartnerClaimType="otpGenerated" />
        </OutputClaims>
      </TechnicalProfile>

      <TechnicalProfile Id="VerifyOtp">
        <DisplayName>Verify one time password</DisplayName>
        <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.OneTimePasswordProtocolProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
        <Metadata>
          <Item Key="Operation">VerifyCode</Item>
        </Metadata>
        <InputClaims>
          <InputClaim ClaimTypeReferenceId="email" PartnerClaimType="identifier" />
          <InputClaim ClaimTypeReferenceId="verificationCode" PartnerClaimType="otpToVerify" />
        </InputClaims>
      </TechnicalProfile>
     </TechnicalProfiles>
  </ClaimsProvider>
<!--
</ClaimsProviders> -->

Incorporación de un perfil técnico de API REST

Este perfil técnico de API REST genera el contenido del correo electrónico (con el formato de Mailjet). Para más información sobre los perfiles técnicos de RESTful, consulte Definición de un perfil técnico de RESTful en una directiva personalizada en Azure Active Directory B2C.

Al igual que hizo con los perfiles técnicos de OTP, agregue los siguientes perfiles técnicos al elemento <ClaimsProviders>.

<ClaimsProvider>
  <DisplayName>RestfulProvider</DisplayName>
  <TechnicalProfiles>
    <TechnicalProfile Id="sendOtp">
      <DisplayName>Use email API to send the code to the user</DisplayName>
      <Protocol Name="Proprietary" Handler="Web.TPEngine.Providers.RestfulProvider, Web.TPEngine, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
      <Metadata>
        <Item Key="ServiceUrl">https://api.mailjet.com/v3.1/send</Item>
        <Item Key="AuthenticationType">Basic</Item>
        <Item Key="SendClaimsIn">Body</Item>
        <Item Key="ClaimUsedForRequestPayload">emailRequestBody</Item>
      </Metadata>
      <CryptographicKeys>
        <Key Id="BasicAuthenticationUsername" StorageReferenceId="B2C_1A_MailjetApiKey" />
        <Key Id="BasicAuthenticationPassword" StorageReferenceId="B2C_1A_MailjetSecretKey" />
      </CryptographicKeys>
      <InputClaimsTransformations>
        <InputClaimsTransformation ReferenceId="GenerateEmailRequestBody" />
      </InputClaimsTransformations>
      <InputClaims>
        <InputClaim ClaimTypeReferenceId="emailRequestBody" />
      </InputClaims>
    </TechnicalProfile>
  </TechnicalProfiles>
</ClaimsProvider>

Referencia al elemento DisplayControl

En el paso final, agregue una referencia al elemento DisplayControl que creó. Invalide los perfiles técnicos existentes y autoafirmados LocalAccountSignUpWithLogonEmail y LocalAccountDiscoveryUsingEmailAddress configurados en la directiva base con el siguiente fragmento de código XML. Si usó una versión anterior de la directiva de Azure AD B2C, estos perfiles técnicos usan DisplayClaims con una referencia a DisplayControl.

Para más información, consulte Definición de un perfil técnico de RESTful en una directiva personalizada en Azure Active Directory B2C y Controles de visualización.

<ClaimsProvider>
  <DisplayName>Local Account</DisplayName>
  <TechnicalProfiles>
    <TechnicalProfile Id="LocalAccountSignUpWithLogonEmail">
      <DisplayClaims>
        <DisplayClaim DisplayControlReferenceId="emailVerificationControl" />
        <DisplayClaim ClaimTypeReferenceId="displayName" Required="true" />
        <DisplayClaim ClaimTypeReferenceId="givenName" Required="true" />
        <DisplayClaim ClaimTypeReferenceId="surName" Required="true" />
        <DisplayClaim ClaimTypeReferenceId="newPassword" Required="true" />
        <DisplayClaim ClaimTypeReferenceId="reenterPassword" Required="true" />
      </DisplayClaims>
    </TechnicalProfile>
    <TechnicalProfile Id="LocalAccountDiscoveryUsingEmailAddress">
      <DisplayClaims>
        <DisplayClaim DisplayControlReferenceId="emailVerificationControl" />
      </DisplayClaims>
    </TechnicalProfile>
  </TechnicalProfiles>
</ClaimsProvider>

(Opcional) Localización del correo electrónico

Para localizar el correo electrónico, debe enviar las cadenas localizadas a Mailjet o al proveedor de correo electrónico. Por ejemplo, puede localizar el asunto del correo electrónico, el cuerpo, el mensaje de código o la firma del correo electrónico. Para ello, puede usar la transformación de notificaciones GetLocalizedStringsTransformation para copiar cadenas localizadas en tipos de notificación. La transformación de notificaciones GenerateEmailRequestBody, que genera la carga JSON, utiliza notificaciones de entrada que contienen las cadenas localizadas.

  1. En la directiva, defina las siguientes notificaciones de cadena: subject, message, codeIntro y signature.

  2. Defina una transformación de notificaciones GetLocalizedStringsTransformation que sustituya los valores de cadena localizados por las notificaciones del paso 1.

  3. Cambie la transformación de notificaciones GenerateEmailRequestBody para que use notificaciones de entrada con el siguiente fragmento de código XML.

  4. Actualice la plantilla de Mailjet para que use los parámetros dinámicos en lugar de todas las cadenas que se localizarán mediante Azure AD B2C.

    <ClaimsTransformation Id="GetLocalizedStringsForEmail" TransformationMethod="GetLocalizedStringsTransformation">
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="subject" TransformationClaimType="email_subject" />
        <OutputClaim ClaimTypeReferenceId="message" TransformationClaimType="email_message" />
        <OutputClaim ClaimTypeReferenceId="codeIntro" TransformationClaimType="email_code" />
        <OutputClaim ClaimTypeReferenceId="signature" TransformationClaimType="email_signature" />
      </OutputClaims>
    </ClaimsTransformation>
    <ClaimsTransformation Id="GenerateEmailRequestBody" TransformationMethod="GenerateJson">
      <InputClaims>
        <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="Messages.0.To.0.Email" />
        <InputClaim ClaimTypeReferenceId="subject" TransformationClaimType="Messages.0.Subject" />
        <InputClaim ClaimTypeReferenceId="otp" TransformationClaimType="Messages.0.Variables.otp" />
        <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="Messages.0.Variables.email" />
        <InputClaim ClaimTypeReferenceId="message" TransformationClaimType="Messages.0.Variables.otpmessage" />
        <InputClaim ClaimTypeReferenceId="codeIntro" TransformationClaimType="Messages.0.Variables.otpcodeIntro" />
        <InputClaim ClaimTypeReferenceId="signature" TransformationClaimType="Messages.0.Variables.otpsignature" />
      </InputClaims>
      <InputParameters>
        <!-- Update the template_id value with the ID of your Mailjet template. -->
        <InputParameter Id="Messages.0.TemplateID" DataType="int" Value="1234567"/>
        <InputParameter Id="Messages.0.TemplateLanguage" DataType="boolean" Value="true"/>
    
        <!-- Update with an email appropriate for your organization. -->
        <InputParameter Id="Messages.0.From.Email" DataType="string" Value="my_email@mydomain.com"/>
      </InputParameters>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="emailRequestBody" TransformationClaimType="outputClaim"/>
      </OutputClaims>
    </ClaimsTransformation>
    
  5. Agregue el siguiente elemento Localization.

    <!--
    <BuildingBlocks> -->
      <Localization Enabled="true">
        <SupportedLanguages DefaultLanguage="en" MergeBehavior="ReplaceAll">
          <SupportedLanguage>en</SupportedLanguage>
          <SupportedLanguage>es</SupportedLanguage>
        </SupportedLanguages>
        <LocalizedResources Id="api.custom-email.en">
          <LocalizedStrings>
            <LocalizedString ElementType="GetLocalizedStringsTransformationClaimType" StringId="email_subject">Contoso account email verification code</LocalizedString>
            <LocalizedString ElementType="GetLocalizedStringsTransformationClaimType" StringId="email_message">Thanks for validating the account</LocalizedString>
            <LocalizedString ElementType="GetLocalizedStringsTransformationClaimType" StringId="email_code">Your code is</LocalizedString>
            <LocalizedString ElementType="GetLocalizedStringsTransformationClaimType" StringId="email_signature">Sincerely</LocalizedString>
          </LocalizedStrings>
        </LocalizedResources>
        <LocalizedResources Id="api.custom-email.es">
          <LocalizedStrings>
            <LocalizedString ElementType="GetLocalizedStringsTransformationClaimType" StringId="email_subject">Código de verificación del correo electrónico de la cuenta de Contoso</LocalizedString>
            <LocalizedString ElementType="GetLocalizedStringsTransformationClaimType" StringId="email_message">Gracias por comprobar la cuenta de </LocalizedString>
            <LocalizedString ElementType="GetLocalizedStringsTransformationClaimType" StringId="email_code">Su código es</LocalizedString>
            <LocalizedString ElementType="GetLocalizedStringsTransformationClaimType" StringId="email_signature">Sinceramente</LocalizedString>
          </LocalizedStrings>
        </LocalizedResources>
      </Localization>
    <!--
    </BuildingBlocks> -->
    
  6. Agregue referencias a los elementos LocalizedResources actualizando el elemento ContentDefinitions.

    <!--
    <BuildingBlocks> -->
      <ContentDefinitions>
        <ContentDefinition Id="api.localaccountsignup">
          <DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:2.1.2</DataUri>
          <LocalizedResourcesReferences MergeBehavior="Prepend">
            <LocalizedResourcesReference Language="en" LocalizedResourcesReferenceId="api.custom-email.en" />
            <LocalizedResourcesReference Language="es" LocalizedResourcesReferenceId="api.custom-email.es" />
          </LocalizedResourcesReferences>
        </ContentDefinition>
        <ContentDefinition Id="api.localaccountpasswordreset">
          <DataUri>urn:com:microsoft:aad:b2c:elements:contract:selfasserted:2.1.2</DataUri>
          <LocalizedResourcesReferences MergeBehavior="Prepend">
            <LocalizedResourcesReference Language="en" LocalizedResourcesReferenceId="api.custom-email.en" />
            <LocalizedResourcesReference Language="es" LocalizedResourcesReferenceId="api.custom-email.es" />
          </LocalizedResourcesReferences>
        </ContentDefinition>
      </ContentDefinitions>
    <!--
    </BuildingBlocks> -->
    
  7. Por último, agregue la siguiente transformación de las notificaciones de entrada a los perfiles técnicos LocalAccountSignUpWithLogonEmail y LocalAccountDiscoveryUsingEmailAddress.

    <InputClaimsTransformations>
      <InputClaimsTransformation ReferenceId="GetLocalizedStringsForEmail" />
    </InputClaimsTransformations>
    

[Opcional] Localización de la interfaz de usuario

El elemento Localization permite incluir varios idiomas o configuraciones regionales en la directiva para los recorridos del usuario. La compatibilidad con localización en directivas permite especificar cadenas específicas del idioma para los elementos de la interfaz de usuario del control de pantalla de comprobación y los mensajes de error de contraseña de un solo uso. Agregue el siguiente elemento LocalizedString a LocalizedResources.

<LocalizedResources Id="api.custom-email.en">
  <LocalizedStrings>
    ...
    <!-- Display control UI elements-->
    <LocalizedString ElementType="DisplayControl" ElementId="emailVerificationControl" StringId="intro_msg">Verification is necessary. Please click Send button.</LocalizedString>
    <LocalizedString ElementType="DisplayControl" ElementId="emailVerificationControl" StringId="success_send_code_msg">Verification code has been sent to your inbox. Please copy it to the input box below.</LocalizedString>
    <LocalizedString ElementType="DisplayControl" ElementId="emailVerificationControl" StringId="failure_send_code_msg">We are having trouble verifying your email address. Please enter a valid email address and try again.</LocalizedString>
    <LocalizedString ElementType="DisplayControl" ElementId="emailVerificationControl" StringId="success_verify_code_msg">E-mail address verified. You can now continue.</LocalizedString>
    <LocalizedString ElementType="DisplayControl" ElementId="emailVerificationControl" StringId="failure_verify_code_msg">We are having trouble verifying your email address. Please try again.</LocalizedString>
    <LocalizedString ElementType="DisplayControl" ElementId="emailVerificationControl" StringId="but_send_code">Send verification code</LocalizedString>
    <LocalizedString ElementType="DisplayControl" ElementId="emailVerificationControl" StringId="but_verify_code">Verify code</LocalizedString>
    <LocalizedString ElementType="DisplayControl" ElementId="emailVerificationControl" StringId="but_send_new_code">Send new code</LocalizedString>
    <LocalizedString ElementType="DisplayControl" ElementId="emailVerificationControl" StringId="but_change_claims">Change e-mail</LocalizedString>
    <!-- Claims-->
    <LocalizedString ElementType="ClaimType" ElementId="emailVerificationCode" StringId="DisplayName">Verification Code</LocalizedString>
    <LocalizedString ElementType="ClaimType" ElementId="emailVerificationCode" StringId="UserHelpText">Verification code received in the email.</LocalizedString>
    <LocalizedString ElementType="ClaimType" ElementId="emailVerificationCode" StringId="AdminHelpText">Verification code received in the email.</LocalizedString>
    <LocalizedString ElementType="ClaimType" ElementId="email" StringId="DisplayName">Email</LocalizedString>
    <!-- Email validation error messages-->
    <LocalizedString ElementType="ErrorMessage" StringId="UserMessageIfSessionDoesNotExist">You have exceeded the maximum time allowed.</LocalizedString>
    <LocalizedString ElementType="ErrorMessage" StringId="UserMessageIfMaxRetryAttempted">You have exceeded the number of retries allowed.</LocalizedString>
    <LocalizedString ElementType="ErrorMessage" StringId="UserMessageIfMaxNumberOfCodeGenerated">You have exceeded the number of code generation attempts allowed.</LocalizedString>
    <LocalizedString ElementType="ErrorMessage" StringId="UserMessageIfInvalidCode">You have entered the wrong code.</LocalizedString>
    <LocalizedString ElementType="ErrorMessage" StringId="UserMessageIfSessionConflict">Cannot verify the code, please try again later.</LocalizedString>
    <LocalizedString ElementType="ErrorMessage" StringId="UserMessageIfVerificationFailedRetryAllowed">The verification has failed, please try again.</LocalizedString>
  </LocalizedStrings>
</LocalizedResources>

Pasos siguientes