Sending Emails using Sendgrid with Node.js

I’m gonna cover sending basic HTML emails using Sendgrid with Node.js in this posting. If you are interested in seeing it done in Node.js, I’ve created a Youtube video. If you are interested in doing it with PHP, I have a Youtube video it here and a Medium post here. If you are interested in doing it with Python, I have a Youtube video of it here and a Medium post in the future.

For this tutorial, you will need to have Node installed, and a Sendgrid account. I’m gonna use this MERN (Mongo, Express, React, Node) boilerplate code because it’s all pre-setup for new endpoints and you can learn more by watching this video.

Setup

First clone the MERN boilerplate code. Then navigate to it with terminal. Once you are in your working directory run:

npm install sendgrid --save
npm install async --save

This will install the Sendgrid library and the Async library.

Next, we need to properly setup the MERN boilerplate code. It requires a config.js in config/config.js . We will have to copy config.example.js to be config.js . The contents of the file will look like:

module.exports = {
db: 'mongodb://localhost:27017/your_db_name'
};

You will also have to install Mongo.

Lastly, you need to install all other Node modules so run:

npm install

After that is complete, you should be able to run:

npm run start:dev

And see a website at http://localhost:8080/

Sending an Email

We will next have to setup the endpoint to ping and send the email. This all happens in /server/routes/api . We are going to create a new file called email.js and that’s going to hold all email related endpoints. The contents will be as follows:

module.exports = (app) => {
app.post('/api/send', function (req, res, next) {
});
};

Add the following imports to the top of this file:

var helper = require('sendgrid').mail;
const async = require('async');

Then below the imports add the following function. This function handles sending the emails so all you have to do, is call the function to send an email, it’s much more clear and easier if your Sendgrid code needs to change.

function sendEmail(
parentCallback,
fromEmail,
toEmails,
subject,
textContent,
htmlContent
) {
const errorEmails = [];
const successfulEmails = [];
const sg = require('sendgrid') ('__YOUR_APIKEY_CREATED_ON_SENDGRID__'); async.parallel([
function(callback) {
// Add to emails
for (let i = 0; i < toEmails.length; i += 1) {
// Add from emails
const senderEmail = new helper.Email(fromEmail);
// Add to email
const toEmail = new helper.Email(toEmails[i]);
// HTML Content
const content = new helper.Content('text/html', htmlContent);
const mail = new helper.Mail(senderEmail, subject, toEmail, content); var request = sg.emptyRequest({
method: 'POST',
path: '/v3/mail/send',
body: mail.toJSON()
});
sg.API(request, function (error, response) {
console.log('SendGrid');
if (error) {
console.log('Error response received');
}
console.log(response.statusCode);
console.log(response.body);
console.log(response.headers);
});
}
// return
callback(null, true);
}
], function(err, results) {
console.log('Done');
});
parentCallback(null,
{
successfulEmails: successfulEmails,
errorEmails: errorEmails,
}
);
}

You will also need to generate an API Key. You can do this under Settings on the Sendgrid dashboard after logging in. Keep your API Key a secret.

Now you can make your endpoint call this send email function:

async.parallel([
function (callback) {
sendEmail(
callback,
'YOUR_FROM_EMAIL@example.com',
['YOUR_TO_EMAIL1@example.com', 'YOUR_TO_EMAIL2@example.com'],
'Subject Line',
'Text Content',
'<p style="font-size: 32px;">HTML Content</p>'
);
}
], function(err, results) {
res.send({
success: true,
message: 'Emails sent',
successfulEmails: results[0].successfulEmails,
errorEmails: results[0].errorEmails,
});
});

And you will have to change the from and to emails but if you run the server with npm run start:dev , open Postman and create a new POST request to http://localhost:8080/api/send . You should see this response:

{
"success": true,
"message": "Emails sent",
"successfulEmails": [],
"errorEmails": []
}

And in your email:

Image for post
Image for post

Done! Great job! Any questions, ask them below. Please check out my Youtube channel.

All code in email.js :

var helper = require('sendgrid').mail;
const async = require('async');
function sendEmail(
parentCallback,
fromEmail,
toEmails,
subject,
textContent,
htmlContent
) {
const errorEmails = [];
const successfulEmails = [];
const sg = require('sendgrid')('__YOUR_APIKEY_CREATED_ON_SENDGRID__');async.parallel([
function(callback) {
// Add to emails
for (let i = 0; i < toEmails.length; i += 1) {
// Add from emails
const senderEmail = new helper.Email(fromEmail);
// Add to email
const toEmail = new helper.Email(toEmails[i]);
// HTML Content
const content = new helper.Content('text/html', htmlContent);
const mail = new helper.Mail(senderEmail, subject, toEmail, content); var request = sg.emptyRequest({
method: 'POST',
path: '/v3/mail/send',
body: mail.toJSON()
});
sg.API(request, function (error, response) {
console.log('SendGrid');
if (error) {
console.log('Error response received');
}
console.log(response.statusCode);
console.log(response.body);
console.log(response.headers);
});
}
// return
callback(null, true);
}
], function(err, results) {
console.log('Done');
});
parentCallback(null,
{
successfulEmails: successfulEmails,
errorEmails: errorEmails,
}
);
}
module.exports = (app) => {
app.post('/api/send', function (req, res, next) {
async.parallel([
function (callback) {
sendEmail(
callback,
'FROM_EMAIL@example.com',
['TO_EMAIL@example.com'],
'Subject Line',
'Text Content',
'<p style="font-size: 32px;">HTML Content</p>'
);
}
], function(err, results) {
res.send({
success: true,
message: 'Emails sent',
successfulEmails: results[0].successfulEmails,
errorEmails: results[0].errorEmails,
});
});
});
};

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store