Elixir
Official Unsent Elixir SDK for sending emails and managing contacts.
This guide shows how to install and use the official unsent Elixir SDK.
Installation
First, you need to add the unsent package to your project's dependencies. Open your mix.exs file and add the following line to the deps function:
def deps do
[
{:unsent, "~> 1.0"}
]
endAfter adding the dependency, run the following command in your terminal to fetch and install the package:
mix deps.getInitialize
To start using the SDK, you need to create a client instance. You'll need your API key, which you can find in your Unsent dashboard.
Create a new client using Unsent.new/1:
client = Unsent.new("un_xxx")Send an email
Now you're ready to send your first email. You can do this by defining an email map and passing it to the Emails.send/2 function.
Here is a simple example of sending an HTML email:
alias Unsent.Emails
# Initialize the client
client = Unsent.new("un_xxx")
# Define the email parameters
email = %{
to: "user@example.com",
from: "no-reply@yourdomain.com",
subject: "Welcome",
html: "<strong>Hello!</strong>"
}
# Send the email
case Emails.send(client, email) do
{:ok, data} ->
IO.puts("Email sent! ID: #{data["id"]}")
{:error, error} ->
IO.puts("Error: #{error["message"]}")
endWith attachments and scheduling
You can also send emails with attachments and schedule them for a later time.
- Attachments: Add an
attachmentslist where each item has afilenameandcontent(Base64 encoded string). - Scheduling: Use the
scheduledAtfield with an ISO 8601 formatted date string.
email = %{
to: "user@example.com",
from: "no-reply@yourdomain.com",
subject: "Report",
text: "See attached.",
attachments: [
%{
filename: "report.txt",
content: "SGVsbG8gd29ybGQ=" # Content must be Base64 encoded
}
],
# Schedule for 10 minutes from now
scheduledAt: DateTime.utc_now() |> DateTime.add(600, :second) |> DateTime.to_iso8601()
}
{:ok, data} = Emails.create(client, email)Batch send
If you need to send multiple emails at once, use the Emails.batch/2 function. This is more efficient than sending them one by one.
emails = [
%{
to: "a@example.com",
from: "no-reply@yourdomain.com",
subject: "A",
html: "<p>A</p>"
},
%{
to: "b@example.com",
from: "no-reply@yourdomain.com",
subject: "B",
html: "<p>B</p>"
}
]
case Emails.batch(client, emails) do
{:ok, data} ->
IO.puts("Sent #{length(data["data"])} emails")
{:error, error} ->
IO.puts("Error: #{error["message"]}")
endIdempotent Retries
To safely retry requests, you can pass custom headers using the opts keyword list.
# For single email
Unsent.Emails.send(client, email, headers: [{"Idempotency-Key", "unique-key-123"}])
# For batch emails
Unsent.Emails.batch(client, emails, headers: [{"Idempotency-Key", "batch-unique-key-123"}])Retrieve and manage emails
You can retrieve the status of sent emails, update their scheduled time, or cancel them if they haven't been sent yet.
Get an email
To check the status of a specific email, use Emails.get/2 with the email ID:
case Emails.get(client, "email_123") do
{:ok, email} ->
IO.puts("Email status: #{email["status"]}")
{:error, error} ->
IO.puts("Error: #{error["message"]}")
endUpdate schedule time
If you need to change when a scheduled email will be sent, you can update its scheduledAt property:
update = %{
scheduledAt: DateTime.utc_now() |> DateTime.add(3600, :second) |> DateTime.to_iso8601()
}
{:ok, data} = Emails.update(client, "email_123", update)Cancel a scheduled email
To stop a scheduled email from being sent, use the Emails.cancel/2 function:
case Emails.cancel(client, "email_123") do
{:ok, _data} ->
IO.puts("Email cancelled successfully")
{:error, error} ->
IO.puts("Error: #{error["message"]}")
endContacts
Manage your audience by creating and updating contacts. Contacts can be organized into "contact books" (identified by book_id).
Create a contact
Add a new contact to a specific contact book. You can include metadata like their subscription plan.
alias Unsent.Contacts
contact = %{
email: "user@example.com",
firstName: "Jane",
metadata: %{
plan: "pro"
}
}
{:ok, data} = Contacts.create(client, "book_123", contact)Get a contact
Retrieve details about a specific contact using their ID and the book ID:
{:ok, contact} = Contacts.get(client, "book_123", "contact_456")Update a contact
Update a contact's information, such as their name or metadata:
update = %{
firstName: "John",
metadata: %{
plan: "enterprise"
}
}
{:ok, data} = Contacts.update(client, "book_123", "contact_456", update)Upsert a contact
Use upsert to create a contact if they don't exist, or update them if they do. This is useful for syncing data.
contact = %{
email: "user@example.com",
firstName: "Jane"
}
{:ok, data} = Contacts.upsert(client, "book_123", "contact_456", contact)Delete a contact
Remove a contact from a book:
{:ok, data} = Contacts.delete(client, "book_123", "contact_456")Campaigns
Campaigns allow you to send emails to an entire contact book.
Create a campaign
Create a new campaign by specifying the content and the target contact book ID.
alias Unsent.Campaigns
campaign = %{
name: "Welcome Series",
subject: "Welcome!",
html: "<p>Thanks for joining us!</p>",
from: "welcome@yourdomain.com",
contactBookId: "book_123"
}
{:ok, data} = Campaigns.create(client, campaign)
IO.puts("Campaign created! ID: #{data["id"]}")Schedule a campaign
Once created, you can schedule the campaign to be sent at a specific time.
schedule = %{
scheduledAt: "2024-12-01T10:00:00Z"
}
{:ok, data} = Campaigns.schedule(client, "campaign_123", schedule)Pause and resume campaigns
You can pause a running or scheduled campaign and resume it later.
# Pause
{:ok, _data} = Campaigns.pause(client, "campaign_123")
IO.puts("Campaign paused successfully!")
# Resume
{:ok, _data} = Campaigns.resume(client, "campaign_123")
IO.puts("Campaign resumed successfully!")Domains
Manage the domains you use to send emails.
List domains
Retrieve a list of all your domains and their verification status.
alias Unsent.Domains
case Domains.list(client) do
{:ok, domains} ->
Enum.each(domains, fn domain ->
IO.puts("Domain: #{domain["domain"]}, Status: #{domain["status"]}")
end)
{:error, error} ->
IO.puts("Error: #{error["message"]}")
endCreate a domain
Add a new domain to your account.
domain = %{
domain: "yourdomain.com"
}
{:ok, data} = Domains.create(client, domain)Verify a domain
Check the verification status of a domain.
case Domains.verify(client, 123) do
{:ok, data} ->
IO.puts("Verification status: #{data["status"]}")
{:error, error} ->
IO.puts("Error: #{error["message"]}")
endError handling
The SDK supports two modes of error handling.
Raising exceptions (Default)
By default, the SDK raises an Unsent.HTTPError exception if the API returns a non-2xx response. This is useful if you want to let the process crash or handle errors with try/rescue.
try do
{:ok, data} = Emails.get(client, "email_123")
rescue
e in Unsent.HTTPError ->
IO.puts("HTTP #{e.status_code}: #{e.error["message"]}")
endReturning error tuples
If you prefer to handle errors as return values (e.g., {:error, reason}), you can set raise_on_error: false when initializing the client.
client = Unsent.new("un_xxx", raise_on_error: false)
case Emails.get(client, "email_123") do
{:ok, data} ->
IO.puts("Success!")
{:error, error} ->
IO.puts("Error: #{error["message"]}")
end