Ithibati.InvitationMail (Ithibati v0.6.2)

Copy Markdown View Source

Delivers existing invitation links through application-owned content and mailer functions.

This module does not create invitations or change registration policy. Call it after the invitation's transaction commits. It refuses delivery inside the configured repo's transaction. For email identifiers, pass the invitation's normalized email as the recipient. Applications using usernames supply a separate delivery address. Construct the URL from trusted endpoint configuration, never from an untrusted request host.

Configure :invitation_mail under :ithibati, or pass the complete options per call:

config :ithibati, :invitation_mail,
  enabled: true,
  content: &MyApp.InvitationEmail.content/2,
  deliver: &MyApp.InvitationEmail.deliver/2

The content function receives (url, context) and returns {:ok, %{subject: subject, text: text}}, optionally with html: html, or {:error, reason}. It may render application templates; Ithibati requires no template engine. The delivery function receives (recipient, content) and returns {:ok, receipt} or {:error, reason}. It owns the sender and adapts this map to the application's existing mailer.

See Invitations for a mailer example, registration integration and retry semantics.

Summary

Functions

Renders and sends an existing invitation URL to a single mailbox.

Returns whether invitation mail is explicitly enabled in the supplied or configured options.

Functions

deliver(recipient, url, opts \\ configured())

Renders and sends an existing invitation URL to a single mailbox.

Options replace configuration rather than merging with it:

  • :enabled — opt-in boolean; defaults to false.
  • :content — a function of arity two returning subject, text and optional HTML.
  • :deliver — a function of arity two calling the application's mailer.
  • :context — passed unchanged to the content function; defaults to %{}.

Disabled delivery returns {:ok, :disabled} without invoking either callback. Successful delivery returns {:ok, receipt}. Expected failures return {:error, reason} where reason is :invalid_configuration, :invalid_recipient, :invalid_url, :transaction_in_progress, {:content, reason} or {:delivery, reason}. A malformed callback result uses :invalid_result as its stage's reason. Callback exceptions propagate as programming errors.

Subject and text must be non-empty strings; HTML is optional. Recipients use the practical syntax of Ithibati.Schema.Identifier.email_format/0. URLs must be absolute HTTP(S) URLs without user information. Content functions must escape dynamic values when rendering HTML.

Delivery does not prove receipt or validate the invitation's state. Expiry and single-use acceptance remain enforced by Ithibati.Identity.Invitations. No token is stored or logged. A delivery error leaves the existing invitation intact. Retry with the same URL while the caller still holds it; after losing it, issue a replacement through the existing schema flow. A transport failure can be ambiguous, so retrying may deliver a duplicate email.

enabled?(opts \\ configured())

Returns whether invitation mail is explicitly enabled in the supplied or configured options.