Skip to main content

Customize message templates for recovery and verification emails

Ory Identity Service (Ory Kratos) comes with built-in templates for all messages sent by the system. You can replace the default templates with custom ones that will carry your own branding, visual elements, and communication tone.

The system uses templates in these flows:

  1. recovery - the system sends these messages when users recover their accounts, for example after forgetting their password.
    • recovery.valid - the system sends these messages when the user completes the recovery flow successfully.
    • recovery.invalid - the system sends these messages when the recovery flow fails, for example when you start the recovery flow using an email address that isn't associated with a registered user account.
  2. verification - the system sends these messages when users verify their accounts after signing up.
    • verification.valid - the system sends these messages when the user verifies their account successfully.
    • verification.invalid - the system sends these messages when the account verification fails, for example when you start the verification flow using an email address that isn't associated with a registered user account.

Use custom message templates

You can use custom templates in place of built-in ones. If you don't specify a custom template, the system automatically uses the built-in one.

To use custom templates in Ory Cloud, encode the content of the template with Base64 and use the encoded string to update the Identity Service config. Follow these steps:

  1. List all your projects and get the Identity Service config file:

    ## List all available projects
    ory list projects

    ## Get config
    ory get identity-config <project-id> --format yaml > identity-config.yaml
  2. Add your Base64-encoded custom message templates to the config:

    from_name: MyProject via Ory
    body: {
    "html": "base64://ENCODED_HTML_TEMPLATE",
    "plaintext": "base64://ENCODED_PLAINTEXT_TEMPLATE"
    body: {}
    body: {}
    body: {}
  3. Upload the edited config:

    ory update identity-config <project-id> --file updated_config.yaml

In Ory Cloud, you can use only Base64-encoded templates. The system doesn't accept http:// or file:// URIs. If you provide custom templates using unsupported methods, the system uses the default templates.

Creating templates

Templates use the golang template engine in the text/template package for rendering the email.subject.gotmpl and email.body.plaintext.gotmpl templates, and the html/template package for rendering the email.body.gotmpl template.

Learn more:


Templates can use the Sprig library, which provides more than 100 commonly used template functions


For security reasons, these Spring functions are disabled in Ory Cloud:

  • Date functions: date,date_in_zone,date_modify, now, htmlDate, htmlDateInZone, dateInZone, dateModify
  • Strings: randAlphaNum, randAlpha, randAscii, randNumeric, uuidv4
  • OS: env, expandenv
  • Network: getHostByName

Use these variables in templates:

  • recovery.valid - To,RecoveryURL, and Identity for validating recovery.
  • recovery.invalid - To for invalidating recovery.
  • verification.valid - To, VerificationURL and Identity for validating verification.
  • verification.invalid - To for invalidating verification.

Each template must have two versions: html and plaintext.

  • html version uses the HTML syntax to achieve the desired look and functionality (such as clickable buttons) of the email message.
  • plaintext version can't contain any HTML. Must contain only plain text content and any necessary gotmpl logic. This version is used as a fallback when the html version cannot be delivered, for example when the user's mail server blocks HTML in all incoming messages.

For example, for this template:

  • The html version looks like this:

    Hi, please verify your account by clicking the following link:

    <a href="{{ .VerificationURL }}">{{ .VerificationURL }}</a>
  • The plaintext version doesn't contain any HTML and keeps only the gotmpl logic ({{ .VerificationURL }}) and plain text.

    Hi, please verify your account by clicking the following link: {{ .VerificationURL }}

Customizing template content for specific users

To enable customizing the content of templates based on the identity of the recipient of the email, the Ory identity is available as the Identity object. This object is a map containing all the attributes of an identity defined in the identity schema, such as id, state, recovery_addresses, verifiable_addresses and traits.


Read this document to learn more about the Ory identity and the Identity Schema.

Nested templates: i18n customization

You can use nested templates to render email.subject.gotmpl, email.body.gotmpl and email.body.plaintext.gotmpl templates.

To enable i18n customization of templates, customize the identity schema to include the user's preferred communication language. For example:

Sample custom Identity Schema with user language
// ...
"properties": {
"traits": {
"type": "object",
"properties": {
// ...
"lang": {
"type": "string",
"title": "Your preferred language"
"required": [
"additionalProperties": false,

As an administrator, you can also set identity metadata, such as the language or the locale automatically using the identity metadata property. Read this document to learn more.

You can then use this trait to decide what template variant to show.

You can use in-line template definitions in nested templates. The following example defines the message body for verification emails. It assumes that there is a lang attribute defined in the identity traits that contains the preferred language of the user. The verification email content changes to show the appropriate language version if the system detects fr or it in the identity traits. If the system detects any other language, it uses the eng template.

Example nested template that serves different content based on an identity trait
{{define "en"}}

Please recover access to your account by clicking the following link:

{{ .RecoveryURL }}

{{define "fr"}}

Veuillez récupérer l'accès à votre compte en cliquant sur le lien suivant:

{{ .RecoveryURL }}

{{define "it"}}

Recuperare l'accesso al proprio account facendo clic sul seguente link:

{{ .RecoveryURL }}

{{- else if eq .Identity.traits.language "fr" -}}
{{ template "fr" . }}
{{- else if eq .Identity.traits.language "it" -}}
{{ template "it" . }}
{{- else -}}
{{ template "en" . }}
{{- end -}}

You can use Sprig functions in the nested templates. For security reasons, some functions are disabled in Ory Cloud. Click here to see the list of disabled functions.