Packages

Elixir client for the Listmonk open-source email platform API

Current section

Files

Jump to
listmonk_client lib listmonk.ex
Raw

lib/listmonk.ex

defmodule Listmonk do
@moduledoc """
Elixir client for the Listmonk email platform API.
This module provides a comprehensive interface to interact with Listmonk's API,
including subscriber management, campaigns, templates, lists, and transactional emails.
Based on the Python Listmonk client by Michael Kennedy (https://github.com/mikeckennedy/listmonk),
adapted to idiomatic Elixir patterns and conventions.
## Configuration
You can configure the client either via environment variables or at runtime:
### Environment Variables
LISTMONK_URL=https://listmonk.example.com
LISTMONK_USERNAME=your_username
LISTMONK_PASSWORD=your_password_or_api_key
### Runtime Configuration
config = %Listmonk.Config{
url: "https://listmonk.example.com",
username: "your_username",
password: "your_password_or_api_key"
}
Runtime configuration takes precedence over environment variables.
## Usage
See `USAGE.md` for detailed examples.
"""
alias Listmonk.{
Config,
Error,
Subscribers,
Lists,
Campaigns,
Templates,
Transactional
}
alias Listmonk.Models.{
Subscriber,
MailingList,
Campaign,
Template
}
@doc """
Checks the health of the Listmonk instance.
Returns `{:ok, true}` if the instance is healthy, or an error tuple otherwise.
"""
@spec healthy?(Config.t() | nil) :: {:ok, boolean()} | {:error, term()}
defdelegate healthy?(config \\ nil), to: Listmonk.Client
@doc """
Checks the health of the Listmonk instance. Raises on error.
"""
@spec healthy!(Config.t() | nil) :: boolean()
defdelegate healthy!(config \\ nil), to: Listmonk.Client
# Subscriber functions
@doc "See `Listmonk.Subscribers.get/2`"
@spec get_subscribers(keyword(), Config.t() | nil) ::
{:ok, list(Subscriber.t())} | {:error, Error.t()}
defdelegate get_subscribers(opts \\ [], config \\ nil), to: Subscribers, as: :get
@doc "See `Listmonk.Subscribers.get!/2`"
@spec get_subscribers!(keyword(), Config.t() | nil) :: list(Subscriber.t())
defdelegate get_subscribers!(opts \\ [], config \\ nil), to: Subscribers, as: :get!
@doc "See `Listmonk.Subscribers.get_by_email/2`"
@spec get_subscriber_by_email(String.t(), Config.t() | nil) ::
{:ok, Subscriber.t() | nil} | {:error, Error.t()}
defdelegate get_subscriber_by_email(email, config \\ nil), to: Subscribers, as: :get_by_email
@doc "See `Listmonk.Subscribers.get_by_email!/2`"
@spec get_subscriber_by_email!(String.t(), Config.t() | nil) :: Subscriber.t() | nil
defdelegate get_subscriber_by_email!(email, config \\ nil), to: Subscribers, as: :get_by_email!
@doc "See `Listmonk.Subscribers.get_by_id/2`"
@spec get_subscriber_by_id(integer(), Config.t() | nil) ::
{:ok, Subscriber.t() | nil} | {:error, Error.t()}
defdelegate get_subscriber_by_id(id, config \\ nil), to: Subscribers, as: :get_by_id
@doc "See `Listmonk.Subscribers.get_by_id!/2`"
@spec get_subscriber_by_id!(integer(), Config.t() | nil) :: Subscriber.t() | nil
defdelegate get_subscriber_by_id!(id, config \\ nil), to: Subscribers, as: :get_by_id!
@doc "See `Listmonk.Subscribers.get_by_uuid/2`"
@spec get_subscriber_by_uuid(String.t(), Config.t() | nil) ::
{:ok, Subscriber.t() | nil} | {:error, Error.t()}
defdelegate get_subscriber_by_uuid(uuid, config \\ nil), to: Subscribers, as: :get_by_uuid
@doc "See `Listmonk.Subscribers.get_by_uuid!/2`"
@spec get_subscriber_by_uuid!(String.t(), Config.t() | nil) :: Subscriber.t() | nil
defdelegate get_subscriber_by_uuid!(uuid, config \\ nil), to: Subscribers, as: :get_by_uuid!
@doc "See `Listmonk.Subscribers.create/2`"
@spec create_subscriber(map(), Config.t() | nil) :: {:ok, Subscriber.t()} | {:error, Error.t()}
defdelegate create_subscriber(attrs, config \\ nil), to: Subscribers, as: :create
@doc "See `Listmonk.Subscribers.create!/2`"
@spec create_subscriber!(map(), Config.t() | nil) :: Subscriber.t()
defdelegate create_subscriber!(attrs, config \\ nil), to: Subscribers, as: :create!
@doc "See `Listmonk.Subscribers.update/3`"
@spec update_subscriber(Subscriber.t(), map(), Config.t() | nil) ::
{:ok, Subscriber.t()} | {:error, Error.t()}
defdelegate update_subscriber(subscriber, attrs, config \\ nil), to: Subscribers, as: :update
@doc "See `Listmonk.Subscribers.update!/3`"
@spec update_subscriber!(Subscriber.t(), map(), Config.t() | nil) :: Subscriber.t()
defdelegate update_subscriber!(subscriber, attrs, config \\ nil), to: Subscribers, as: :update!
@doc "See `Listmonk.Subscribers.delete/2`"
@spec delete_subscriber(String.t() | integer(), Config.t() | nil) ::
{:ok, boolean()} | {:error, Error.t()}
defdelegate delete_subscriber(identifier, config \\ nil), to: Subscribers, as: :delete
@doc "See `Listmonk.Subscribers.delete!/2`"
@spec delete_subscriber!(String.t() | integer(), Config.t() | nil) :: boolean()
defdelegate delete_subscriber!(identifier, config \\ nil), to: Subscribers, as: :delete!
@doc "See `Listmonk.Subscribers.enable/2`"
@spec enable_subscriber(Subscriber.t(), Config.t() | nil) ::
{:ok, Subscriber.t()} | {:error, Error.t()}
defdelegate enable_subscriber(subscriber, config \\ nil), to: Subscribers, as: :enable
@doc "See `Listmonk.Subscribers.enable!/2`"
@spec enable_subscriber!(Subscriber.t(), Config.t() | nil) :: Subscriber.t()
defdelegate enable_subscriber!(subscriber, config \\ nil), to: Subscribers, as: :enable!
@doc "See `Listmonk.Subscribers.disable/2`"
@spec disable_subscriber(Subscriber.t(), Config.t() | nil) ::
{:ok, Subscriber.t()} | {:error, Error.t()}
defdelegate disable_subscriber(subscriber, config \\ nil), to: Subscribers, as: :disable
@doc "See `Listmonk.Subscribers.disable!/2`"
@spec disable_subscriber!(Subscriber.t(), Config.t() | nil) :: Subscriber.t()
defdelegate disable_subscriber!(subscriber, config \\ nil), to: Subscribers, as: :disable!
@doc "See `Listmonk.Subscribers.block/2`"
@spec block_subscriber(Subscriber.t(), Config.t() | nil) ::
{:ok, Subscriber.t()} | {:error, Error.t()}
defdelegate block_subscriber(subscriber, config \\ nil), to: Subscribers, as: :block
@doc "See `Listmonk.Subscribers.block!/2`"
@spec block_subscriber!(Subscriber.t(), Config.t() | nil) :: Subscriber.t()
defdelegate block_subscriber!(subscriber, config \\ nil), to: Subscribers, as: :block!
@doc "See `Listmonk.Subscribers.confirm_optin/3`"
@spec confirm_optin(String.t(), String.t(), Config.t() | nil) ::
{:ok, boolean()} | {:error, Error.t()}
defdelegate confirm_optin(subscriber_uuid, list_uuid, config \\ nil), to: Subscribers
@doc "See `Listmonk.Subscribers.confirm_optin!/3`"
@spec confirm_optin!(String.t(), String.t(), Config.t() | nil) :: boolean()
defdelegate confirm_optin!(subscriber_uuid, list_uuid, config \\ nil), to: Subscribers
# List functions
@doc "See `Listmonk.Lists.get/1`"
@spec get_lists(Config.t() | nil) :: {:ok, list(MailingList.t())} | {:error, Error.t()}
defdelegate get_lists(config \\ nil), to: Lists, as: :get
@doc "See `Listmonk.Lists.get!/1`"
@spec get_lists!(Config.t() | nil) :: list(MailingList.t())
defdelegate get_lists!(config \\ nil), to: Lists, as: :get!
@doc "See `Listmonk.Lists.get_by_id/2`"
@spec get_list_by_id(integer(), Config.t() | nil) ::
{:ok, MailingList.t() | nil} | {:error, Error.t()}
defdelegate get_list_by_id(id, config \\ nil), to: Lists, as: :get_by_id
@doc "See `Listmonk.Lists.get_by_id!/2`"
@spec get_list_by_id!(integer(), Config.t() | nil) :: MailingList.t() | nil
defdelegate get_list_by_id!(id, config \\ nil), to: Lists, as: :get_by_id!
@doc "See `Listmonk.Lists.create/2`"
@spec create_list(map(), Config.t() | nil) :: {:ok, MailingList.t()} | {:error, Error.t()}
defdelegate create_list(attrs, config \\ nil), to: Lists, as: :create
@doc "See `Listmonk.Lists.create!/2`"
@spec create_list!(map(), Config.t() | nil) :: MailingList.t()
defdelegate create_list!(attrs, config \\ nil), to: Lists, as: :create!
@doc "See `Listmonk.Lists.delete/2`"
@spec delete_list(integer(), Config.t() | nil) :: {:ok, boolean()} | {:error, Error.t()}
defdelegate delete_list(id, config \\ nil), to: Lists, as: :delete
@doc "See `Listmonk.Lists.delete!/2`"
@spec delete_list!(integer(), Config.t() | nil) :: boolean()
defdelegate delete_list!(id, config \\ nil), to: Lists, as: :delete!
# Campaign functions
@doc "See `Listmonk.Campaigns.get/1`"
@spec get_campaigns(Config.t() | nil) :: {:ok, list(Campaign.t())} | {:error, Error.t()}
defdelegate get_campaigns(config \\ nil), to: Campaigns, as: :get
@doc "See `Listmonk.Campaigns.get!/1`"
@spec get_campaigns!(Config.t() | nil) :: list(Campaign.t())
defdelegate get_campaigns!(config \\ nil), to: Campaigns, as: :get!
@doc "See `Listmonk.Campaigns.get_by_id/2`"
@spec get_campaign_by_id(integer(), Config.t() | nil) ::
{:ok, Campaign.t() | nil} | {:error, Error.t()}
defdelegate get_campaign_by_id(id, config \\ nil), to: Campaigns, as: :get_by_id
@doc "See `Listmonk.Campaigns.get_by_id!/2`"
@spec get_campaign_by_id!(integer(), Config.t() | nil) :: Campaign.t() | nil
defdelegate get_campaign_by_id!(id, config \\ nil), to: Campaigns, as: :get_by_id!
@doc "See `Listmonk.Campaigns.preview/2`"
@spec preview_campaign(integer(), Config.t() | nil) :: {:ok, String.t()} | {:error, Error.t()}
defdelegate preview_campaign(id, config \\ nil), to: Campaigns, as: :preview
@doc "See `Listmonk.Campaigns.preview!/2`"
@spec preview_campaign!(integer(), Config.t() | nil) :: String.t()
defdelegate preview_campaign!(id, config \\ nil), to: Campaigns, as: :preview!
@doc "See `Listmonk.Campaigns.create/2`"
@spec create_campaign(map(), Config.t() | nil) :: {:ok, Campaign.t()} | {:error, Error.t()}
defdelegate create_campaign(attrs, config \\ nil), to: Campaigns, as: :create
@doc "See `Listmonk.Campaigns.create!/2`"
@spec create_campaign!(map(), Config.t() | nil) :: Campaign.t()
defdelegate create_campaign!(attrs, config \\ nil), to: Campaigns, as: :create!
@doc "See `Listmonk.Campaigns.update/3`"
@spec update_campaign(Campaign.t(), map(), Config.t() | nil) ::
{:ok, Campaign.t()} | {:error, Error.t()}
defdelegate update_campaign(campaign, attrs, config \\ nil), to: Campaigns, as: :update
@doc "See `Listmonk.Campaigns.update!/3`"
@spec update_campaign!(Campaign.t(), map(), Config.t() | nil) :: Campaign.t()
defdelegate update_campaign!(campaign, attrs, config \\ nil), to: Campaigns, as: :update!
@doc "See `Listmonk.Campaigns.delete/2`"
@spec delete_campaign(integer(), Config.t() | nil) :: {:ok, boolean()} | {:error, Error.t()}
defdelegate delete_campaign(id, config \\ nil), to: Campaigns, as: :delete
@doc "See `Listmonk.Campaigns.delete!/2`"
@spec delete_campaign!(integer(), Config.t() | nil) :: boolean()
defdelegate delete_campaign!(id, config \\ nil), to: Campaigns, as: :delete!
# Template functions
@doc "See `Listmonk.Templates.get/1`"
@spec get_templates(Config.t() | nil) :: {:ok, list(Template.t())} | {:error, Error.t()}
defdelegate get_templates(config \\ nil), to: Templates, as: :get
@doc "See `Listmonk.Templates.get!/1`"
@spec get_templates!(Config.t() | nil) :: list(Template.t())
defdelegate get_templates!(config \\ nil), to: Templates, as: :get!
@doc "See `Listmonk.Templates.get_by_id/2`"
@spec get_template_by_id(integer(), Config.t() | nil) ::
{:ok, Template.t() | nil} | {:error, Error.t()}
defdelegate get_template_by_id(id, config \\ nil), to: Templates, as: :get_by_id
@doc "See `Listmonk.Templates.get_by_id!/2`"
@spec get_template_by_id!(integer(), Config.t() | nil) :: Template.t() | nil
defdelegate get_template_by_id!(id, config \\ nil), to: Templates, as: :get_by_id!
@doc "See `Listmonk.Templates.preview/2`"
@spec preview_template(integer(), Config.t() | nil) :: {:ok, String.t()} | {:error, Error.t()}
defdelegate preview_template(id, config \\ nil), to: Templates, as: :preview
@doc "See `Listmonk.Templates.preview!/2`"
@spec preview_template!(integer(), Config.t() | nil) :: String.t()
defdelegate preview_template!(id, config \\ nil), to: Templates, as: :preview!
@doc "See `Listmonk.Templates.create/2`"
@spec create_template(map(), Config.t() | nil) :: {:ok, Template.t()} | {:error, Error.t()}
defdelegate create_template(attrs, config \\ nil), to: Templates, as: :create
@doc "See `Listmonk.Templates.create!/2`"
@spec create_template!(map(), Config.t() | nil) :: Template.t()
defdelegate create_template!(attrs, config \\ nil), to: Templates, as: :create!
@doc "See `Listmonk.Templates.update/3`"
@spec update_template(Template.t(), map(), Config.t() | nil) ::
{:ok, Template.t()} | {:error, Error.t()}
defdelegate update_template(template, attrs, config \\ nil), to: Templates, as: :update
@doc "See `Listmonk.Templates.update!/3`"
@spec update_template!(Template.t(), map(), Config.t() | nil) :: Template.t()
defdelegate update_template!(template, attrs, config \\ nil), to: Templates, as: :update!
@doc "See `Listmonk.Templates.delete/2`"
@spec delete_template(integer(), Config.t() | nil) :: {:ok, boolean()} | {:error, Error.t()}
defdelegate delete_template(id, config \\ nil), to: Templates, as: :delete
@doc "See `Listmonk.Templates.delete!/2`"
@spec delete_template!(integer(), Config.t() | nil) :: boolean()
defdelegate delete_template!(id, config \\ nil), to: Templates, as: :delete!
@doc "See `Listmonk.Templates.set_default/2`"
@spec set_default_template(integer(), Config.t() | nil) ::
{:ok, boolean()} | {:error, Error.t()}
defdelegate set_default_template(id, config \\ nil), to: Templates, as: :set_default
@doc "See `Listmonk.Templates.set_default!/2`"
@spec set_default_template!(integer(), Config.t() | nil) :: boolean()
defdelegate set_default_template!(id, config \\ nil), to: Templates, as: :set_default!
# Transactional email functions
@doc "See `Listmonk.Transactional.send_email/2`"
@spec send_transactional_email(map(), Config.t() | nil) ::
{:ok, boolean()} | {:error, Error.t()}
defdelegate send_transactional_email(attrs, config \\ nil), to: Transactional, as: :send_email
@doc "See `Listmonk.Transactional.send_email!/2`"
@spec send_transactional_email!(map(), Config.t() | nil) :: boolean()
defdelegate send_transactional_email!(attrs, config \\ nil), to: Transactional, as: :send_email!
end