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:
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.
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.
- Ory Cloud
- Self-Hosted Ory Kratos Config
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:
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.yamlAdd your Base64-encoded custom message templates to the config:
identity-config.yamlcourier:
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 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.
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).
smtp:
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 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, andIdentityfor validating recovery.recovery.invalid-Tofor invalidating recovery.verification.valid-To,VerificationURLandIdentityfor 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 thehtmlversion 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.gotmplHi, 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.gotmplHi, 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.
- Ory Cloud
- 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 Ory Cloud. Click here to see the list of disabled functions.