LettermintLettermint
  • Knowledge base
  • Community
  • Changelog
  • Support
  • Documentation
  • Sending API
  • Team API
  • MCP server
Get started
Send email
    Send with
      SDKs
        Node.jsPHPPythonGoJava.NETElixir
      Frameworks
    SMTP
    Email activitySchedulingTest emailsTLSIdempotencySuppressionsTagsInline imagesData retentionSending limits
    Tracking
Receive email
Manage
Resources
SDKs

Elixir

Use the official Lettermint Elixir SDK to send email from an Elixir application. The SDK also supports the Team API and webhook signature verification. See SDKs and integrations for other packages.

Requirements

Before you start, you need:

  • Elixir 1.15 or newer with a compatible Erlang/OTP release
  • A Mix project
  • A Lettermint account with a verified sending domain
  • A Project API token from your project settings

1. Installation

Add the Lettermint Hex package to the existing dependency list in mix.exs:

ElixirCode
defp deps do [ {:lettermint, "~> 1.0"} ] end

Install the dependency:

TerminalCode
mix deps.get

The SDK uses Req for HTTP requests and Jason for JSON. Mix installs these dependencies. No application configuration is required.

2. Send your first email

Set LETTERMINT_PROJECT_TOKEN in your application's environment. Use a Project API token for email sends.

Create a script in your project directory:

ElixirCode
client = Lettermint.email(System.fetch_env!("LETTERMINT_PROJECT_TOKEN")) {:ok, message} = Lettermint.Email.send(client, %{ from: "Example <hello@yourdomain.com>", to: ["recipient@example.com"], subject: "Hello from Lettermint", html: "<h1>Hello!</h1><p>This is a test email.</p>", text: "Hello! This is a test email." }) IO.puts("Email ID: #{message.message_id}") IO.puts("Status: #{message.status}")

Replace the sender with an address on your verified domain. Replace the recipient with your test address, then run the script:

TerminalCode
mix run send_email.exs

API calls return {:ok, result} or {:error, %Lettermint.Error{}}. The first example matches a successful response. Use a case expression to handle failures, as shown in the error section below.

3. Email options

The examples below use the client from the previous section. Request maps accept atom or string keys.

Recipients, reply-to, and headers

ElixirCode
Lettermint.Email.send(client, %{ from: "Support <support@yourdomain.com>", to: ["customer@example.com", "colleague@example.com"], cc: ["manager@yourdomain.com"], bcc: ["archive@yourdomain.com"], reply_to: ["help@yourdomain.com"], subject: "Support ticket 12345", text: "Your support ticket has an update.", headers: %{"X-Ticket-ID" => "12345"} })

The payload's headers field sets email headers. Use the idempotency_key request option for the HTTP idempotency header.

Tags and metadata

ElixirCode
Lettermint.Email.send(client, %{ from: "orders@yourdomain.com", to: ["customer@example.com"], subject: "Order 12345 confirmed", text: "Your order is confirmed.", tags: [%{name: "category", value: "order-confirmation"}], metadata: %{order_id: "12345", customer_id: "cust_789"} })

Use tags for named tags or tag: "order-confirmation" for a single tag. Use string values for metadata. Lettermint includes metadata in webhook payloads so you can connect delivery events to application records. See tags for tag options.

Route and delivery settings

ElixirCode
Lettermint.Email.send(client, %{ from: "notifications@yourdomain.com", to: ["recipient@example.com"], subject: "Your account is ready", text: "You can now sign in.", route: "transactional", settings: %{track_opens: false, track_clicks: true, tls: "enforced"} })

route selects a route by its slug. The tracking settings control open and click tracking for this email. tls: "enforced" requires TLS for email delivery. See tracking and TLS.

Idempotency

Pass an idempotency key as a request option:

ElixirCode
Lettermint.Email.send( client, %{ from: "orders@yourdomain.com", to: ["customer@example.com"], subject: "Order 12345 confirmed", text: "Your order is confirmed." }, idempotency_key: "order-confirmation-12345" )

Use the same key when you retry the same email. The SDK does not retry requests automatically. See idempotency for the API rules and retention window.

File attachments

Read the file and encode its content as Base64:

ElixirCode
content = "/path/to/invoice.pdf" |> File.read!() |> Base.encode64() Lettermint.Email.send(client, %{ from: "invoices@yourdomain.com", to: ["customer@example.com"], subject: "Your invoice", text: "Your invoice is attached.", attachments: [ %{filename: "invoice.pdf", content: content, content_type: "application/pdf"} ] })

For an inline image, set content_id on the attachment and use the matching cid: reference in the HTML body. See inline images.

Scheduled emails

Use a future timestamp with an explicit time zone:

ElixirCode
scheduled_at = DateTime.utc_now() |> DateTime.add(3600, :second) |> DateTime.to_iso8601() Lettermint.Email.send(client, %{ from: "reminders@yourdomain.com", to: ["recipient@example.com"], subject: "Appointment reminder", text: "Your appointment starts in one hour.", scheduled_at: scheduled_at })

The SDK also provides Lettermint.Messages.reschedule/3 and Lettermint.Messages.cancel/2. See email scheduling for scheduling limits and cancellation behavior.

4. Use the pipe operator

Use Lettermint.EmailBuilder to build an email in separate steps:

ElixirCode
alias Lettermint.EmailBuilder, as: Email client |> Email.new() |> Email.from("orders@yourdomain.com") |> Email.to(["customer@example.com"]) |> Email.subject("Order 12345 confirmed") |> Email.html("<h1>Order confirmed</h1><p>Thank you for your order.</p>") |> Email.text("Order confirmed. Thank you for your order.") |> Email.tags([%{name: "category", value: "order-confirmation"}]) |> Email.metadata(%{order_id: "12345"}) |> Email.send(idempotency_key: "order-confirmation-12345")

Each builder function replaces one field and returns a new builder. Use Email.to_map/1 to prepare an item for Lettermint.Email.send_batch/2.

5. Responses and errors

Successful JSON responses use generated structs. For an email send, read message_id and status. API acceptance does not confirm delivery. Use webhooks for delivery and bounce events.

Handle API errors and other SDK failures with a case expression:

ElixirCode
payload = %{ from: "hello@yourdomain.com", to: ["recipient@example.com"], subject: "Hello", text: "This is a test email." } case Lettermint.Email.send(client, payload) do {:ok, message} -> IO.puts("Email ID: #{message.message_id}") {:error, %Lettermint.Error{kind: :api, status: status}} -> IO.puts(:stderr, "Lettermint rejected the request: HTTP #{status}.") {:error, %Lettermint.Error{kind: kind}} -> IO.puts(:stderr, "The request failed: #{kind}.") end

Error kinds are :api, :transport, and :decode. API errors include the HTTP status and a body field. The SDK removes token text from error data. Invalid local arguments raise ArgumentError.

To set the request timeout, pass milliseconds when you create the client:

ElixirCode
client = Lettermint.email(System.fetch_env!("LETTERMINT_PROJECT_TOKEN"), timeout: 15_000)

The timeout applies separately to connection setup and response receipt.

Team API

Use a separate Team API token to manage team resources. Set it in LETTERMINT_TEAM_TOKEN:

ElixirCode
api = Lettermint.api(System.fetch_env!("LETTERMINT_TEAM_TOKEN")) {:ok, page} = Lettermint.Domains.list(api, query: %{"page[size]" => 25}) Enum.each(page.data, fn domain -> IO.puts(domain.domain) end)

Do not use a Team API token with the email client. See the Team API quickstart for token setup and permissions.

Track delivery, opens, and bounces

Enable tracking on your route to record opens and clicks. Subscribe to webhooks for delivery and bounce events.

Use Lettermint.Webhook.verify(raw_body, signature_header, webhook_secret) to verify webhook signatures. Pass the original request body before JSON decoding. Verification returns :ok or {:error, :invalid_signature}. See webhook signing for the header and signing secret.

Use Lettermint with Swoosh

If your application uses Swoosh, use its Lettermint adapter for mail delivery. The official SDK provides direct Sending API and Team API access. The Swoosh adapter remains a separate integration.

Next steps

Tags

Organize emails with tags.

Webhooks

Receive delivery and bounce events.

Test addresses

Test delivery and bounce handling.

Hex package

Find package releases and dependencies.

GitHub repository

Read the source code or report an issue.

.NETLaravel
On this page
  • Requirements
  • 1. Installation
  • 2. Send your first email
  • 3. Email options
    • Recipients, reply-to, and headers
    • Tags and metadata
    • Route and delivery settings
    • Idempotency
    • File attachments
    • Scheduled emails
  • 4. Use the pipe operator
  • 5. Responses and errors
  • Team API
  • Track delivery, opens, and bounces
  • Use Lettermint with Swoosh
  • Next steps