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.
This guide covers SDK 2.0. If your project uses 1.x, follow the Elixir SDK 2.0 upgrade guide on GitHub.
Requirements
Before you start, you need:
- Elixir 1.15 or newer and Erlang/OTP 25 or newer
- 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:
mix.exs
Install the dependency:
Code
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:
send_email.exs
Replace the sender with an address on your verified domain. Replace the recipient with your test address, then run the script:
Code
The client stores nothing about a message, so create it once and share it across processes. You can also pass the token as a string, as in Lettermint.new(token). Options such as timeout: go in the second argument.
API calls return {:ok, result} or {:error, error}, where error is an exception struct. The first example matches a successful response. Use a case expression to handle failures, as shown in the error section below.
Lettermint.Emails.send/3 takes the message in the API's field names, for example reply_to and scheduled_at. The to, cc, and bcc fields are lists.
The Team API uses a separate Team API token. Pass it as team_token:, alone or next to sending_token:. Each part of the client uses its own token and never falls back to the other. See Team API below.
3. Email options
The examples below use the lettermint client from the previous section. Request maps accept atom or string keys.
Recipients, reply-to, and headers
Code
The payload's headers field sets email headers. Use the idempotency_key request option for the HTTP idempotency header.
Tags and metadata
Code
Use tags for up to 20 name and value pairs, or tag: "order-confirmation" for the existing single tag. The SDK checks tag names and values before it sends the request and returns {:error, %Lettermint.ClientValidationError{}} if one is invalid. 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
Code
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:
Code
Use the same key when you retry the same email. Lettermint.Emails.send_batch/3 and Lettermint.EmailBuilder.send/2 take the same option. The key applies only to that call, and the SDK does not retry requests automatically. See idempotency for the API rules and retention window.
File attachments
Set content to Base64 text or to {:bytes, binary}. The SDK encodes raw bytes to Base64 for you:
Code
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:
Code
The SDK also provides Lettermint.Messages.reschedule/4 and Lettermint.Messages.cancel/3. They accept either token: the team token when you set one, otherwise the sending token. See email scheduling for scheduling limits and cancellation behavior.
Batch sending
Send up to 500 emails in one request with Lettermint.Emails.send_batch/3. The list can mix plain messages and builders (see the next section). The result is a list with one response per email:
Code
4. Use the pipe operator
Use Lettermint.Emails.compose/2 to build an email in separate steps with Lettermint.EmailBuilder:
Code
Each builder function returns a new builder and leaves the original unchanged, so one builder is safe to share and reuse as a template, also across processes. Keep the value that a function returns. The next example uses the Email alias from above:
Code
Use Email.attach/2 to add an attachment and Email.build/1 to get the message in the API's format. Builders also work in Lettermint.Emails.send_batch/3.
5. Responses and errors
Successful JSON responses use generated structs from Lettermint.Types. For an email send, read message_id and status. A field the API did not send is :unset, and enums are open, so give case expressions on values such as status a catch-all clause. API acceptance does not confirm delivery. Use webhooks for delivery and bounce events.
Every error is an exception struct. API errors are Lettermint.APIError and its specific forms, which carry status, code, message, details, and body. Match the structs you want to handle:
Code
The status-specific structs are Lettermint.AuthenticationError (401), Lettermint.PermissionError (403), Lettermint.NotFoundError (404), Lettermint.ConflictError (409), Lettermint.ValidationError (422), Lettermint.RateLimitError (429), and Lettermint.ServerError (5xx). Other errors are Lettermint.ConnectionError, Lettermint.UnexpectedResponseError, Lettermint.RedirectError, and Lettermint.ClientValidationError, which the SDK returns before it sends the request, for example for an invalid tag. Lettermint.Error provides guards such as is_api_error/1 for matching a whole family.
The SDK never retries a request and never follows a redirect. Reuse the same idempotency key when you retry so the customer gets one email. A missing token, an unrecognised token format, or an invalid option or ID raises Lettermint.ConfigError before any request.
To set the request timeout, pass milliseconds when you create the client:
Code
The timeout covers the whole request, including the response body. Pass timeout: to a single call to override it for that call.
Team API
Use a separate Team API token to manage team resources. Set it in LETTERMINT_TEAM_TOKEN:
Code
Query parameters are nested maps. Every list also has an iterate function that returns a lazy Stream and follows next_cursor:
Code
Do not pass a Team API token as sending_token:. Each part of the client uses its own token and never falls back to the other. 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.
The SDK verifies each delivery for you. Create a verifier from the webhook's signing secret and pass the raw request body and the request headers:
Code
Pass the original request body before JSON decoding. verify/4 requires both the X-Lettermint-Signature and X-Lettermint-Delivery headers and returns the decoded payload. See Webhook signatures for a Phoenix handler and the header and signing secret details.
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.