Using Bamboo to Send Emails in Phoenix

Using Bamboo to Send Emails in Phoenix

Hey people! I’m back with another article based on my Phoenix learning.

So to get to the point - in any application, one of the most important processes is sending emails to users. We are going to use the Bamboo library which supports all the major email providers and we can also use the HTML template for the email content.

Here we will see the following:

  1. Setting up Bamboo
  2. Sending users a welcome email once they sign up
  3. Using HTML to compose an email

Ok, let’s get into this now. My main goal for this post is to have my app send a welcome email to the new signups. The app is a status management app that lets us know the current working status of fellow employees.

Setting up Bamboo:

We’ll get started by adding the Bamboo dependency to our project’s mix.exs file. Add bamboo to the deps and application function.

mix.exs
def application do
[mod: {WorkStatus.Application, []},
applications: [... :bamboo]]
end
defp deps do
[...
{:bamboo, "~> 1.5"}
]
end

Now, let us install the dependencies by using the command

Terminal window
$ mix deps.get

Let’s now define the “Mailer”, which is in charge of sending the email. We will create a mailer module in the “lib/workstatus (lib/:application)” named “mailer.ex”. Later on in this module, we will define a deliver function that will be responsible for delivering the email.

lib/workstatus/mailer.ex
defmodule Workstatus.Mailer do
use Bamboo.Mailer, otp_app: :workstatus
end

Now let us configure our development environment to use the Bamboo.LocalAdapter. In the dev.exs, add the following,

config/dev.exs
config :workstatus, Workstatus.Mailer,
adapter: Bamboo.LocalAdapter

Bamboo.LocalAdapter allows us to view the sent emails in the development with the Bamboo.EmailPreviewPlug. To configure this, let us add the “/sent_emails” route and forward it to the Bamboo.SentEmailViewerPlug. Let’s add this in our “routes.ex”.

lib/workstatus_web/router.ex
if Mix.env == :dev do
forward "/sent_emails", Bamboo.SentEmailViewerPlug
end

This wraps up the setup required for the Bamboo. Now, let’s fire up our Phoenix server. If you get into any errors, please check the above steps once again.

Terminal window
$ mix phoenix.server

Adding the Mailer Functionality

Bamboo separates the delivery and the composition of the mail. The delivery will be performed by the Mailer module. Let’s create an Email module that will perform the composition.

Create a file called “email.ex” in the same directory of our Mailer module. We will import Bamboo.Email here, from which we will use the new_email function to compose our email.

Now, let’s create a function for welcoming users.

lib/workstatus/email.ex
defmodule Workstatus.Email do
import Bamboo.Email
def welcome_mail(user) do
new_email(
to: user.email,
subject: "Welcome to WorkStatus!",
text_body: "Welcome to the WorkStatus!"
)
end
end

For now let us, leave it with the text body. Later on in this post, we will see how to use the html template to compose the email.

Now, let us add this in the users_controller where the sign_up is handled. To send the email, we will use the deliver function in the Bamboo library which will be imported in the Mailer module. Import both the Mailer and Email in the controller.

lib/workstatus_web/contorollers/auth_contoroller.ex
def signup(%{assigns: %{ueberauth_auth: auth}}:conn, params) do
user_params:%{token: auth.credentials.token, email: auth.info.email, provider: "github"}
changeset:User.changeset(%User{}, user_params)
{:ok, user}:sign_in(conn, changeset)
Email.welcome_mail(user)
|> Mailer.deliver_later()
end

Now, once the user sign_up for the app, the welcome email will be sent. We can see the email that has been sent in the routes we defined earlier in the development environment.

We can see the sent_email as in the above screenshot. Next, let us see how we can use the HTML to compose the email.

Using HTML to compose email:

With HTML we can compose the email in a more elegant way. First, let’s create a view for our emails. Create a file “email_view.ex” in the views folder.

workstatus_web/views/email_view.ex
defmodule Workstatus.EmailView do
use WorkstatusWeb, :view
end

Now let’s create the templates we need. Let’s start by creating our new email layout. Create a new “email.html.eex” in the layouts folder.

workstatus_web/templates/layouts/email.html.eex
<html>
<head>
<link rel="stylesheet" href="<%= static_url(Workstatus.Endpoint,
"/css/style.css") %>">
</head>
<body>
<div class="container">
<%= render @view_module, @view_template, assigns %>
</div>
</body>
</html>

Then we will create the template for our welcome_mail. Create a template in the templates/email folder called welcome_mail.html.eex

workstatus_web/templates/email/welcome_mail.html.eex
<p>Hi, <%= @user.name %></p>
<img src="/images/phoenix.png" alt="Phoenix Framework Logo" />

Let’s update our mailer function to render the created template. The updated welcome_mail function looks like.

lib/workstatus/email.ex
defmodule Workstatus.Email do
use Bamboo.Phoenix, view: Workstatus.EmailView
import Bamboo.Email
def welcome_mailer(user) do
new_email
|> from("[email protected]")
|> to(user.email)
|> subject("Welcome to WorkStatus!!")
|> assign(:user, user)
|> render("welcome_mail.html")
end
end

Now the sent email looks like this,

This is a basic implementation of sending emails in Phoenix using Bamboo. This post is intended to be used as a Get Started guide. There are many more extensions and detailed explanations available in the Bamboo Docs .