4

I am using Keycloak's Admin REST API to send a verification email to the user. Specifically, using the endpoint :

admin/realms/{realmName}/users/{userId}/execute-actions-email?redirect_uri={redirectURI}&client_id={clientId}

The email is sent successfully, but the email template selected by keycloak is "Update Your Account" template instead of "Verify email" template.

Is there a way I can get Keycloak to use the right template?

UPDATE : Tried with the send-verify-email endpoint too.. same problem exists.

Peeka
  • 135
  • 1
  • 3
  • 9

2 Answers2

16

I extended Barnys answer and ended up with this template. Don't know why they do not call it a "bug" but a limitation https://issues.redhat.com/browse/KEYCLOAK-5034

for HTML

<#outputformat "plainText">
<#assign requiredActionsText><#if requiredActions??><#list requiredActions><#items as reqActionItem>${msg("requiredAction.${reqActionItem}")}<#sep>, </#sep></#items></#list></#if></#assign>
<#assign requiredActionsValues><#if requiredActions??><#list requiredActions><#items as reqActionItem>${reqActionItem}<#sep>, </#sep></#items></#list></#if></#assign>
</#outputformat>


<html>
<body>
<#if requiredActionsValues == "VERIFY_EMAIL">
${kcSanitize(msg("emailVerificationBodyHtml",link, linkExpiration, realmName, linkExpirationFormatter(linkExpiration)))?no_esc}
<#elseif requiredActionsValues == "UPDATE_PASSWORD">
${kcSanitize(msg("passwordResetBodyHtml",link, linkExpiration, realmName, linkExpirationFormatter(linkExpiration)))?no_esc}
<#else>
${kcSanitize(msg("executeActionsBodyHtml",link, linkExpiration, realmName, requiredActionsText, linkExpirationFormatter(linkExpiration)))?no_esc}
</#if>
</body>
</html>

for plain text

<#ftl output_format="plainText">
<#assign requiredActionsText><#if requiredActions??><#list requiredActions><#items as reqActionItem>${msg("requiredAction.${reqActionItem}")}<#sep>, </#sep></#items></#list><#else></#if></#assign>
<#assign requiredActionsValues><#if requiredActions??><#list requiredActions><#items as reqActionItem>${reqActionItem}<#sep>, </#sep></#items></#list></#if></#assign>


<#if requiredActionsValues == "VERIFY_EMAIL">
${msg("emailVerificationBody",link, linkExpiration, realmName, linkExpirationFormatter(linkExpiration))}
<#elseif requiredActionsValues == "UPDATE_PASSWORD">
${msg("passwordResetBody",link, linkExpiration, realmName, linkExpirationFormatter(linkExpiration))}
<#else>
${msg("executeActionsBody",link, linkExpiration, realmName, requiredActionsText, linkExpirationFormatter(linkExpiration))}
</#if>

don't forgot to put the template changes in all instances of the cluster and restart each cluster instance

sudo systemctl restart keycloak.service
msek
  • 181
  • 1
  • 5
2

I am working with Version 3.4.0. If you use the execute-actions endpoint, you cannot choose the template directly. But you can use freemarker to select different content. Here is an example of a <MY-THEME>/email/html/executeActions.ftl

<#outputformat "plainText">    
<#assign requiredActionsValues><#if requiredActions??><#list requiredActions><#items as reqActionItem>${reqActionItem}}<#sep>, </#sep></#items></#list></#if></#assign>
</#outputformat>

<!DOCTYPE html>
<html>
<body>
Actions: '${requiredActionsValues}'<br>
Email: ${user.email}<br>
Username: ${user.username}<br>
</body>
</html>

Use the variable requiredActionsValues to select your content based on the actions.

Barny
  • 1,685
  • 1
  • 17
  • 25
  • You can take a look at https://github.com/keycloak/keycloak/blob/master/services/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailTemplateProvider.java and https://github.com/keycloak/keycloak/blob/master/services/src/main/java/org/keycloak/email/freemarker/beans/ProfileBean.java. Here is the code keycloak uses to fill the email template with variables. – Barny Mar 26 '18 at 15:59
  • What does the `<#assign requiredActionsValues><#if requiredActions??><#list requiredActions><#items as reqActionItem>${reqActionItem}}<#sep>, #sep>#items>#list>#if>#assign>` refer to? – Kévin Sanchez Lacroix Jul 07 '21 at 20:46