Stylesheet inlining and plain text template generation for your email templates.
Follow the installation instructions to set up Smoothie. After that we can use it in the following way in our project:
Let's suppose we are using the excellent Mailgun library to send our emails.
Then we set up a Mailer module in the following location: web/mailers/mailer.ex
, with the following content:
defmodule MyApp.Mailer do
# your mailgun config here
@config %{...}
use Mailgun.Client, @config
def welcome_email(user) do
send_email to: user.email_address,
from: "[email protected]",
subject: "Welcome!",
text: "Welcome #{user.name}"
:ok
end
end
Pretty boring right. So lets add smoothie. First we need a layout, lets try this one (save as: web/mailers/templates/layouts/main.html.eex
):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style type="text/css">
@media screen and (min-width: 581px) {
.container {
width: 580px !important;
}
}
</style>
</head>
<body>
<table class="body-wrap">
<tr>
<td class="container">
<table>
<tr>
<td align="center" class="masthead">
<h1><%= @title %></h1>
</td>
</tr>
<tr>
<td class="content">
{content}
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td class="container">
<table>
<tr>
<td class="content footer" align="center">
<p>Sent by <a href="http://www.acme.com">Acme</a></p>
<p><a href="mailto:[email protected]">[email protected]</a></p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
Also, lets add a stylesheet. We can use sass for this! save in web/mailers/templates/layout/style.scss
. If you just want to use css you can save it as style.css
.
$action-color: #50E3C2;
@media only screen and (min-device-width: 581px) {
.container {
width: 580px !important;
}
}
// Global
* {
margin: 0;
padding: 0;
font-size: 100%;
font-family: 'Avenir Next', "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif;
line-height: 1.65;
}
img {
max-width: 100%;
margin: 0 auto;
display: block;
}
body,
.body-wrap {
width: 100% !important;
height: 100%;
background: #efefef;
-webkit-font-smoothing:antialiased;
-webkit-text-size-adjust:none;
}
a {
color: $action-color;
text-decoration: none;
}
.text-center {
text-align: center;
}
.text-right {
text-align: right;
}
.text-left {
text-align: left;
}
// Button
.button {
display: inline-block;
color: white;
background: $action-color;
border: solid $action-color;
border-width: 10px 20px 8px;
font-weight: bold;
border-radius: 4px;
}
// Typography
h1, h2, h3, h4, h5, h6 {
margin-bottom: 20px;
line-height: 1.25;
}
h1 {
font-size: 32px;
}
h2 {
font-size: 28px;
}
h3 {
font-size: 24px;
}
h4 {
font-size: 20px;
}
h5 {
font-size: 16px;
}
p, ul, ol {
font-size: 16px;
font-weight: normal;
margin-bottom: 20px;
}
// layout
.container {
display: block !important;
clear: both !important;
margin: 0 auto !important;
max-width: 580px !important;
table {
width: 100% !important;
border-collapse: collapse;
}
.masthead {
padding: 80px 0;
background: #50E3C2;
color: white;
h1 {
margin: 0 auto !important;
max-width: 90%;
text-transform: uppercase;
}
}
.content {
background: white;
padding: 30px 35px;
&.footer {
background: none;
p {
margin-bottom: 0;
color: #888;
text-align: center;
font-size: 14px;
}
a {
color: #888;
text-decoration: none;
font-weight: bold;
}
}
}
}
Now create the template for our email, we can save this in web/mailers/templates/welcome.html.eex
Optionally adding additional css styling specific for this template partial is possible using <style> </style>
tags.
<style>
.inner-template{
font-size: 120%;
color: lightgreen;
}
</style>
<h2>Hi <%= @name %>,</h2>
<p class="inner-template">Welcome!</p>
<p>Cheers,</p>
<p><em>—The Acme</em></p>
Alright we're all set up, lets make sure this template works in Smoothie:
defmodule MyApp.Mailer do
# your mailgun config here
@config %{...}
use Mailgun.Client, @config
use Smoothie,
template_dir: "templates",
layout_file: Path.join("layouts", "main.html.eex")
def welcome_email(user) do
template_params = [
title: "Big Welcome!",
name: user.name,
]
send_email to: user.email_address,
from: "[email protected]",
subject: "Welcome!",
text: welcome_text(template_params),
html: welcome_html(template_params)
:ok
end
end
Additionally to enable smoothie compilation on this module we need to add the module to the configuration (config/config.exs
):
config :smoothie, modules: [MyApp.Mailer]
The last thing to do is to compile the templates, we need to do this every time when we change the templates or the layout:
> mix smoothie.compile
Preparing to compile the following template files:
- welcome.html.eex
Created welcome.html.eex
Created welcome.txt.eex
Done 🙏
Done! Now we are able to send very beautifully styled templates with styles inlined so it works in every email client, and for we also have a nice plain text version of the email!
Smoothie automatically generates txt.eex
templates from your html.eex
files. If you don't like them, you can provide your own txt.eex
templates by saving them to the same directory as your html.eex
files.
/build
/layout
welcome.html.eex
welcome.txt.eex
To skip generating text templates altogether, set :html_only
in your config,
config :smoothie, html_only: true
or run mix smoothie.compile --html-only
.
Smoothie can be installed as:
- Add
smoothie
to your list of dependencies inmix.exs
:
def deps do
[{:smoothie, "~> 3.0"}]
end
- Ensure
smoothie
is started before your application:
def application do
[applications: [:smoothie]]
end
- The only thing left is install the npm package that smoothie relies on in your project, we can do this with the following command:
> mix smoothie.init
Compile with layout
> mix smoothie.compile
Smoothie needs to install a npm library to do the css inlining, so make sure you have npm initialized in your project (a package.json
file in your project's root)
yarn install && mix test
- Create example usage repository (and link to README)