Customize message templates for recovery and verification emails
Ory Identities (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:
- recovery- the system sends these messages when users recover their accounts. Used with the- linkrecovery strategy.- 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.
 
- recovery_code- the system sends these messages when users recover their accounts. Used with the- coderecovery strategy.- recovery_code.valid- the system sends these messages when the user provided a valid recovery address.
- recovery_code.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.
 
- 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.
- The Ory Network
- Self-Hosted Ory Kratos Config
To use custom templates in The Ory Network, encode the content of the template with Base64 and use the encoded string to update the Ory Identities config. Follow these steps:
- List all your projects and get the Ory Identities config file: - ## List all available projects
 ory list projects
 ## Get config
 ory get identity-config <project-id> --format yaml > identity-config.yaml
- Add your Base64-encoded custom message templates to the config: identity-config.yaml- courier:
 smtp:
 from_name: MyProject via Ory
 templates:
 recovery:
 invalid:
 email:
 body: {
 "html": "base64://ENCODED_HTML_TEMPLATE",
 "plaintext": "base64://ENCODED_PLAINTEXT_TEMPLATE"
 }
 valid:
 email:
 body: {}
 verification:
 invalid:
 email:
 body: {}
 valid:
 email:
 body: {}
- Upload the edited config: - ory update identity-config <project-id> --file updated_config.yaml
In The Ory Network, 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.
In self-hosted Ory Kratos instances, you can add custom templates from http://, file://, and base64:// URIs.
The plaintext and html fields are mandatory when defining the body key. All other keys are optional. If the system can't use
the custom templates, it falls back to the built-in templates or to the template_override_path (if specified).
courier:
  template_override_path: /conf/courier-template
  # ...
  templates:
    verification:
      valid:
        email:
          body:
            html: https://some-remote-resource/gotmpl
            plaintext: base64://SGV5IHlvdSBkZWNvZGVkIG1lIDop
          # optional
          subject: file://some-file/subject.gotmpl
When self-hosting Ory Kratos, the system expects the templates at these paths:
- <kratos-root>/<template-root>/recovery/valid
- <kratos-root>/<template-root>/recovery/invalid
- <kratos-root>/<template-root>/verification/valid
- <kratos-root>/<template-root>/verification/invalid
Read this document to learn more about the email courier and the specifics of using templates in self-hosted Ory Kratos instances.
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 The Ory Network:
- 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- Identityfor validating recovery.
- recovery.invalid-- Tofor invalidating recovery.
- verification.valid-- To,- VerificationURLand- Identityfor validating verification.
- verification.invalid-- Tofor invalidating verification.
Each template must have two versions: html and plaintext.
- htmlversion uses the HTML syntax to achieve the desired look and functionality (such as clickable buttons) of the email message.
- plaintextversion 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- htmlversion cannot be delivered, for example when the user's mail server blocks HTML in all incoming messages.
For example, for this template:
- The - htmlversion looks like this:courier/template/templates/verification/valid/email.body.gotmpl- Hi, please verify your account by clicking the following link:
 <a href="{{ .VerificationURL }}">{{ .VerificationURL }}</a>
- The - plaintextversion doesn't contain any HTML and keeps only the gotmpl logic (- {{ .VerificationURL }}) and plain text.courier/template/templates/verification/valid/email.body.plaintext.gotmpl- 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:
{
  // ...
  "properties": {
    "traits": {
      "type": "object",
      "properties": {
        // ...
        "lang": {
          "type": "string",
          "title": "Your preferred language"
      },
      "required": [
        "email"
      ],
      "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.
- The Ory Network
- Self-Hosted Ory Kratos Config
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.
{{define "en"}}
Hi,
Please recover access to your account by clicking the following link:
{{ .RecoveryURL }}
{{end}}
{{define "fr"}}
Bonjour,
Veuillez récupérer l'accès à votre compte en cliquant sur le lien suivant:
{{ .RecoveryURL }}
{{end}}
{{define "it"}}
Ciao,
Recuperare l'accesso al proprio account facendo clic sul seguente link:
{{ .RecoveryURL }}
{{end}}
{{- else if eq .Identity.traits.language "fr" -}}
{{ template "fr" . }}
{{- else if eq .Identity.traits.language "it" -}}
{{ template "it" . }}
{{- else -}}
{{ template "en" . }}
{{- end -}}
To create nested templates, you can use either in-line template definitions, or as in this example, use separate template files. 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.
{{- if eq .Identity.traits.language "de" -}}
{{ template "email.body.de.gotmpl" . }}
{{- else -}}
{{ template "email.body.en.gotmpl" . }}
{{- end -}}
<a href="{{ .RecoveryURL }}">{{.RecoveryURL }}</a>
Hallo {{ upper .Identity.traits.firstName }},
Um Ihr Konto wiederherzustellen, klicken Sie bitte auf den folgenden Link:
Hello {{ upper .Identity.traits.firstName }},
to recover your account, please click on the link below:
The i18n template is nested in the root email.body.gotmpl template. The sub-templates must conform to the email.body* pattern.
The identity of the user is available in all templates.
You can use Sprig functions in the nested templates. For security reasons, some functions are disabled in The Ory Network. Click here to see the list of disabled functions.