Packages

Send emails with Campaign Monitor, through Bamboo

Current section

Files

Jump to
bamboo_campaign_monitor lib bamboo campaign_monitor_adapter.ex
Raw

lib/bamboo/campaign_monitor_adapter.ex

defmodule Bamboo.CampaignMonitorAdapter do
@moduledoc """
Sends email using Campaign Monitor's JSON API.
Use this adapter to send emails through Campaign Monitor's API. Requires that an API
key is set in the config.
If you would like to add a replyto header to your email, then simply pass it in
using the header property or put_header function like so:
put_header("reply-to", "foo@bar.com")
## Example config
# In config/config.exs, or config.prod.exs, etc.
config :my_app, MyApp.Mailer,
adapter: Bamboo.CampaignMonitorAdapter,
api_key: "my_api_key", # or System.get_env("API_KEY")
client_id: "my_client_id" # or System.get_env("CLIENT_ID")
# Define a Mailer. Maybe in lib/my_app/mailer.ex
defmodule MyApp.Mailer do
use Bamboo.Mailer, otp_app: :my_app
end
"""
@service_name "CampaignMonitor"
@default_base_uri "https://api.createsend.com/api/v3.2"
@classic_email_path "/transactional/classicEmail/send"
@smart_email_path "/transactional/smartEmail/[smartEmailId]/send"
@behaviour Bamboo.Adapter
alias Bamboo.Email
import Bamboo.ApiError
def deliver(email, config) do
api_key = get_from_config(config, :api_key)
body = email |> to_campaign_monitor_body(config) |> Poison.encode!()
url = [base_uri(), get_path(email, config)]
case :hackney.post(url, headers(api_key), body, [:with_body]) do
{:ok, status, _headers, response} when status > 299 ->
filtered_params = body |> Poison.decode!() |> Map.put("key", "[FILTERED]")
raise_api_error(@service_name, response, filtered_params)
{:ok, status, headers, response} ->
%{status_code: status, headers: headers, body: response}
{:error, reason} ->
raise_api_error(inspect(reason))
end
end
@doc false
def handle_config(config) do
# build the api key - will raise if there are errors
Map.merge(config, %{api_key: get_from_config(config, :api_key)})
end
@doc false
def supports_attachments?, do: false
defp get_from_config(config, key) do
value =
case Map.get(config, key) do
{:system, var} -> System.get_env(var)
key -> key
end
if value in [nil, ""] do
raise_api_key_error(config)
else
value
end
end
defp raise_api_key_error(config) do
raise ArgumentError, """
There was no API key set for the Campaign Monitor adapter.
* Here are the config options that were passed in:
#{inspect(config)}
"""
end
defp headers(api_key) do
[
{"Content-Type", "application/json"},
{"Accept", "application/json"},
{"Authorization", "Basic #{Base.encode64(api_key <> ":x")}"}
]
end
# get the path based on the type of email (smart/classic)
defp get_path(%Email{private: %{smart_email_id: smart_email_id}}, _) do
String.replace(@smart_email_path, "[smartEmailId]", smart_email_id)
end
defp get_path(%Email{}, config) do
client_id = get_from_config(config, :client_id)
@classic_email_path <> "?clientID=#{client_id}"
end
defp to_campaign_monitor_body(email = %Email{}, _config) do
%{}
|> put_to(email)
|> put_cc(email)
|> put_bcc(email)
|> put_from(email)
|> put_reply_to(email)
|> put_subject(email)
|> put_html_body(email)
|> put_text_body(email)
|> put_consent_to_track(email)
|> put_tracking_group(email)
|> put_smart_email_data(email)
end
defp put_from(body, %Email{from: from}) do
Map.put(body, "From", to_address(from))
end
defp put_to(body, %Email{to: to}) do
put_addresses(body, "To", to)
end
defp put_cc(body, %Email{cc: []}), do: body
defp put_cc(body, %Email{cc: cc}) do
put_addresses(body, "CC", cc)
end
defp put_bcc(body, %Email{bcc: []}), do: body
defp put_bcc(body, %Email{bcc: bcc}) do
put_addresses(body, "BCC", bcc)
end
defp put_reply_to(body, %Email{headers: %{"reply-to" => reply_to}}) do
Map.put(body, "ReplyTo", reply_to)
end
defp put_reply_to(body, _), do: body
defp put_subject(body, %Email{subject: subject}) when not is_nil(subject),
do: Map.put(body, "Subject", subject)
defp put_subject(body, _), do: body
defp put_html_body(body, %Email{html_body: nil}), do: body
defp put_html_body(body, %Email{html_body: html_body}) do
Map.put(body, "Html", html_body)
end
defp put_text_body(body, %Email{text_body: nil}), do: body
defp put_text_body(body, %Email{text_body: text_body}) do
Map.put(body, "Text", text_body)
end
defp put_consent_to_track(body, %Email{private: %{consent_to_track: "Yes"}}) do
Map.put(body, "ConsentToTrack", "Yes")
end
defp put_consent_to_track(body, _) do
Map.put(body, "ConsentToTrack", "No")
end
defp put_tracking_group(body, %Email{private: %{group: group}}) do
Map.put(body, "Group", group)
end
defp put_tracking_group(body, _), do: body
defp put_smart_email_data(body, %Email{private: %{smart_email_data: data}}) do
Map.put(body, "Data", data)
end
defp put_smart_email_data(body, _), do: body
defp put_addresses(body, _, []), do: body
defp put_addresses(body, field, addresses),
do: Map.put(body, field, Enum.map(addresses, &to_address/1))
defp to_address({nil, address}), do: address
defp to_address({"", address}), do: address
defp to_address({name, address}), do: "#{name} <#{address}>"
defp base_uri do
Application.get_env(:bamboo, :campaign_monitor_base_uri) || @default_base_uri
end
end