Behaviour for suppression-list storage backends.
ships two callbacks — check/2 (pre-send lookup) and
record/2 (add/update entry). may extend with more
callbacks when the Outbound preflight lands. Default impl is
Mailglass.SuppressionStore.Ecto (Postgres-backed).
Adopters swap via:
config :mailglass, suppression_store: MyApp.SuppressionStoreSemantics
check/2 returns {:suppressed, %Entry{}} when the recipient is
on the list under any matching scope (address, domain, or
address_stream with the stream parameter). Returns :not_suppressed
otherwise. Never raises except on infrastructure failure.
record/2 inserts an Entry; on UNIQUE collision
(tenant_id, address, scope, COALESCE(stream, '')) it UPDATES
reason/source/expires_at/metadata (admin re-adds become
idempotent at the application layer).
Summary
Types
Lookup key accepted by check/2.
Attr map accepted by record/2; passes through to Mailglass.Suppression.Entry.changeset/1.
Callbacks
Optionally checks multiple lookup keys in their original order.
Functions
Checks a list through an optional native bulk callback or a bounded legacy
check/2 fallback. Results always correspond to the input positions.
Types
@type lookup_key() :: %{ :tenant_id => String.t(), :address => String.t(), optional(:stream) => atom() | nil }
Lookup key accepted by check/2.
tenant_id and address are required. stream is required when
the caller intends to match an :address_stream-scoped entry.
@type record_attrs() :: map()
Attr map accepted by record/2; passes through to Mailglass.Suppression.Entry.changeset/1.
Callbacks
@callback check( lookup_key(), keyword() ) :: {:suppressed, Mailglass.Suppression.Entry.t()} | :not_suppressed | {:error, term()}
@callback check_many( [lookup_key()], keyword() ) :: [ {:suppressed, Mailglass.Suppression.Entry.t()} | :not_suppressed | {:error, term()} ]
Optionally checks multiple lookup keys in their original order.
Stores that implement this callback must return exactly one result for each
input key. check_many/3 below probes this capability so existing stores
that only implement check/2 remain compatible.
@callback record( record_attrs(), keyword() ) :: {:ok, Mailglass.Suppression.Entry.t()} | {:error, Ecto.Changeset.t() | term()}
Functions
@spec check_many(module(), [lookup_key()], keyword()) :: [ {:suppressed, Mailglass.Suppression.Entry.t()} | :not_suppressed | {:error, term()} ]
Checks a list through an optional native bulk callback or a bounded legacy
check/2 fallback. Results always correspond to the input positions.