Skip to main content

Email stage

The Email stage sends a verification or action email from within a flow.

About the email stage​

This stage is used for email verification, account recovery, invitations, and similar flow steps where authentik should send a tokenized link or message to a user.

The email is normally sent to the current pending_user, but the target address can be overridden from flow context.

When an email cannot be delivered immediately, authentik retries delivery through its background worker.

Configuration options​

  • Use global connection settings: use authentik's global email configuration instead of stage-specific SMTP settings.
  • SMTP Host: SMTP server hostname for stage-specific delivery.
  • SMTP Port: SMTP server port.
  • SMTP Username: optional SMTP username.
  • SMTP Password: optional SMTP password.
  • Use TLS: enable STARTTLS for the SMTP connection.
  • Use SSL: enable SMTPS for the SMTP connection.
  • Timeout: SMTP connection timeout in seconds.
  • From address: sender address used for flow emails.
  • Account Recovery Max Attempts: maximum number of recovery emails allowed in the configured time window.
  • Account Recovery Cache Timeout: time window used for recovery-email rate limiting.
  • Activate user on success: activate the user after the stage succeeds.
  • Token expiry: how long the email token remains valid.
  • Subject: subject line used for the email.
  • Template: template used to render the email body.

Flow integration​

Use this stage in recovery, enrollment, verification, or invitation flows where an email should be sent before the flow continues.

By default, the message goes to the current pending_user. To override the destination, set email in the flow plan context before the stage runs:

request.context["flow_plan"].context["email"] = "foo@bar.baz"
return True

You can also source the address from prompt data or another user attribute:

request.context["flow_plan"].context["email"] = request.context["prompt_data"]["email"]
return True
request.context["flow_plan"].context["email"] = request.context["pending_user"].attributes.get("otherEmail")
return True

Notes​

Rate limiting​

The recovery rate-limiting fields only affect recovery-style email sends. They limit how many recent attempts a user can trigger within the configured time window.

Custom templates​

You can provide custom email templates.

info

You can also add a matching .txt file next to the .html file to send multipart text and HTML emails.

Place custom templates in the custom-templates directory next to your Compose file. The template becomes selectable in the Email stage configuration.

If a custom template does not appear in the selector, check the worker logs.

Template variables​

Templates are rendered with Django's templating engine. Common variables include:

  • url: the full URL the user should open
  • user: the pending user
  • expires: when the token expires

These templates are rendered with Django's templating engine, so you can also use standard template inheritance and translation tags.

Example template​

Templates can extend the base email template and use standard Django template tags. For example:

info

Each Django {% ... %} tag must stay on one line; a tag wrapped across lines won't parse.

{# This comment is not rendered in the final email. #}
{% extends "email/base.html" %}
{% load i18n %}
{% load humanize %}

{% block content %}
<tr>
<td class="alert alert-success">
{% blocktrans with username=user.username %} Hi {{ username }},{% endblocktrans %}
</td>
</tr>
<tr>
<td class="content-wrap">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
{% blocktrans %}You recently requested to change your password for your authentik account. Use the button below to set a new password.{% endblocktrans %}
</td>
</tr>
<tr>
<td class="content-block">
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<tr>
<td align="center">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>
<a id="confirm" href="{{ url }}" rel="noopener noreferrer" target="_blank">{% trans 'Reset Password' %}</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td class="content-block">
{% blocktrans with expires=expires|timeuntil %}If you did not request a password change, please ignore this email. The link above is valid for {{ expires }}.{% endblocktrans %}
</td>
</tr>
</table>
</td>
</tr>
{% endblock %}