Resilient e-mail sending in Meteor with Superface.ai
Tags: meteor, email, superfaceai
Published: 2021-09-30 20:09:51

Meteor 2.4 brought with it new feature version of the `email` package. v2.2 of `email` package added a function, `Email.customTransport`, that can override e-mail sending from Meteor app with the way you want it. This allows us to build resilient e-mail sending. Normally this would include a lot of logic and API calls to handle, but no longer! We have an elegant solution with Superface.ai

Superface is a start-up with a goal to simplify API integration and one of the solutions they came up with is target/source resiliency. This means that if one API end-point is dead it will automatically switch automatically to your backup one that you have configured without you needing to add any extra lines of code. You can read more details about this on their [page](https://www.superface.ai/solutions/resilient-email) or in [their dev.to post about e-mail sending resiliency](https://dev.to/superface/don-t-get-burned-by-email-6c4).

Here I'm going to show you how to combine Meteor's `Email.customTransport` with Superface.ai to make resilient e-mail sending for you Meteor app.

## Pre-requisits
As a pre-requisits you will need to be on at least Meteor 2.4 and have configured two e-mail sending services to send from. In my case it is Mailgun and Sendgrid.

## Prepare Superface.ai
[Let's get started with Superface.ai!](https://superface.ai/getting-started) We start with adding their `one-sdk` to our project:

```sh
meteor npm install @superfaceai/one-sdk
```

Next, we add the `send-email` capability:

```sh
npx @superfaceai/cli install communication/send-email -i
```

Now you just follow the setup to select your primary and secondary e-mail services and add their keys. In case you want to add them manually later on you can use the following commands:

```sh
npx @superfaceai/cli configure mailgun --profile=communication/send-email
npx @superfaceai/cli configure sendgrid --profile=communication/send-email
```

Now you will notice two new things in your project directory. First you have a new directory called `superface`. In it you will find all the superface settings, most notably in `super.json` and you can manually edit them if you know what you are doing.

Second is `.env` file has been either created or has new entries from the interactive setup. You can edit them if you need to.

## Meteor code

Now that we have Superface all setup, it is time to plug it into our Meteor code. On your server go to the file where you are handling e-mail related stuff (or create a new file or add it to index.js in your server folder).

First things first, we need to import Meteor, our email packages and `one-sdk` from Superface:
```javascript
import { Meteor } from 'meteor/meteor'
import { Email } from 'meteor/email'
import { SuperfaceClient } from '@superfaceai/one-sdk'
```

Now let's create our Superface send function:
```javascript
/**
 * Function to send e-mails via Superface
 * @type {object} data E-mail data from Email.customTransport
 * @returns {string} e-mail id
 */
const superfaceSendEmail = async (data) => {
  // Instanciate Superface client
  const superfaceClient = new SuperfaceClient()
  // Let's get the send email profile 
  const profile = await superfaceClient.getProfile('communication/send-email')
  // Perform the action
  const result = await profile.getUseCase('SendEmail').perform(data)
  // Get the result
  return result.unwrap()
}
```

Meteor can be a bit iffy with async functions like this, so we better wrap it in `Meteor.wrapAsync` like this:
```javascript
const superfaceSendEmail = Meteor.wrapAsync(async (data) => {
  const superfaceClient = new SuperfaceClient()
  try {
    const profile = await superfaceClient.getProfile('communication/send-email')
    const result = await profile.getUseCase('SendEmail').perform(data)
    return result.unwrap()
  } catch(e) {
    console.error(e)
  }
})
```

Now we just need to hook it up to the e-mail package and we are all set:
```javascript
Email.customTransport = (data) => {
  superfaceSendEmail(data)
}
```

## Profit?
Not quiet there yet. Since Superface expects that its settings will be available in the default location, it will get a nasty surprise when you run Meteor. Meteor builds separately for server and client and strange folders like `superface` in the root is not something that it will touch. So to get it on the server you will need to copy (or better, create create a symbolic link) in your `private` folder. This will then put the `superface` folder on the server under assets (`assets/app/superface/`). Now all that remains is to tell via env variable Superface where it should look for its settings:

```
SUPERFACE_PATH=assets/app/superface/super.json
```

> Note, you can setup `dotenv` package to get all this data from .env file that you place into your private folder. Install the `dotenv` package and then at the start of your server run: `require('dotenv').config({ path: 'assets/app/.env' })`
> For Galaxy deployment you can put all your variables in Meteor settings under `"galaxy.meteor.com".env` in your Meteor settings.

Now, with all of that set you can enjoy Superface with Meteor!

--------
If you like my work, please support me on [GitHub Sponsors ❤️](https://github.com/sponsors/StorytellerCZ).