How to send emails from Phoenix using Elixir and Mandrill.
Sending out emails using Mandrill is great for both sides of your team. Your designers/marketing team can build out an email using Mailchimp’s great UI designer. You can send out emails by just replacing merge_vars.
It’s a win-win!
Here’s how you can send out emails from your Phoenix Elixir application.
First let’s install the bamboo package from thoughtbot. Add the package and whichever version is latest to your mix.exs file.
{:bamboo, "~> 0.8"}
Install it.
mix deps.get
Now we need to create a .env file so you can safely set your Mandrill API key without saving it to your git repository.
Inside of your .env
file, paste this in:
export MANDRILL_API_KEY=mykeygoeshere
Make sure you source the .env
file in your terminal window so when you run mix phx.server
your project picks up the env var properly.
source .env
Finally, let’s configure bamboo to use this environment variable API key.
config :my_app, MyApp.Mailer,
adapter: Bamboo.MandrillAdapter,
api_key: System.get_env("MANDRILL_API_KEY")
Create a base mailer.
This mailer module is going to be in charge of actually sending out the emails, but it’s very small. Create a file called mailer.ex
somewhere in your /lib
folder.
defmodule MyApp.Mailer do
use Bamboo.Mailer, otp_app: :my_app
end
And you’re done. Let’s try sending out an email now.
Sending out an email.
Sending an email is very easy, succinct and testable. We’ll create a simple email that sends out a confirmation code given a user. Module can be anything, but in this example I’m using Phoenix 1.3 and contexts to organize my code.
defmodule MyApp.User.Onboarding.Email do
import Bamboo.Email
import Bamboo.MandrillHelper
def confirmation_code_email(user) do
new_email()
|> template("My Mandrill Template Name")
|> to(user.email)
|> from("hello@myapp.com")
|> subject("Here's your confirmation code")
|> put_param("global_merge_vars", [
%{
"name": "confirmationCode",
"content": user.confirmation_code
}
])
|> MyApp.Mailer.deliver_later
end
end
Notice how we’re using the previously created MyApp.Mailer
module at the end there.
That’s all there is to it, you’re sending emails now!
Unit Testing Phoenix Framework emails
How do we test these emails though? It’s really simple and Bamboo comes with testing support out of the box.
First let’s setup the MyApp.Mailer
module to use a different adapter when in test mode. Inside test.exs, let’s do this:
config :my_app, MyApp.Mailer,
adapter: Bamboo.TestAdapter
And our test:
defmodule MyApp.User.Onboarding.EmailTest do
use ExUnit.Case, async: true
use Bamboo.Test
import MyApp.Factory
describe "Example email test" do
test "sends an email confirmation code" do
user = insert(:user, %{email: "abc@email.com", confirmation_code: "123123"})
email = MyApp.User.Onboarding.Email.confirmation_code_email(user)
assert_delivered_email(email)
end
end
end
The assert_delivered_email
function is part of the Bamboo.Test
module, that’s why we’re bringing it into our test up top.
I hope this helps you out in sending emails from a Phoenix Framework application. The Bamboo package is really top-tier and made handling emails really nice. Be sure to leave them a star on the repo:
Thanks!