Mail delivery for Elixir
Courier is built and maintained by DockYard, contact us for expert Elixir and Phoenix consulting.
Courier is an OTP adapter-based mail delivery system for Elixir applications. It means serious business for sending emails.
It depends upon Mail
for composing the message.
First create your mailer:
defmodule MyApp.Mailer do
use Courier, otp_app: :my_app
end
After this we need to add the Courier Supervisor to your tree. For
example, if you are using in a Phoenix app you can edit lib/my_app.ex
def start(_type, _args) do
children = [
supervisor(MyApp.Repo, []),
supervisor(MyApp.Endpoint, []),
# Mailer Supervisor
supervisor(MyApp.Mailer, [])
]
end
Next set the default adapter in config/config.exs
or config/{environment}.exs
:
config :my_app, MyApp.Mailer,
adapter: Courier.Adapters.SMTP,
relay: "smtp.myserver.com",
hostname: "my-mail-server",
port: 2525,
username: System.get_env("COURIER_USERNAME"),
password: System.get_env("COURIER_PASSWORD")
More configuration options for each adapter is in the Adapters section.
Then you can compose and deliver the message:
Mail.build_multipart()
|> Mail.put_to("friend@example.com")
|> Mail.put_from("me@example.com")
|> Mail.put_subject("How are things?")
|> Mail.put_text("Let's meet for drinks!")
|> Mail.put_html("<p>Let's meet for drinks!</p>")
|> MyApp.Mailer.deliver()
Courier will deliver the message through the adapter that is configured.
All deliveries are pushed into a shceduler and sent out asynchronously. Let's learn how to customize this scheduler
By default if you do not specify a datetime to delivery at
Courier
will mark the message for immediate delivery. But let's say we want to
schedule a specific datetime to send a message. You can do that with:
MyApp.Mailer.deliver(message, at: datetime)
The datetime
variable should conform to either an Erlang calendar
tuple {{year, month, day}, {hour, minute, second}}
Courier will use a pool to rate limit the number of concurrent messages
being sent. This is necessary if you are sending to services that hate
their own rate limits. The default pool size is 10
. If you'd like to
change this default you can simply modify when configuring your mailer:
config :my_app, MyApp.Mailer,
pool_size: 15
Read more about the Scheduler, configuring it, and using it.
If you'd like to render the text
or html
parts with a Phoenix view
you should use Courier.render/4
Mail.build_multipart()
|> Mail.put_to("friend@example.com")
|> Mail.put_from("me@example.com")
|> Mail.put_subject("How are things?")
|> Courier.render(MyApp.MailerView, "check_in.txt", user: user)
|> Courier.render(MyApp.MailerView, "check_in.html", user: user)
|> MyApp.Mailer.deliver()
Courier.render/4
will parse the template path to determine the
expected content-type
. For example, if your template is foobar.html
the assumed content-type
is text/html
and Courier will render the
template to a string and use Mail.put_html(message, rendered_template)
Courier comes with some built-in adapters
The built-in SMTP adapter is implemented with gen_smtp
Options:
relay
mail server hostport
mail server port (defaults to25
whenssl
isfalse
, defaults to465
whenssl
istrue
)ssl
connect with SSL (defaults tofalse
)hostname
label for therelay
username
username used for authenticationpassword
password used for authentication
Will write deliver all messages to the Logger
. All attachment encoded data will
render as [File content]
Options:
level
theLogger
level to send the message to (defaults to:info
)
Exposes the ETS adapter from a REST based API
CourierWeb adds a web interface for viewing the messages sent. To use it
add the library to your mix.exs
file. For more information on this adapter please refer to
CourierWeb
Creating your own adapter is simple. The only functions necessary are
start_link/1
and deliver/2
defmodule MyApp.Adapters.Custom do
def start_link(_opts), do: :ignore
def deliver(%Mail.Message{} = message, opts) do
# your customized mailer
end
end
The message
passed into deliver/2
is not a rendered RFC2822 message.
If you need the rendered version you can use mail
to render it:
rendered_message = Mail.render(message, Mail.Renderers.RFC2822)
Please refer to the mail
library to learn more about creating custom
message renderers.
Each adapter is treated as its own OTP supervisor within your mailer's
supervisor tree. This will give you the opportunity to create more
complex adapters with their own workers. Just override
start_link/1
however you'd like. The configuration options declared
for your mailer within the given mix environment are passed in as the
argument.
We are very thankful for the many contributors
This library follows Semantic Versioning
At DockYard we are ready to help you build your next Elixir project. We have a unique expertise in Elixir and Phoenix development that is unmatched. Get in touch!
At DockYard we love Elixir! You can read our Elixir blog posts or come visit us at The Boston Elixir Meetup that we organize.
Please do! We are always looking to improve this library. Please see our Contribution Guidelines on how to properly submit issues and pull requests.
DockYard, Inc. © 2016