Packages
swoosh
1.6.2
1.26.3
1.26.2
1.26.1
1.26.0
1.25.3
1.25.2
1.25.1
1.25.0
1.24.0
1.23.1
1.23.0
1.22.1
1.22.0
1.21.0
1.20.1
1.20.0
1.19.9
1.19.8
1.19.7
1.19.6
1.19.5
1.19.4
1.19.3
1.19.2
1.19.1
1.19.0
1.18.4
1.18.3
1.18.2
1.18.1
1.18.0
1.17.10
1.17.9
1.17.8
retired
1.17.7
retired
1.17.6
1.17.5
1.17.4
retired
1.17.3
1.17.2
1.17.1
1.17.0
1.16.12
1.16.11
1.16.10
1.16.9
1.16.8
1.16.7
1.16.6
1.16.5
1.16.4
1.16.3
1.16.2
retired
1.16.1
retired
1.16.0
1.15.3
1.15.2
1.15.1
1.15.0
1.14.4
1.14.3
1.14.2
1.14.1
1.14.0
1.13.0
1.12.0
1.11.6
1.11.5
1.11.4
1.11.3
1.11.2
1.11.1
retired
1.11.0
1.10.3
1.10.2
1.10.1
1.10.0
1.9.1
1.9.0
1.8.3
1.8.2
1.8.1
1.8.0
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.2
1.5.1
1.5.0
1.4.0
1.3.11
1.3.10
1.3.9
1.3.8
retired
1.3.7
1.3.6
retired
1.3.5
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.2
1.2.1
1.2.0
1.1.2
1.1.1
1.1.0
1.0.9
1.0.8
retired
1.0.7
retired
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.25.6
0.25.5
0.25.4
0.25.3
retired
0.25.2
0.25.1
0.25.0
0.24.4
0.24.3
0.24.2
0.24.1
0.24.0
0.23.5
0.23.4
0.23.3
0.23.2
0.23.1
0.23.0
0.22.2
0.22.1
0.22.0
0.21.1
0.21.0
0.20.0
0.19.0
0.18.0
0.17.0
0.16.1
0.16.0
0.15.0
0.14.0
0.13.0
0.12.1
0.12.0
0.11.0
0.10.0
0.9.1
0.9.0
0.8.1
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Compose, deliver and test your emails easily in Elixir. Supports SMTP, Sendgrid, Mandrill, Postmark, Mailgun and many more out of the box. Preview your emails in the browser. Test your email sending code.
Current section
Files
Jump to
Current section
Files
lib/swoosh/adapters/sparkpost.ex
defmodule Swoosh.Adapters.SparkPost do
@moduledoc ~S"""
An adapter that sends email using the SparkPost API.
For reference: [SparkPost API docs](https://developers.sparkpost.com/api/)
## Example
# config/config.exs
config :sample, Sample.Mailer,
adapter: Swoosh.Adapters.SparkPost,
api_key: "my-api-key",
endpoint: "https://api.sparkpost.com/api/v1"
# or "https://YOUR_DOMAIN.sparkpostelite.com/api/v1" for enterprise
# lib/sample/mailer.ex
defmodule Sample.Mailer do
use Swoosh.Mailer, otp_app: :sample
end
## Using with SparkPost templates
import Swoosh.Email
new()
|> from("tony.stark@example.com")
|> to("steve.rogers@example.com")
|> subject("Hello, Avengers!")
|> put_provider_option(:template_id, "my-first-email")
|> put_provider_option(:substitution_data, %{
first_name: "Peter",
last_name: "Parker"
})
## Setting SparkPost transmission options
Full options can be found at [SparkPost Transmissions API Docs](https://developers.sparkpost.com/api/transmissions/#header-request-body)
import Swoosh.Email
new()
|> from("tony.stark@example.com")
|> to("steve.rogers@example.com")
|> subject("Hello, Avengers!")
|> put_provider_option(:options, %{
click_tracking: false,
open_tracking: false,
transactional: true,
inline_css: true
})
## Provider Options
* `:options` (map) - customization on how the email is sent
* `:template_id` (string) - id of the template to use
* `:substitution_data` (map) - data passed to the template language in
the content, and take precendence over the other data like `:metadata`
"""
use Swoosh.Adapter, required_config: [:api_key]
alias Swoosh.Email
import Swoosh.Email.Render
@endpoint "https://api.sparkpost.com/api/v1"
@impl true
def deliver(%Email{} = email, config \\ []) do
headers = prepare_headers(email, config)
body = email |> prepare_body |> Swoosh.json_library().encode!
url = [endpoint(config), "/transmissions"]
case Swoosh.ApiClient.post(url, headers, body, email) do
{:ok, 200, _headers, body} ->
{:ok, Swoosh.json_library().decode!(body)}
{:ok, code, _headers, body} when code > 399 ->
case Swoosh.json_library().decode(body) do
{:ok, error} -> {:error, {code, error}}
{:error, _} -> {:error, {code, body}}
end
{:error, reason} ->
{:error, reason}
end
end
defp endpoint(config), do: config[:endpoint] || @endpoint
defp prepare_headers(_email, config) do
[
{"User-Agent", "swoosh/#{Swoosh.version()}"},
{"Authorization", config[:api_key]},
{"Content-Type", "application/json"}
]
end
defp prepare_body(
%{
from: {name, address},
to: to,
subject: subject,
text_body: text,
html_body: html
} = email
) do
%{
content: %{
from: %{
name: name,
email: address
},
subject: subject,
text: text,
html: html,
headers: %{}
},
recipients: prepare_recipients(to, to)
}
|> prepare_reply_to(email)
|> prepare_cc(email)
|> prepare_bcc(email)
|> prepare_custom_headers(email)
|> prepare_attachments(email)
|> prepare_template_id(email)
|> prepare_substitutions(email)
|> prepare_options(email)
end
defp prepare_reply_to(body, %{reply_to: nil}), do: body
defp prepare_reply_to(body, %{reply_to: reply_to}) do
put_in(body, [:content, :reply_to], render_recipient(reply_to))
end
defp prepare_cc(body, %{cc: []}), do: body
defp prepare_cc(body, %{cc: cc, to: to}) do
body
|> update_in([:recipients], fn list ->
list ++ prepare_recipients(cc, to)
end)
|> put_in([:content, :headers, "CC"], render_recipient(cc))
end
defp prepare_bcc(body, %{bcc: []}), do: body
defp prepare_bcc(body, %{bcc: bcc, to: to}) do
update_in(body.recipients, fn list ->
list ++ prepare_recipients(bcc, to)
end)
end
defp prepare_recipients(recipients, to) do
Enum.map(recipients, fn {name, address} ->
%{
address: %{
name: name,
email: address,
header_to: raw_email_addresses(to)
}
}
end)
end
defp raw_email_addresses(mailboxes) do
mailboxes |> Enum.map_join(",", fn {_name, address} -> address end)
end
defp prepare_attachments(body, %{attachments: []}), do: body
defp prepare_attachments(body, %{attachments: attachments}) do
{standalone_attachments, inline_attachments} =
Enum.split_with(attachments, fn %{type: type} -> type == :attachment end)
body
|> inject_attachments(:attachments, standalone_attachments)
|> inject_attachments(:inline_images, inline_attachments)
end
defp inject_attachments(body, _key, []), do: body
defp inject_attachments(body, key, attachments) do
put_in(
body.content[key],
Enum.map(attachments, fn %{content_type: type, filename: name} = attachment ->
%{type: type, name: name, data: Swoosh.Attachment.get_content(attachment, :base64)}
end)
)
end
defp prepare_template_id(body, %{provider_options: %{template_id: template_id}}) do
put_in(body, [:content, :template_id], template_id)
end
defp prepare_template_id(body, _email), do: body
defp prepare_substitutions(body, %{provider_options: %{substitution_data: substitution_data}}) do
Map.put(body, :substitution_data, substitution_data)
end
defp prepare_substitutions(body, _email), do: body
defp prepare_options(body, %{provider_options: %{options: options}}) do
Map.put(body, :options, options)
end
defp prepare_options(body, _email), do: body
defp prepare_custom_headers(body, %{headers: headers}) do
custom_headers = Map.merge(body.content.headers, headers)
put_in(body, [:content, :headers], custom_headers)
end
end