I have been looking for a straight forward way to use email templates in a contact form. I have searched and searched with no real success. So, I thought I would write a tutorial on how to build a (very!) simple contact page that uses an email template. This uses Express, Nodemailer and node-email-templates.
Basic File Structure
├── app
├── css
└── main.css
├── templates
└── contact-request
├── html.hbs
├── style.css
└── text.hbs
└── index.html
├── package.json
└── server.js
We will start out by adding Handlebars, express and email-templates:
npm init
Feel free to fill in the information or press enter until it is complete. I have my entry-point
set as server.js
.
npm install -S express email-templates handlebars
This will install those packages and add them to our dependencies in the package.json
file.
Basic Styling and Markup
<!-- app/index.html -->
<body>
<div class="alert"></div>
<input type="text" id="name" name="name" placeholder="Name" />
<input type="email" name="email" id="email" placeholder="Email" />
<textarea
name="message"
id="message"
cols="30"
rows="10"
placeholder="Enter your message."
></textarea>
<button id="send-contact" type="submit">Send</button>
</body>
/* app/css/main.css */
* {
box-sizing: border-box;
}
body {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding-top: 50px;
background-color: #ccc;
}
input {
margin-bottom: 20px;
width: 300px;
height: 25px;
font-size: 16px;
color: #3e3e3e;
}
textarea {
font-size: 16px;
width: 300px;
margin-bottom: 20px;
color: #3e3e3e;
}
button {
padding: 15px 25px;
font-size: 16px;
cursor: pointer;
color: #3e3e3e;
}
button:hover {
background-color: #3e3e3e;
color: #fefefe;
}
.alert {
display: flex;
align-items: center;
justify-content: center;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
color: #fff;
margin: 20px;
padding: 15px;
border-radius: 5px;
}
.error {
background-color: #c43c35;
background-repeat: repeat-x;
background-image: linear-gradient(top, #ee5f5b, #c43c35);
border-color: #c43c35 #c43c35 #882a25;
}
.success {
background-color: #57a957;
background-repeat: repeat-x;
background-image: linear-gradient(top, #62c462, #57a957);
border-color: #57a957 #57a957 #3d773d;
}
Setting up Express
Since we are using express, it’s pretty simple to get our server going. You can follow the getting started and hello world quick tutorials. Below is what our base server.js
file will currently look like.
// server.js
var express = require("express");
var app = express();
app.use(express.static("app"));
var server = app.listen(8080, function () {
var host = "localhost";
var port = server.address().port;
console.log("Example app listening at http://%s:%s", host, port);
});
Now you should be able to view the index.html
contact page in your browser (http://localhost:8080
) by typing node server.js
in your terminal.
Setting up Nodemailer
So we are using Nodemailer to help us send our emails. In order to use the package, we will need to add it to our dependencies and install it:
npm install -S [email protected]
To get a better understanding of Nodemailer, I would encourage you to read through the documentation as I will just highlight the basics to get our simple contact page up and running. We will use the basic example given by Nodemailer in our project.
// server.js
var express = require("express");
var app = express();
var nodemailer = require("nodemailer");
app.use(express.static("app"));
// nodemailer
var smtpTransport = nodemailer.createTransport("SMTP", {
service: "Gmail",
auth: {
user: "[email protected]",
pass: "password",
},
});
var mailOptions = {
from: "Fred Foo <[email protected]>", // Sender Address
to: "[email protected]",
subject: "Contact Request", // Subject Line
text: "Hello World!", // Plaintext Body
html: "<b>Hello Word! </b>", // HTML Body
};
smtpTransport.sendMail(mailOptions, function (error, response) {
if (error) {
console.log(error);
} else {
console.log("Message sent: " + response.message);
}
});
var server = app.listen(8080, function () {
var host = "localhost";
var port = server.address().port;
console.log("Example app listening at http://%s:%s", host, port);
});
Now when you startup your server, node server.js
, you should receive an email (assuming you added your email address and password to the user:
and pass:
respectively.
Now that we know it works, we need to wrap mailOptions
and smtpTransport.sendMail
with a get()
method so we don’t get an email every time we start up our app.
// server.js
var express = require("express");
var app = express();
var nodemailer = require("nodemailer");
app.use(express.static("app"));
// nodemailer
var smtpTransport = nodemailer.createTransport("SMTP", {
service: "Gmail",
auth: {
user: "[email protected]",
pass: "password",
},
});
app.get("/sendContact", function (req, res) {
var mailOptions = {
from: "Fred Foo <[email protected]>", // Sender Address
to: "[email protected]",
subject: "Contact Request", // Subject Line
text: "Hello World!", // Plaintext Body
html: "<b>Hello Word! </b>", // HTML Body
};
smtpTransport.sendMail(mailOptions, function (error, response) {
if (error) {
console.log(error);
} else {
console.log("Message sent: " + response.message);
}
});
});
var server = app.listen(8080, function () {
var host = "localhost";
var port = server.address().port;
console.log("Example app listening at http://%s:%s", host, port);
});
Using the Form Data
Next we will want to use our form to capture the data the user will input. For simplicity, I’ll add jQuery to our project and add another file called main.js
to app/scripts/main.js
. I’ll add jQuery by inserting it at the bottom of the <body>
inside the index.html
with <script src=“https://code.jquery.com/jquery-2.1.4.min.js”\>
</script>
along with <script src=“scripts/main.js”>
</script>
just below it. Next we’ll create the main.js
file.
// app/scripts/main.js
$("#send-contact").click(function (evt) {
evt.preventDefault();
var name = $("#name").val();
var email = $("#email").val();
var message = $("#message").val();
if (name !== "" && email !== "" && message != "") {
$.get(
"http://localhost:8080/sendContact",
{
name: name,
email: email,
message: message,
},
function (data) {
if (data == "sent") {
$(".alert")
.html("<strong>Success! </strong> Your message has been sent!")
.addClass("success");
} else {
$(".alert")
.html(
"<strong>Uh oh! </strong> It looks like that didn't go through, let's try that again."
)
.addClass("error");
}
}
);
}
});
Add the Email Templates to Server.js
We will now add node-email-templates to our server.js file. For completeness, I have added the entire server.js file:
var express = require("express");
var app = express();
var nodemailer = require("nodemailer");
var path = require("path");
var EmailTemplate = require("email-templates").EmailTemplate;
var templatesDir = path.resolve(__dirname, "app/templates");
app.use(express.static("app"));
// nodemailer
var smtpTransport = nodemailer.createTransport("SMTP", {
service: "Gmail",
auth: {
user: "[email protected]",
pass: "password",
},
});
app.get("/sendContact", function (req, res) {
var template = new EmailTemplate(path.join(templatesDir, "contact-request"));
var locals = {
email: req.query.email,
name: req.query.name,
message: req.query.message,
};
template.render(locals, function (err, results) {
if (err) {
return console.error(err);
}
smtpTransport.sendMail(
{
from: locals.email,
to: "[email protected]",
subject: "Contact Request",
html: results.html,
text: results.text,
},
function (err, responseStatus) {
if (err) {
console.error(err);
res.end("error");
} else {
console.log(responseStatus.message);
res.end("sent");
}
}
);
});
});
var server = app.listen(8080, function () {
var host = "localhost";
var port = server.address().port;
console.log("Example app listening at http://%s:%s", host, port);
});
Email Templates
Our emails should now be sending, but in order to test them, we will need to add our templates. Unfortunately, with node-email-templates, there isn’t a way for us to easily style the templates without sending an email to ourselves. But to help shorten this tutorial, I’ll add some styling to our templates so we can test our email and wrap this tutorial up.
We will need to add an html.hbs
and text.hbs
to our templates/contact-request
directory. We have the text.hbs
for better support.
<!-- app/templates/contact-request/html.hbs -->
<div class="container">
<h3 class="center">Contact Request</h3>
<p class="center">
{{ name }} has filled out the contact form on your website with the
following message:
</p>
<blockquote>
<p>{{ message }}</p>
</blockquote>
<p class="center small">
To respond to {{ name }}, you may reply directly to this email or send an
email to {{ email }}.
</p>
</div>
<!-- app/templates/contact-request/text.hbs -->
Contact Request {{ name }} has filled out the contact form on your website with
the following message: {{ message }} To respond to {{ name }}, you may reply
directly to this email or send an email to {{ email }}.
* {
box-sizing: border-box;
}
.container {
border: 1px solid #e5e3d8;
padding: 20px;
border-radius: 5px;
}
h3,
p {
color: #808284;
font-family: sans-serif;
line-height: 1.5em;
}
h3 {
font-size: 16px;
}
p {
font-size: 15px;
}
blockquote {
background: #f9f9f9;
border-left: 10px solid #ccc;
margin: 1.5em 10px;
padding: 0.5em 10px;
}
blockquote p {
display: inline;
}
.center {
text-align: center;
}
.small {
font-size: 10;
}
This should give us a nice template to use as a starting point. There is still plenty of work that needs to be done (form validation for starters), but this concludes this tutorial. You should have a working contact form with a nicely styled template. There are other options out there like Swig that allow us to view the changes to the template in a browser. I hope to have a tutorial of that up soon.
As always, feedback is welcome and if you run into any problems or have any questions, let me know in the comments below and I will try my best to help you out. I have added the code used in this tutorial to github in case anyone wanted to play around with it or use it as a starting point.