Serverless email notifications with Sendgrid

Serverless email notifications with Sendgrid

Email notifications have become an integral part of our systems. Common use cases include sending reports, notifying build success, system failure events, etc. This tutorial demonstrates a solution using Google Cloud Functions to send emails using Sendgrid.

Goals

  • Scalable

  • Ease of content modification

  • Reliable delivery

A sender will provide the trigger a cloud function with params. The cloud function will make a call to Sendgrid which in turn will send emails to the receiver.

Alt Text

System

Setting up a Sendgrid account

You can Sign up for a Sendgrid Account to manage our details. It offers a generous free plan which is enough for our demo. Choose the create single sender option, in case you want to use your own domain the instructions can be found here.

Sender Identity Type

Sender Identity Type

Creating a sender

Creating a sender

You’ll receive an email for sender confirmation as configured, click on Verify Single Sender.

Sender Verification

Sender Verification

Obtaining an API key

Sending emails via APIs is the recommended way for apps rather than SMTP. So, we’ll use the Web APIs which will be called by the SDKs. Let’s get the API Key for our account.

Choosing the Integration type

Choosing the Integration type

Choosing the language

Choosing the language

Obtain the API Key

Library function for Sendgrid

Let’s create a library that will enable us to send emails via Sendgrid. This way our code is decoupled and can be used by a simple library import.

Install the Sendgrid SDK via npm.

# install sendgrid dependency
npm install --save @sendgrid/mail

Now let’s write a library that abstracts the SDK calls of Sendgrid.

function getMessage(to, from, subject, text, html) {
    return {
        to: to, //'test@example.com'
        from: from, //'test@example.com',
        subject: subject, //'Sending with SendGrid is Fun',
        text: text, //'and easy to do anywhere, even with Node.js',
        html: html //'<strong>and easy to do anywhere, even with Node.js</strong>',
    }
}

module.exports = {
    sgMail: null,
    init: function (apiKey) {
        this.sgMail = require('@sendgrid/mail');
        this.sgMail.setApiKey(apiKey); // set the api-key
    },
    sendEmail: async function (to, from, subject, text, html) {
        const sendgridMessage = getMessage(to, from, subject, text, html);
        const response = await this.sgMail
            .send(sendgridMessage)
            .then(() => {
                console.log('Email sent');
                return { status: 200 };
            })
            .catch((error) => {
                console.error(error);
                return { status: 500, err: error };
            });
        return response;
    }
}

Let’s test the lib code with our API Key.

let sendgridLib = require('../lib/sendgrid');

const API_KEY = '<YOUR-API-KEY>';

sendgridLib.init(API_KEY);
const resp = sendgridLib.sendEmail('smit.thakkar1@gmail.com',
    'thefellowcoder@gmail.com',
    'Test Email',
    'Sample text',
    '<p>yep, it works!<p>'
);
resp.then(data => console.log(data)); //should print { status: 200 }

Great! now we have a working library code, let’s use it in our cloud function.

Cloud function

Let’s create a simple cloud function that uses this library and sends an email.

let sendgridLib = require('../lib/sendgrid');

const API_KEY = process.env.API_KEY;

exports.sendgridCF = async (req, res) => {
    //console.log(JSON.parse(req));
    sendgridLib.init(API_KEY);
    const resp = await sendgridLib.sendEmail('smit.thakkar1@gmail.com',
        'thefellowcoder@gmail.com',
        'Test Email',
        'Sample text',
        '<p>yep, it works!<p>'
    );
    console.log(resp);
    if (resp.status == 200) {
        res.send(`<h1>Email sent successfully</h1>`);
    }
    else {
        console.error(resp.err);
        res.send(`<h1>Failed to send message</h1>`);
    }

};

Here, we have configured the API Key as an env variable, thus we need to make sure that it is available at runtime. Make sure that the lib code is also part of the deployment, else it will throw an error.

Sample command to deploy the cloud function

gcloud functions deploy sendgridDemo --trigger-http --entry-point=sendgridCF \
--region=us-central1 --runtime=nodejs10 --set-env-vars API_KEY='123'

Once deployed make sure to change the env variable value with the actual Sendgrid API Key.

Updating env variable

Updating env variable

Testing

Visit the Cloud Function’s Testing tab to test the function. Just click on ‘TEST THE FUNCTION’ to trigger the function.

Testing the cloud function

Testing the cloud function

Now let’s verify in our mailbox. Sometimes the email appears in spam, so be sure to check there if not received.

Inbox

You may wonder why is ‘Sample Text’ not visible. It seems that ‘text’ is a fallback in the event the email client does not support HTML emails.

Thus we can send emails programmatically in a serverless way. Note that because we worked in a library structure, we can extend this and have a similar setup for AWS Lambda.

All the code samples can be found in our git repository.

Hope you found this tutorial helpful.

Let me know your thoughts in the comment section below.

Did you find this article valuable?

Support Smit Thakkar by becoming a sponsor. Any amount is appreciated!