Send email with Elixir

Req in a few lines, ready to be supervised.

You need a verified sending domain and an API key from Settings › API Keys. If neither exists yet, the quickstart covers both in a couple of minutes.

Install

{:req, "~> 0.5"}

Send

defmodule Acme.Email do
  @endpoint "https://sending.dev/api/v1/emails"
 
  def welcome(email, user_id) do
    Req.post(@endpoint,
      auth: {:bearer, System.fetch_env!("SENDING_API_KEY")},
      json: %{
        from: "Acme <[email protected]>",
        to: email,
        subject: "Welcome",
        html: "<p>You're in.</p>",
        idempotencyKey: "welcome-#{user_id}"
      }
    )
  end
end

A successful call answers 202 with the message id: accepted and queued, not yet delivered. Delivery, opens, bounces and complaints arrive later, on webhooks or in the dashboard.

What changes in Elixir

fetch_env! fails at boot when the variable is missing, which is the behaviour you want in a supervised release.

The thing that catches people

Run it inside a Task under a supervisor rather than spawning a bare process: an unsupervised task that dies takes the send with it and nothing reports the failure.

Next

  • All the fields: cc and bcc, reply-to, attachments, templates, scheduling.
  • Webhooks: delivery, bounce and complaint events, signed with HMAC.
  • Domains: SPF, DKIM and MAIL FROM, and why sending is refused until they are in place.
  • MCP: the same operations as tools, when the one writing the code is an agent.

Nearby: Compiled languages

All 30 stacks