Настройка проверки электронной почты с помощью SendGrid

Для начала с помощью селектора Choose a policy type (Выбрать тип политики) выберите тип пользовательской политики. Azure Active Directory B2C предлагает два метода определения способа взаимодействия пользователей с вашими приложениями: с помощью предопределенных потоков пользователей или полностью настраиваемых пользовательских политик. Действия, которые необходимо выполнить, отличаются для каждого метода.

Используйте функцию настройки сообщений электронной почты в Azure Active Directory B2C, чтобы отправлять электронные письма пользователям, зарегистрированным в вашем приложении. Пользуясь услугами стороннего поставщика сервиса электронной почты SendGrid, можно использовать свой собственный шаблон "Отправитель: адрес и тема", а также обеспечить поддержку локализации и настроить одноразовый пароль (OTP).

Эта возможность доступна только для пользовательских политик. Чтобы ознакомиться с этапами установки, в предыдущем селекторе выберите Настраиваемая политика.

Для настройки проверки электронной почты требуется использование стороннего поставщика услуг электронной почты, например SendGrid, Mailjet или SparkPost, настраиваемого REST API или любого поставщика услуг электронной почты на основе HTTP (включая свой собственный). В этой статье описывается настройка решения с использованием SendGrid.

Создание учетной записи SendGrid

Если у вас еще нет учетной записи SendGrid, начните с настройки учетной записи SendGrid. Инструкции по настройке см. в разделе Создание учетной записи SendGrid статьи Отправка электронной почты с использованием SendGrid в Azure.

Убедитесь, что вы завершите работу с разделом, в котором создается ключ API SendGrid. Запишите ключ API для использования в следующем шаге.

Важно!

SendGrid предоставляет клиентам возможность отправки электронной почты с общего IP-адреса и выделенных IP-адресов. При использовании выделенных IP-адресов необходимо правильно создать собственную репутацию путем соответствующей подготовки IP-адреса. Дополнительные сведения см. в статье Подготовка IP-адреса.

Создание ключа политики Azure Active Directory B2C

Затем сохраните ключ SendGrid API в ключе политики Azure AD B2C, чтобы политики ссылались на него.

  1. Войдите на портал Azure.
  2. Если у вас есть доступ к нескольким клиентам, выберите значок Параметры в верхнем меню, чтобы переключиться на клиент Azure AD B2C из меню каталогов и подписок.
  3. В левом верхнем углу портал Azure выберите "Все службы", а затем найдите и выберите Azure AD B2C.
  4. На странице "Обзор" выберите Identity Experience Framework.
  5. Выберите Ключи политики, а затем щелкните Добавить.
  6. Для пункта Параметры выберите Вручную.
  7. Введите имя ключа политики. Например, SendGridSecret. Префикс B2C_1A_ будет автоматически добавлен к имени ключа.
  8. В поле Секрет введите сохраненный ранее ключ SendGrid API.
  9. Чтобы использовать параметр Ключ, выберите Подпись.
  10. Нажмите кнопку создания.

Создание шаблона SendGrid

Создав учетную запись SendGrid и сохранив ключ SendGrid API в ключе политики Azure AD B2C, создайте динамический шаблон транзакций SendGrid.

  1. На веб-сайте SendGrid откройте страницу шаблонов транзакций и нажмите Создать динамический шаблон.

  2. Введите уникальное имя шаблона, например Verification email, и нажмите кнопку Создать.

  3. Чтобы начать редактирование нового шаблона, выберите шаблон, Verification emailкоторый есть, а затем нажмите кнопку "Добавить версию".

  4. Выберите Пустой шаблон, а затем — Редактор кода.

  5. В редакторе HTML вставьте следующий шаблон HTML или используйте свой. {{email}} Параметры {{otp}} заменяются динамически значением одноразового пароля и адресом электронной почты пользователя.

    <!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">
       <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 {{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: {{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>
    
  6. Разверните меню Параметры и введите версию шаблона.

  7. В поле Тема введите {{subject}}.

  8. Выберите Сохранить.

  9. Вернитесь на страницу Шаблоны транзакций, нажав стрелку назад.

  10. Запишите Идентификатор шаблона, созданного для использования в последующих шагах. Например, d-989077fbba9746e89f3f6411f596fb96. Этот идентификатор указывается при добавлении преобразования утверждений.

Важно!

В следующих шагах показано, как создавать XML-файлы настраиваемой политики. Мы рекомендуем использовать пример настраиваемой политики проверки электронной почты, доступный на GitHub. DisplayControl_TrustFrameworkExtensions.xml использует TrustFrameworkExtensions.xml в качестве базового файла, поэтому не забудьте включить в свою политику файлы TrustFrameworkBase.xml, TrustFrameworkLocalization.xml и TrustFrameworkExtensions.xml из SocialAndLocalAccountsначальный пакет.

Добавление типов утверждений Azure Active Directory B2C

В политике добавьте следующие типы утверждений в элемент <ClaimsSchema> внутри <BuildingBlocks>.

Эти типы утверждений требуются для создания и проверки адреса электронной почты с использованием кода одноразового пароля (OTP).

<!-- 
<BuildingBlocks>
  <ClaimsSchema> -->
    <ClaimType Id="Otp">
      <DisplayName>Secondary One-time password</DisplayName>
      <DataType>string</DataType>
    </ClaimType>
    <ClaimType Id="emailRequestBody">
      <DisplayName>SendGrid 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> -->

Добавление преобразований утверждений

Затем необходимо преобразовать утверждения, чтобы вывести строковое утверждение JSON, которое формирует текст запроса, отправленного в SendGrid.

Структура объекта JSON определяется идентификаторами в точечной нотации InputParameters и TransformationClaimTypes в InputClaims. Числа в точечной нотации представляют массивы. Значения берутся из значений InputClaims и свойств "Value" для InputParameters. Дополнительные сведения о преобразовании утверждений JSON см. в статье Преобразования утверждений JSON.

Добавьте следующее преобразование утверждений в элемент <ClaimsTransformations> внутри <BuildingBlocks>. Внесите следующие изменения в XML-код преобразования утверждений.

  • Обновите значение template_id для InputParameter, указав идентификатор шаблона транзакции SendGrid, который был создан ранее при изучении статьи Создание шаблона SendGrid.
  • Обновите значение адреса from.email. Используйте действительный адрес электронной почты, чтобы сообщение электронной почты не было отмечено как спам.

    Примечание.

    Этот адрес электронной почты должен быть подтвержден в SendGrid в разделе проверки подлинности отправителя путем проверки подлинности домена или одного отправителя.

  • Обновите значение входного параметра строки темы personalizations.0.dynamic_template_data.subject, указав строку темы, подходящую для вашей организации.
<!-- 
<BuildingBlocks>
  <ClaimsTransformations> -->
    <ClaimsTransformation Id="GenerateEmailRequestBody" TransformationMethod="GenerateJson">
      <InputClaims>
        <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="personalizations.0.to.0.email" />
        <InputClaim ClaimTypeReferenceId="otp" TransformationClaimType="personalizations.0.dynamic_template_data.otp" />
        <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="personalizations.0.dynamic_template_data.email" />
      </InputClaims>
      <InputParameters>
        <!-- Update the template_id value with the ID of your SendGrid template. -->
        <InputParameter Id="template_id" DataType="string" Value="d-989077fbba9746e89f3f6411f596fb96"/>
        <InputParameter Id="from.email" DataType="string" Value="my_email@mydomain.com"/>
        <!-- Update with a subject line appropriate for your organization. -->
        <InputParameter Id="personalizations.0.dynamic_template_data.subject" DataType="string" Value="Contoso account email verification code"/>
      </InputParameters>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="emailRequestBody" TransformationClaimType="outputClaim"/>
      </OutputClaims>
    </ClaimsTransformation>
  <!--
  </ClaimsTransformations>
</BuildingBlocks> -->

Добавление определения содержимого DataUri

Ниже преобразований утверждений внутри <BuildingBlocks> добавьте следующее ContentDefinition для ссылки на URI данных версии 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> -->

Создание DisplayControl

Элемент управления отображением проверки используется для проверки адреса электронной почты с кодом проверки, получаемым пользователем.

Этот пример элемента управления отображением настроен следующим образом.

  1. Получите от пользователя тип утверждения адреса email.

  2. Создание кода OTP с помощью действия SendCode и отправка пользователю сообщения электронной почты с кодом OTP.

    Send verification code email action

  3. Ожидание, пока пользователь укажет тип утверждения verificationCode с кодом, отправленным пользователю.

  4. Верните email обратно в самоутвержденный технический профиль со ссылкой на этот элемент управления отображением.

В разделе определений содержимого внутри <BuildingBlocks> добавьте в свою политику DisplayControl типа VerificationControl.

<!--
<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> -->

Добавление технических профилей с OTP

Технический профиль GenerateOtp создает код для адреса электронной почты. Технический профиль VerifyOtp проверяет код, связанный с адресом электронной почты. Можно изменить конфигурацию формата и срок действия одноразового пароля. Дополнительные сведения о технических профилях OTP см. в статье Определение технического профиля с одноразовым паролем.

Примечание.

Коды OTP, которые создаются с применением протокола Web.TPEngine.Providers.OneTimePasswordProtocolProvider, привязаны к сеансу браузера. Это означает, что пользователь может создавать уникальные коды OTP в разных сеансах браузера, каждый из которых действителен для соответствующих сеансов. Напротив, код OTP, созданный встроенным поставщиком услуг электронной почты, не зависит от сеанса браузера. Поэтому, если пользователь создает новый код OTP в новом сеансе браузера, он заменяет предыдущий код OTP.

Добавьте следующие технические профили в элемент <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> -->

Добавление технического профиля REST API

В этом техническом профиле REST API создается содержимое сообщения электронной почты (с применением формата SendGrid). Дополнительные сведения о технических профилях RESTful см. в статье Определение технического профиля RESTful.

Как и в случае с техническими профилями с OTP, добавьте следующие технические профили в элемент <ClaimsProviders>.

<ClaimsProvider>
  <DisplayName>RestfulProvider</DisplayName>
  <TechnicalProfiles>
    <TechnicalProfile Id="SendOtp">
      <DisplayName>Use SendGrid's 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.sendgrid.com/v3/mail/send</Item>
        <Item Key="AuthenticationType">Bearer</Item>
        <Item Key="SendClaimsIn">Body</Item>
        <Item Key="ClaimUsedForRequestPayload">emailRequestBody</Item>
      </Metadata>
      <CryptographicKeys>
        <Key Id="BearerAuthenticationToken" StorageReferenceId="B2C_1A_SendGridSecret" />
      </CryptographicKeys>
      <InputClaimsTransformations>
        <InputClaimsTransformation ReferenceId="GenerateEmailRequestBody" />
      </InputClaimsTransformations>
      <InputClaims>
        <InputClaim ClaimTypeReferenceId="emailRequestBody" />
      </InputClaims>
    </TechnicalProfile>
  </TechnicalProfiles>
</ClaimsProvider>

Создание ссылки на DisplayControl

На последнем шаге добавьте ссылку на созданный ранее DisplayControl. Переопределите существующие самостоятельно утвержденные технические профили LocalAccountSignUpWithLogonEmail и LocalAccountDiscoveryUsingEmailAddress, которые настроены в базовой политике, с помощью приведенного ниже фрагмента XML-кода. Если вы использовали более раннюю версию политики Azure AD B2C, эти технические профили используют DisplayClaims со ссылкой на DisplayControl.

Дополнительные сведения см. в статье Самоутвержденный технический профиль и DisplayControl.

<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>

[Необязательно] Локализация сообщений электронной почты

Чтобы локализовать сообщение электронной почты, необходимо отправить локализованные строки в SendGrid или поставщику услуг электронной почты. Например, можно локализовать тему сообщения электронной почты, текст, сообщение с кодом или подпись сообщения. Для этого можно использовать преобразование утверждений GetLocalizedStringsTransformation для копирования локализованных строк в типы утверждений. Преобразование утверждений GenerateEmailRequestBody, создающее полезные данные JSON, использует входные утверждения, содержащие локализованные строки.

  1. В политике определите следующие строковые утверждения: subject, message, codeIntro и signature.

  2. Определите преобразование утверждений GetLocalizedStringsTransformation, чтобы заменить локализованные строковые значения на утверждения из шага 1.

  3. Измените преобразование утверждений GenerateEmailRequestBody, чтобы использовать входные утверждения, как в следующем фрагменте кода XML.

  4. Обновите шаблон SendGrid, чтобы использовать динамические параметры вместо всех строк, локализованных 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="personalizations.0.to.0.email" />
        <InputClaim ClaimTypeReferenceId="subject" TransformationClaimType="personalizations.0.dynamic_template_data.subject" />
        <InputClaim ClaimTypeReferenceId="otp" TransformationClaimType="personalizations.0.dynamic_template_data.otp" />
        <InputClaim ClaimTypeReferenceId="email" TransformationClaimType="personalizations.0.dynamic_template_data.email" />
        <InputClaim ClaimTypeReferenceId="message" TransformationClaimType="personalizations.0.dynamic_template_data.message" />
        <InputClaim ClaimTypeReferenceId="codeIntro" TransformationClaimType="personalizations.0.dynamic_template_data.codeIntro" />
        <InputClaim ClaimTypeReferenceId="signature" TransformationClaimType="personalizations.0.dynamic_template_data.signature" />
      </InputClaims>
      <InputParameters>
        <InputParameter Id="template_id" DataType="string" Value="d-1234567890" />
        <InputParameter Id="from.email" DataType="string" Value="my_email@mydomain.com" />
      </InputParameters>
      <OutputClaims>
        <OutputClaim ClaimTypeReferenceId="emailRequestBody" TransformationClaimType="outputClaim" />
      </OutputClaims>
    </ClaimsTransformation>
    
  5. Добавьте следующий элемент локализации.

    <!--
    <BuildingBlocks> -->
      <Localization Enabled="true">
        <SupportedLanguages DefaultLanguage="en" MergeBehavior="ReplaceAll">
          <SupportedLanguage>en</SupportedLanguage>
          <SupportedLanguage>es</SupportedLanguage>
        </SupportedLanguages>
        <LocalizedResources Id="api.custom-email.en">
          <LocalizedStrings>
            <!--Email template parameters-->
            <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>
            <!--Email template parameters-->
            <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. Добавьте ссылки на элементы LocalizedResources, обновив элемент 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. Наконец, добавьте следующее преобразование входных утверждений в технические профили LocalAccountSignUpWithLogonEmail и LocalAccountDiscoveryUsingEmailAddress.

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

[Необязательно] Локализация пользовательского интерфейса

Элемент Localization обеспечивает поддержку несколько языковых стандартов или языков в политике для путей взаимодействия пользователя. Поддержка локализации в политиках позволяет предоставлять зависимые от языка строки для элементов пользовательского интерфейса настройки проверки почты и сообщений об ошибках одноразового пароля. Добавьте следующую строку LocalizedString в 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>

Следующие шаги