AshDispatch.Transports.SMS (AshDispatch v0.8.3)

View Source

SMS transport — enqueues a job that calls the configured backend.

config :ash_dispatch, :sms_backend, MyApp.SMS

The module must implement AshDispatch.SMSBackend. Without one the receipt is marked :skipped with error_message: "transport_not_implemented", as before.

The path

pending → scheduled (job enqueued)
        ↘ skipped   (recipient opted out)

later, in AshDispatch.Workers.SendSMS:
scheduled → sending → sent
                    ↘ failed  (retried)

What changed

The transport used to call backend.deliver/4 synchronously. Dispatch runs in an after_action hook inside the action's transaction, so a slow provider held that transaction open, time: could not be used, and a failed message could never be retried — RetryFailedDeliveries only recognises transports that have a worker.

It now takes the same shape as email: consent, enqueue, :scheduled. A backend that already sends synchronously keeps working unchanged — it is simply called from the worker rather than from the transaction.

Requires an Oban queue named :sms.

Delayed delivery

Falls out of the queue, exactly as it does for email:

channel = %Channel{transport: :sms, time: {:in, 300}}
channel = %Channel{transport: :sms, time: {:at, ~U[2026-09-21 06:00:00Z]}}

The recipient field

config :ash_dispatch, :recipient_fields must carry an :sms entry, or every recipient raises "No identifier field configured for sms transport":

recipient_fields: [
  sms: [identifier: :phone, name: [:display_name, :name]]
]

Summary

Functions

deliver(receipt, context, channel, event_config)

Callback implementation for AshDispatch.Transport.deliver/4.