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
endSupervise 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
@type site_id() :: String.t() | nil
Callbacks
@callback deliver(Swoosh.Email.t(), site_id(), keyword()) :: {:ok, String.t() | nil} | {:error, term()}
Sends email for site_id.
@callback id() :: String.t()
The provider's id, stored in mailer.provider.
@callback label() :: String.t()
The name on the settings page, as a gettext_noop/1 msgid.
@callback offered?() :: boolean()
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.
@callback settings() :: [MishkaCmsCore.Settings.definition()]
The provider's own setting definitions (MishkaCmsCore.Settings.define/3).
Functions
@spec all() :: [module()]
Every registered provider module, the first of each id.
@spec event() :: String.t()
The event a provider plugin listens on.
The offered provider registered under id.
@spec offered() :: [module()]
The providers this installation offers on the settings page.
@spec secret(String.t(), String.t(), keyword()) :: MishkaCmsCore.Settings.definition()
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.