Skip to content

Invitation email via ak_send_email, not NotificationTransport

Date: 2026-06-26 Status: Accepted Decision: hl-a1uh Deciders: sean

Authentik has two structurally separate outbound-email paths: a NotificationTransport (mode=email) delivers only to existing Authentik users via notification.user.email, while the ak_send_email() expression function accepts arbitrary recipient addresses. When an invitation is created, the invitee has no user account yet, and the invitation_created event’s user field is the admin who created the invitation — not the invitee.

Invitation email is sent via ak_send_email() inside an Authentik expression policy (tf/authentik/policies/send_invitation_email.py), not via a native email NotificationTransport. The native transport is structurally incapable of reaching a pre-registration address.

  • NotificationTransport selects recipients from notification.user.email — only existing registered users.
  • The invitation_created event’s user is the inviting admin, not the invitee; a native transport would email the wrong person.
  • ak_send_email(address=invitee_email, ...) accepts caller-supplied addresses and reuses the same global AUTHENTIK_EMAIL SMTP config.
  • This constraint is permanent for as long as invitations pre-date user-account creation.
  • ak_send_email() in an expression policy (chosen): accepts arbitrary addresses; reuses the global SMTP config; async via the Authentik task queue; failures observable in event/task logs instead of a silent pass.
  • Native NotificationTransport (mode=email) (rejected): clean IaC resource and consistent with the other notification rules, but can only deliver to existing users — it would email the inviting admin, not the invitee. Structurally impossible to reach a pre-registration address.
  • Positive: invitation email reaches pre-registration addresses; ak_send_email is async and does not block the policy thread during invitation creation; mail failures surface in Authentik task logs and ClickStack instead of being silently swallowed.
  • Negative: two outbound-email paths (NotificationTransport and ak_send_email) must be understood and maintained separately; the invitation_email_dummy (mode=local) transport cannot be removed because event rules require at least one transport, so it remains a permanent structural placeholder.
  • Neutral: ak_send_email returns True when the mail is queued, not when delivered; delivery confirmation is not available at call time.