Packages
swoosh
1.16.11
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.
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/swoosh/adapters/mailjet.ex
defmodule Swoosh.Adapters.Mailjet do
@moduledoc ~S"""
An adapter that sends email using the Mailjet API.
For reference: [Mailjet API docs](https://dev.mailjet.com/guides/#send-api-v3-1)
**This adapter requires an API Client.** Swoosh comes with Hackney, Finch and Req out of the box.
See the [installation section](https://hexdocs.pm/swoosh/Swoosh.html#module-installation)
for details.
> ### Dependency {: .info}
>
> Mailjet adapter requires `Plug` to work properly.
## Example
# config/config.exs
config :sample, Sample.Mailer,
adapter: Swoosh.Adapters.Mailjet,
api_key: "my-api-key",
secret: "my-secret-key"
# lib/sample/mailer.ex
defmodule Sample.Mailer do
use Swoosh.Mailer, otp_app: :sample
end
## Using with provider options
import Swoosh.Email
new()
|> from({"Billi Wang", "billi_wang@example.com"})
|> to({"Nai Nai", "nainai@example.com"})
|> reply_to("a24@example.com")
|> cc({"Haiyan Wang", "haiyan_wang@example.com"})
|> cc("lujian@example.com")
|> bcc({"Hao Hao", "haohao@example.com"})
|> bcc("aiko@example.com")
|> subject("Hello, Nai Nai!")
|> html_body("<h1>Hello</h1>")
|> text_body("Hello")
|> put_provider_option(:template_id, 123)
|> put_provider_option(:template_error_deliver, true)
|> put_provider_option(:template_error_reporting, "developer@example.com")
|> put_provider_option(:variables, %{firstname: "lulu", lastname: "wang"})
## Provider options
* `:template_id` (integer) - `TemplateID`, unique template id of the
template to be used as email content
* `:template_error_deliver` (boolean) - `TemplateErrorDeliver`,
send even if error in template if `true`, otherwise stop email delivery
immediately upon error
* `:template_error_reporting` (string | tuple | map) - `TemplateErrorReporting`,
email address or a tuple of name and email address of a recipient to send a
carbon copy upon error
* `:variables` (map) - `Variables`, custom key-value variable for the email
content
"""
use Swoosh.Adapter,
required_config: [:api_key, :secret],
required_deps: [plug: Plug.Conn.Query]
alias Swoosh.{Email, Attachment}
@base_url "https://api.mailjet.com/v3.1"
@api_endpoint "send"
def deliver(%Email{} = email, config \\ []) do
send_request(:single, prepare_body(email), email, config)
end
def deliver_many(emails, config \\ [])
def deliver_many([], _config) do
{:ok, []}
end
def deliver_many(emails, config) when is_list(emails) do
send_request(:many, prepare_body(emails), emails, config)
end
defp send_request(type, body, email_or_emails, config) do
email = email_or_emails |> List.wrap() |> List.first()
headers = prepare_headers(config)
url = [base_url(config), "/", @api_endpoint]
case Swoosh.ApiClient.post(url, headers, body, email) do
{:ok, 200, _headers, body} ->
{:ok, parse_results(type, body)}
{:ok, error_code, _headers, body} when error_code >= 400 ->
{:error, {error_code, parse_results(type, body)}}
{:error, reason} ->
{:error, reason}
end
end
defp parse_results(type, %{"Messages" => results}) do
results =
Enum.map(results, fn
%{"Status" => "success"} = result -> get_message_id(result)
per_message_error -> per_message_error
end)
case {type, results} do
{:single, [single]} -> single
{:many, list} -> list
end
end
defp parse_results(type, body) when is_binary(body) do
parse_results(type, Swoosh.json_library().decode!(body))
end
defp parse_results(_type, global_error) do
global_error
end
defp get_message_id(%{"To" => [%{"MessageID" => message_id}]}) do
%{id: message_id}
end
defp get_message_id(%{"To" => multiple_receivers}) do
%{
id:
Enum.map(
multiple_receivers,
fn %{"MessageID" => message_id} ->
message_id
end
)
}
end
defp base_url(config), do: config[:base_url] || @base_url
defp prepare_headers(config) do
[
{"User-Agent", "swoosh/#{Swoosh.version()}"},
{"Authorization", "Basic #{auth(config)}"},
{"Content-Type", "application/json"}
]
end
defp auth(config), do: Base.encode64("#{config[:api_key]}:#{config[:secret]}")
defp prepare_body(emails) do
emails
|> List.wrap()
|> Enum.map(&prepare_message/1)
|> wrap_messages()
|> Swoosh.json_library().encode!()
end
defp prepare_message(email) do
%{}
|> prepare_from(email)
|> prepare_to(email)
|> prepare_subject(email)
|> prepare_html(email)
|> prepare_text(email)
|> prepare_cc(email)
|> prepare_bcc(email)
|> prepare_reply_to(email)
|> prepare_attachments(email)
|> prepare_variables(email)
|> prepare_template(email)
|> prepare_custom_headers(email)
|> prepare_custom_id(email)
end
defp wrap_messages(body) when is_list(body), do: %{Messages: body}
defp prepare_custom_id(body, %{provider_options: %{custom_id: custom_id}}),
do: Map.put(body, "CustomID", custom_id)
defp prepare_custom_id(body, _options), do: body
defp prepare_custom_headers(body, %{headers: headers}),
do: Map.put(body, "Headers", headers)
defp prepare_attachments(body, %{attachments: []}), do: body
defp prepare_attachments(body, %{attachments: attachments}) do
{normal_attachments, inline_attachments} =
Enum.split_with(attachments, fn %{type: type} -> type == :attachment end)
body
|> Map.put(
"Attachments",
Enum.map(normal_attachments, &prepare_attachment/1)
)
|> Map.put(
"InlinedAttachments",
Enum.map(inline_attachments, &prepare_attachment/1)
)
end
defp prepare_attachment(attachment) do
%{
"ContentType" => attachment.content_type,
"Filename" => attachment.filename,
"Base64Content" => Attachment.get_content(attachment, :base64),
"ContentId" => attachment.cid || attachment.filename
}
end
defp prepare_recipients(recipients),
do: Enum.map(recipients, &prepare_recipient(&1))
defp prepare_recipient({name, address}),
do: %{"Name" => name, "Email" => address}
defp prepare_from(body, %{from: from}),
do: Map.put(body, "From", prepare_recipient(from))
defp prepare_to(body, %{to: to}),
do: Map.put(body, "To", prepare_recipients(to))
defp prepare_reply_to(body, %{reply_to: nil}), do: body
defp prepare_reply_to(body, %{reply_to: reply_to}),
do: Map.put(body, "ReplyTo", prepare_recipient(reply_to))
defp prepare_cc(body, %{cc: []}), do: body
defp prepare_cc(body, %{cc: cc}),
do: Map.put(body, "Cc", prepare_recipients(cc))
defp prepare_bcc(body, %{bcc: []}), do: body
defp prepare_bcc(body, %{bcc: bcc}),
do: Map.put(body, "Bcc", prepare_recipients(bcc))
defp prepare_subject(body, %{subject: subject}),
do: Map.put(body, "Subject", subject)
defp prepare_text(body, %{text_body: nil}), do: body
defp prepare_text(body, %{text_body: text_body}),
do: Map.put(body, "TextPart", text_body)
defp prepare_html(body, %{html_body: nil}), do: body
defp prepare_html(body, %{html_body: html_body}),
do: Map.put(body, "HTMLPart", html_body)
defp prepare_variables(body, %{provider_options: %{variables: variables}}) do
Map.put(body, "Variables", variables)
end
defp prepare_variables(body, _email), do: body
defp prepare_template(body, %{
provider_options: %{template_id: template_id} = provider_options
}) do
body =
body
|> Map.put("TemplateID", template_id)
|> Map.put("TemplateLanguage", true)
|> Map.put(
"TemplateErrorDeliver",
!!provider_options[:template_error_deliver]
)
case provider_options[:template_error_reporting] do
nil ->
body
{name, email} when is_binary(name) and is_binary(email) ->
Map.put(body, "TemplateErrorReporting", %{
"Email" => email,
"Name" => name
})
email when is_binary(email) ->
Map.put(body, "TemplateErrorReporting", %{
"Email" => email,
"Name" => ""
})
map when is_map(map) ->
Map.put(body, "TemplateErrorReporting", map)
end
end
defp prepare_template(body, _email), do: body
end