MishkaCmsCore.Mail.Provider behaviour (Mishka CMS Core v0.0.1)

Copy Markdown View Source

An email provider: one module that is a mishka_installer plugin on the "mail:providers" event and implements the callbacks below. MishkaCmsCore.Mail never names a provider; a site picks one on the settings page (mailer.provider) and every email of that site goes through it.

defmodule MyExtension.Mail.Postmark do
  use MishkaCmsCore.Mail.Provider, id: "postmark", label: "Postmark"

  @impl true
  def settings do
    [secret("mailer.postmark.server_token", gettext_noop("Postmark server token"))]
  end

  @impl true
  def ready?(site_id), do: not is_nil(Settings.secret("mailer.postmark.server_token", site_id))

  @impl true
  def deliver(email, site_id, _opts) do
    token = Settings.secret("mailer.postmark.server_token", site_id)
    MishkaCmsCore.Mailer.deliver(email, adapter: Swoosh.Adapters.Postmark, api_key: token)
  end
end

Supervise the module in the extension's application, like any other plugin. use adds the plugin half — the "mail:providers" registration, see MishkaCmsCore.ProviderRegistry — plus secret/3, which builds a provider setting the way the core's are built.

Settings

settings/0 declares the provider's own fields, shown on the settings page's Email tab under its label. Each scope sets its own (resolve: :own): a site never sends with the installation's key. A key is a :secret setting; read it with MishkaCmsCore.Settings.secret/2, never get/3.

Delivering

deliver/3 sends one Swoosh.Email for site_id and returns {:ok, message_id} (nil when the provider gives none) or {:error, reason}. opts carries :idempotency_key and :purpose. retry?/1 says whether a failure may succeed on a later attempt (a rate limit, a timeout) or will fail the same way again (a bad key, an unverified domain).

The registered providers

all/0, offered/0 and fetch/1 ask the "mail:providers" event which providers are installed: the core's own — Resend and, in development, the DevMailbox — register the same way an extension's would, so stopping a provider's plugin in the installer takes it off the settings page and out of delivery. Nothing is cached: the event is asked when the settings page loads and when an email is sent.

Summary

Callbacks

Sends email for site_id.

The provider's id, stored in mailer.provider.

The name on the settings page, as a gettext_noop/1 msgid.

Whether the provider is offered on this installation. Every provider is, unless it says not.

Whether site_id has everything this provider needs to send.

Whether a failure deliver/3 returned is worth another attempt.

The provider's own setting definitions (MishkaCmsCore.Settings.define/3).

Functions

Every registered provider module, the first of each id.

The event a provider plugin listens on.

The offered provider registered under id.

The providers this installation offers on the settings page.

A provider's secret field: a :secret setting on the Email tab, under the provider's label, that each scope sets for itself. opts are MishkaCmsCore.Settings.define/3's.

Types

site_id()

@type site_id() :: String.t() | nil

Callbacks

deliver(t, site_id, keyword)

@callback deliver(Swoosh.Email.t(), site_id(), keyword()) ::
  {:ok, String.t() | nil} | {:error, term()}

Sends email for site_id.

id()

@callback id() :: String.t()

The provider's id, stored in mailer.provider.

label()

@callback label() :: String.t()

The name on the settings page, as a gettext_noop/1 msgid.

offered?()

(optional)
@callback offered?() :: boolean()

Whether the provider is offered on this installation. Every provider is, unless it says not.

ready?(site_id)

@callback ready?(site_id()) :: boolean()

Whether site_id has everything this provider needs to send.

retry?(term)

@callback retry?(term()) :: boolean()

Whether a failure deliver/3 returned is worth another attempt.

settings()

@callback settings() :: [MishkaCmsCore.Settings.definition()]

The provider's own setting definitions (MishkaCmsCore.Settings.define/3).

Functions

all()

@spec all() :: [module()]

Every registered provider module, the first of each id.

event()

@spec event() :: String.t()

The event a provider plugin listens on.

fetch(id)

@spec fetch(String.t() | nil) ::
  {:ok, module()} | {:error, :unknown_provider | :cannot_run}

The offered provider registered under id.

offered()

@spec offered() :: [module()]

The providers this installation offers on the settings page.

secret(key, label, opts \\ [])

A provider's secret field: a :secret setting on the Email tab, under the provider's label, that each scope sets for itself. opts are MishkaCmsCore.Settings.define/3's.