Add realm-name in email themes

Hello.
In email templates I would like to add the URL to User Account Service for this realm. I can not find a way to do this. URL is <server-root>/auth/realms/{realm-name}/account but how can I get realm-name in email template?

Hi,

you can use ${realmName} in existing emails.
If you have custom emails you can add values to the attributes map and use those in your emails.
An example for the default emails https://github.com/keycloak/keycloak/blob/master/services/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailTemplateProvider.java
https://github.com/keycloak/keycloak/blob/master/services/src/main/java/org/keycloak/authentication/requiredactions/ConsoleVerifyEmail.java

I don’t think there is a list or good documentation about this, but when in doubt clone the repository and browse the code.

Thank you for the response @zonaut.
${realmName} can not be used in URLs, it is the display name of the realm. What am looking for seems to be realm.getName() but how can I access that object in a email template?

/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailTemplateProvider.java:

protected String getRealmName() {
    if (realm.getDisplayName() != null) {
        return realm.getDisplayName();
    } else {
        return ObjectUtil.capitalize(realm.getName());
    }
}
...
attributes.put("realmName", getRealmName());

Can I define somehow own attributes that can be available for Freemarker templates? The template system is currently lacking because am limited to what is defined as attributes.put() in keycloak source code.

yes, it seems that only in the test email the normal realm name is used.
I’ve done a little search as this same subject will be of interest to me also in the future.
As far as I can see there is no possibility at all to add extra attributes, which is surprising.

A possible solution is to create a CustomFreeMarkerEmailTemplateProvider based on the code you can find under the package org.keycloak.email.freemarker.

You can basically just copy/paste that whole package into your own provider and give an id of ‘custom-freemarker’, you can add all the attributes you want in your custom provider. I would suggest to extend the FreeMarkerEmailTemplateProvider class with your own and use that in the factory. You can add the attributes from that class. This way on new releases you could just copy paste over the old code without doing much of refactoring.

Then disable the ‘freemarker’ provider which is the default for the emailTemplate SPI.
When deploying your custom provider it should be registered under the emailTemplate SPI, you can check this in your server info on Keycloak.

As I said, not tested but it should be feasible.

To disable the current one you can put the following in your standalone-ha.xml file

<spi name="emailTemplate">
    <provider name="freemarker" enabled="false"/>
</spi>

I ended up choosing to use Freemarker template system built-in regular expression against the link attribute that is available. link contains the beginning of the URL that I need.

export customThemePath=/opt/keycloak/themes/mytheme
mkdir -p $customThemePath/email/{html,messages,text}

Add $customThemePath/email/html/executeActions.ftl so it looks like this:

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

<#assign regex1 = link?matches("(http.*)/login-actions")>
<#list regex1 as m>
  <#assign realmUserAccountUrl = "${m?groups[1]}/account/">
</#list>

<html>
<body>
${kcSanitize(msg("executeActionsBodyHtml",link, linkExpiration, realmBaseUrl, requiredActionsText, linkExpirationFormatter(linkExpiration), realmUserAccountUrl))?no_esc}
</body>
</html>

Copy needed translations

cp $customThemePath/../base/email/messages/messages_en.properties $customThemePath/email/messages/

Edit your translations and add {5} where needed.