Packages
swoosh
0.24.3
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/sendgrid.ex
defmodule Swoosh.Adapters.Sendgrid do
@moduledoc ~S"""
An adapter that sends email using the Sendgrid API.
For reference: [Sendgrid API docs](https://sendgrid.com/docs/API_Reference/Web_API_v3/Mail/index.html)
## Example
# config/config.exs
config :sample, Sample.Mailer,
adapter: Swoosh.Adapters.Sendgrid,
api_key: "my-api-key"
# lib/sample/mailer.ex
defmodule Sample.Mailer do
use Swoosh.Mailer, otp_app: :sample
end
## Sandbox mode
For [sandbox mode](https://sendgrid.com/docs/for-developers/sending-email/sandbox-mode/),
use `put_provider_option/3`:
iex> new() |> put_provider_option(:mail_settings, %{sandbox_mode: %{enable: true}})
"""
use Swoosh.Adapter, required_config: [:api_key]
alias Swoosh.Email
@base_url "https://api.sendgrid.com/v3"
@api_endpoint "/mail/send"
def deliver(%Email{} = email, config \\ []) do
headers = [
{"Content-Type", "application/json"},
{"User-Agent", "swoosh/#{Swoosh.version()}"},
{"Authorization", "Bearer #{config[:api_key]}"}
]
body = email |> prepare_body() |> Swoosh.json_library().encode!
url = [base_url(config), @api_endpoint]
case Swoosh.ApiClient.post(url, headers, body, email) do
{:ok, code, headers, _body} when code >= 200 and code <= 399 ->
{:ok, %{id: extract_id(headers)}}
{:ok, code, _headers, body} when code >= 400 and code <= 499 ->
{:error, {code, Swoosh.json_library().decode!(body)}}
{:ok, code, _headers, body} when code >= 500 ->
{:error, {code, body}}
{:error, reason} ->
{:error, reason}
end
end
defp extract_id(headers) do
headers
|> Enum.into(%{})
|> Map.get("X-Message-Id")
end
defp base_url(config), do: config[:base_url] || @base_url
defp prepare_body(email) do
%{}
|> prepare_from(email)
|> prepare_personalizations(email)
|> prepare_subject(email)
|> prepare_content(email)
|> prepare_attachments(email)
|> prepare_reply_to(email)
|> prepare_template_id(email)
|> prepare_categories(email)
|> prepare_asm(email)
|> prepare_custom_headers(email)
|> prepare_mail_settings(email)
end
defp email_item({"", email}), do: %{email: email}
defp email_item({name, email}), do: %{email: email, name: name}
defp email_item(email), do: %{email: email}
defp prepare_from(body, %{from: from}),
do: Map.put(body, :from, from |> email_item)
defp prepare_personalizations(body, email) do
personalizations =
%{}
|> prepare_to(email)
|> prepare_cc(email)
|> prepare_bcc(email)
|> prepare_custom_vars(email)
|> prepare_substitutions(email)
|> prepare_dynamic_template_data(email)
Map.put(body, :personalizations, [personalizations])
end
defp prepare_to(personalizations, %{to: to}),
do: Map.put(personalizations, :to, to |> Enum.map(&email_item(&1)))
defp prepare_cc(personalizations, %{cc: []}), do: personalizations
defp prepare_cc(personalizations, %{cc: cc}),
do: Map.put(personalizations, :cc, cc |> Enum.map(&email_item(&1)))
defp prepare_bcc(personalizations, %{bcc: []}), do: personalizations
defp prepare_bcc(personalizations, %{bcc: bcc}),
do: Map.put(personalizations, :bcc, bcc |> Enum.map(&email_item(&1)))
# example custom_vars
#
# %{"my_var" => %{"my_message_id": 123},
# "my_other_var" => %{"my_other_id": 1, "stuff": 2}}
defp prepare_custom_vars(personalizations, %{
provider_options: %{custom_args: my_vars}
}) do
Map.put(personalizations, :custom_args, my_vars)
end
defp prepare_custom_vars(personalizations, _email), do: personalizations
defp prepare_substitutions(personalizations, %{
provider_options: %{substitutions: substitutions}
}) do
Map.put(personalizations, :substitutions, substitutions)
end
defp prepare_substitutions(personalizations, _email), do: personalizations
defp prepare_dynamic_template_data(personalizations, %{
provider_options: %{dynamic_template_data: dynamic_template_data}
}) do
Map.put(personalizations, :dynamic_template_data, dynamic_template_data)
end
defp prepare_dynamic_template_data(personalizations, _email),
do: personalizations
defp prepare_subject(body, %{subject: subject}),
do: Map.put(body, :subject, subject)
defp prepare_content(body, %{html_body: html, text_body: text}) do
content =
Enum.reject(
[%{type: "text/plain", value: text}, %{type: "text/html", value: html}],
&is_nil(&1.value)
)
case content do
[] -> body
_ -> Map.put(body, :content, content)
end
end
defp prepare_attachments(body, %{attachments: []}), do: body
defp prepare_attachments(body, %{attachments: attachments}) do
attachments =
Enum.map(attachments, fn attachment ->
attachment_info = %{
filename: attachment.filename,
type: attachment.content_type,
content: Swoosh.Attachment.get_content(attachment, :base64)
}
extra =
case attachment.type do
:inline -> %{disposition: "inline", content_id: attachment.filename}
:attachment -> %{disposition: "attachment"}
end
Map.merge(attachment_info, extra)
end)
Map.put(body, :attachments, attachments)
end
defp prepare_reply_to(body, %{reply_to: nil}), do: body
defp prepare_reply_to(body, %{reply_to: reply_to}),
do: Map.put(body, :reply_to, reply_to |> email_item)
defp prepare_template_id(body, %{
provider_options: %{template_id: template_id}
}) do
Map.put(body, :template_id, template_id)
end
defp prepare_template_id(body, _email), do: body
defp prepare_categories(body, %{provider_options: %{categories: categories}}) do
Map.put(body, :categories, categories)
end
defp prepare_categories(body, _email), do: body
defp prepare_asm(body, %{provider_options: %{asm: asm}}) do
Map.put(body, :asm, asm)
end
defp prepare_asm(body, _email), do: body
defp prepare_custom_headers(body, %{headers: headers})
when map_size(headers) == 0,
do: body
defp prepare_custom_headers(body, %{headers: headers}) do
Map.put(body, :headers, headers)
end
defp prepare_mail_settings(body, %{
provider_options: %{mail_settings: mail_settings}
}) do
Map.put(body, :mail_settings, mail_settings)
end
defp prepare_mail_settings(body, _), do: body
end