Packages
swoosh
1.0.6
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/mailer.ex
defmodule Swoosh.Mailer do
@moduledoc ~S"""
Defines a mailer.
A mailer is a wrapper around an adapter that makes it easy for you to swap the
adapter without having to change your code.
It is also responsible for doing some sanity checks before handing down the
email to the adapter.
When used, the mailer expects `:otp_app` as an option.
The `:otp_app` should point to an OTP application that has the mailer
configuration. For example, the mailer:
defmodule Sample.Mailer do
use Swoosh.Mailer, otp_app: :sample
end
Could be configured with:
config :sample, Sample.Mailer,
adapter: Swoosh.Adapters.Sendgrid,
api_key: "SG.x.x"
Most of the configuration that goes into the config is specific to the adapter,
so check the adapter's documentation for more information.
Per module configuration is also supported, it has priority over mix configs:
defmodule Sample.Mailer do
use Swoosh.Mailer, otp_app: :sample,
adapter: Swoosh.Adapters.Sendgrid,
api_key: "SG.x.x"
end
System environment variables can be specified with `{:system, "ENV_VAR_NAME"}`:
config :sample, Sample.Mailer,
adapter: Swoosh.Adapters.SMTP,
relay: "smtp.sendgrid.net"
username: {:system, "SMTP_USERNAME"},
password: {:system, "SMTP_PASSWORD"},
tls: :always
## Examples
Once configured you can use your mailer like this:
# in an IEx console
iex> email = new |> from("tony.stark@example.com") |> to("steve.rogers@example.com")
%Swoosh.Email{from: {"", "tony.stark@example.com"}, ...}
iex> Mailer.deliver(email)
:ok
You can also pass an extra config argument to `deliver/2` that will be merged
with your Mailer's config:
# in an IEx console
iex> email = new |> from("tony.stark@example.com") |> to("steve.rogers@example.com")
%Swoosh.Email{from: {"", "tony.stark@example.com"}, ...}
iex> Mailer.deliver(email, domain: "jarvis.com")
:ok
"""
alias Swoosh.DeliveryError
defmacro __using__(opts) do
quote bind_quoted: [opts: opts] do
alias Swoosh.Mailer
@otp_app Keyword.fetch!(opts, :otp_app)
@mailer_config opts
@spec deliver(Swoosh.Email.t(), Keyword.t()) :: {:ok, term} | {:error, term}
def deliver(email, config \\ [])
def deliver(email, config) do
Mailer.deliver(email, parse_config(config))
end
@spec deliver!(Swoosh.Email.t(), Keyword.t()) :: term | no_return
def deliver!(email, config \\ [])
def deliver!(email, config) do
case deliver(email, config) do
{:ok, result} -> result
{:error, reason} -> raise DeliveryError, reason: reason
end
end
@spec deliver_many(list(%Swoosh.Email{}), Keyword.t()) :: {:ok, term} | {:error, term}
def deliver_many(emails, config \\ [])
def deliver_many(emails, config) do
Mailer.deliver_many(emails, parse_config(config))
end
@on_load :validate_dependency
@doc false
def validate_dependency do
adapter = Keyword.get(parse_config([]), :adapter)
Mailer.validate_dependency(adapter)
end
defp parse_config(config) do
Mailer.parse_config(@otp_app, __MODULE__, @mailer_config, config)
end
end
end
def deliver(%Swoosh.Email{from: nil}, _config) do
{:error, :from_not_set}
end
def deliver(%Swoosh.Email{from: {_name, address}}, _config)
when address in ["", nil] do
{:error, :from_not_set}
end
def deliver(%Swoosh.Email{} = email, config) do
adapter = Keyword.fetch!(config, :adapter)
:ok = adapter.validate_config(config)
adapter.deliver(email, config)
end
def deliver_many(emails, config) do
adapter = Keyword.fetch!(config, :adapter)
:ok = adapter.validate_config(config)
adapter.deliver_many(emails, config)
end
@doc """
Parse configs in the following order, later ones taking priority:
1. mix configs
2. compiled configs in Mailer module
3. dynamic configs passed into the function
4. system envs
"""
def parse_config(otp_app, mailer, mailer_config, dynamic_config) do
Application.get_env(otp_app, mailer, [])
|> Keyword.merge(mailer_config)
|> Keyword.merge(dynamic_config)
|> Swoosh.Mailer.interpolate_env_vars()
end
@doc """
Interpolate system environment variables in the configuration.
This function will transform all the {:system, "ENV_VAR"} tuples into their
respective values grabbed from the process environment.
"""
def interpolate_env_vars(config) do
Enum.map(config, fn
{key, {:system, env_var}} -> {key, System.get_env(env_var)}
{key, value} -> {key, value}
end)
end
@doc false
def validate_dependency(adapter) do
require Logger
with adapter when not is_nil(adapter) <- adapter,
{:module, _} <- Code.ensure_loaded(adapter),
true <- function_exported?(adapter, :validate_dependency, 0),
:ok <- adapter.validate_dependency() do
:ok
else
no_match when no_match in [nil, false] ->
:ok
{:error, :nofile} ->
Logger.error("#{adapter} does not exist")
:abort
{:error, deps} when is_list(deps) ->
Logger.error(Swoosh.Mailer.missing_deps_message(adapter, deps))
:abort
end
end
@doc false
def missing_deps_message(adapter, deps) do
deps =
deps
|> Enum.map(fn
{lib, module} -> "#{module} from #{inspect(lib)}"
{module} -> inspect(module)
end)
|> Enum.map(&"\n- #{&1}")
"""
The following dependencies are required to use #{inspect(adapter)}:
#{deps}
"""
end
end