Support Ukraine 🇺🇦Help Ukrainian ArmyHumanitarian Assistance to Ukrainians

How to mock SendGrid during development?

Laverage

Jan 08 2022 at 15:06 GMT

I want to use SendGrid to send emails in my app.

However, I do not want to use my production SendGrid account during local development.

Is there a way to mock SendGrid locally so that every message that I send is not actually sent but stored locally and at the same time easily viewable maybe in a web UI?

Also, for my integration tests it would be great if I can access all the sent messages through a REST API and at the same time have the ability to clear all sent messages after each test.

1 Answer

Mike The Programmer

Jan 08 2022 at 15:59 GMT

One way to mock SendGrid locally is to use Docker.

There are several SendGrid mock images available on Docker Hub, such as ghashange/sendgrid-mock.

Here's how you can run it locally using docker run:

docker run -p 7000:3000 -e "API_KEY=mock-api-key" ghashange/sendgrid-mock:1.7.2

Or if you prefer docker-compose:

version: '3.9'

services:
  sendgrid:
    image: ghashange/sendgrid-mock:1.7.2
    ports:
      - '7000:3000'
    environment:
      - API_KEY=${SENDGRID_API_KEY}

You can use anything as your API key since the mock doesn't case. However, I suggest to start it with SG. to not receive warnings from the SendGrid client (e.g., "SG.secret").

Once you have the mocked SendGrid service running locally, it will be accessible on localhost on the specified port, in our example we chose 7000.

So, you can instruct the SendGrid client to use the http://localhost:7000 endpoint when in development.

The specific code to configure the SendGrid client depends on the programming language that you're using.

So, if you're using the @sendgrid/mail client for NodeJS, you would do the following when in development:

const sgClient = require('@sendgrid/client');
const sgMail = require('@sendgrid/mail');

sgClient.setApiKey(mockApiKey);
sgClient.setDefaultRequest('baseUrl', 'http://localhost:7000');
sgMail.setClient(sgClient);

Note that you additionally need to install @sendgrid/client if you haven't already.

So, a possible setup could look like this:

const sgClient = require('@sendgrid/client');
const sgMail = require('@sendgrid/mail');

if (inDevelopment) {
  sgClient.setApiKey(mockApiKey);
  sgClient.setDefaultRequest('baseUrl', 'http://localhost:7000');
  sgMail.setClient(sgClient);
} else {
  sgMail.setApiKey(apiKey)
}

With all this in place, you can see the email messages sent by your application in development by opening http://localhost:7000 in your web browser.

Note that this particular Docker image stores the sent email messages in memory and deletes them after 24 hours. Although you can configure after how long the messages are deleted using the MAIL_HISTORY_DURATION environment variable, if you restart the Docker container all the sent messages will be deleted since they are kept in memory.

As far as integration tests are concerned, you can access all the sent messages by issuing a GET request to http://localhost:7000/api/mails.

To clear all sent messages, you can issue a DELETE request to http://localhost:7000/api/mails.

claritician © 2022