# `AshAuthentication.Sender`
[🔗](https://github.com/team-alembic/ash_authentication/blob/main/lib/ash_authentication/sender.ex#L5)

A module to implement sending of a token to a user.

Allows you to glue sending of instructions to
[swoosh](https://hex.pm/packages/swoosh),
[ex_twilio](https://hex.pm/packages/ex_twilio) or whatever notification system
is appropriate for your application.

Senders should return `:ok` on success or `{:error, reason}` on failure.
Failures will propagate as `AshAuthentication.Errors.SenderFailed` errors
and cause the authentication action to fail.

If you need retry logic or want to avoid blocking the action on email delivery,
consider using a job queue like [Oban](https://hex.pm/packages/oban). Your sender
can insert a job and return `:ok` immediately, letting the job handle delivery
and retries asynchronously.

## Example

Implementing as a module:

```elixir
defmodule MyApp.PasswordResetSender do
  use AshAuthentication.Sender
  import Swoosh.Email

  def send(user, reset_token, _opts) do
    new()
    |> to({user.name, user.email})
    |> from({"Doc Brown", "emmet@brown.inc"})
    |> subject("Password reset instructions")
    |> html_body("""
      <h1>Password reset instructions</h1>
      <p>
        Hi #{user.name},<br />

        Someone (maybe you) has requested a password reset for your account.
        If you did not initiate this request then please ignore this email.
      </p>
      <a href="https://example.com/user/password/reset?#{URI.encode_query(reset_token: reset_token)}\">
        Click here to reset
      </a>
    """)
    |> MyApp.Mailer.deliver()
    |> case do
      {:ok, _} -> :ok
      {:error, reason} -> {:error, reason}
    end
  end
end

defmodule MyApp.Accounts.User do
  use Ash.Resource,
    extensions: [AshAuthentication],
    domain: MyApp.Accounts

  authentication do
    strategies do
      password :password do
        resettable do
          sender MyApp.PasswordResetSender
        end
      end
    end
  end
end
```

You can also implement it directly as a function:

```elixir
defmodule MyApp.Accounts.User do
  use Ash.Resource,
    extensions: [AshAuthentication],
    domain: MyApp.Accounts

  authentication do
    strategies do
      password :password do
        resettable do
          sender fn user, token ->
            MyApp.Mailer.send_password_reset_email(user, token)
          end
        end
      end
    end
  end
end
```

# `send`

```elixir
@callback send(
  user :: Ash.Resource.Record.t() | String.t(),
  token :: String.t(),
  opts :: list()
) ::
  :ok | {:error, term()}
```

Sending callback.

This function will be called with a value representing a user, the token and any options passed
to the module in the DSL.

Should return `:ok` on success or `{:error, reason}` on failure.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
