Sign up for a Parse account to implement this tutorial and more!

Sign Up

Icon_third_party_cloud_code
Integrating with Third-Party Services

This tutorial will show you how you can build your very own Cloud Code module and integrate with third-party APIs. We'll take an in-depth tour of the Mailgun Cloud Module and see how you can apply the same techniques to create your own.

Cloud Code
Cloud Module
module
JavaScript
third-party
Mailgun

Download code for this tutorial:

GitHub

Integrating third-party services in your Parse app is really easy using Cloud Modules. But if a Cloud Module is not yet available for a service you are interested in, you can create your own module. In this tutorial, we'll take a look at how you would create your own module, using the Mailgun Cloud Module as an example. If you are not familiar with Mailgun, take a look at their website to learn more about what they offer. The Mailgun feature most relevant to this tutorial is the ability to send emails.

Before we begin, remember that Cloud Modules are no different than the modules you create yourself. They've simply been made readily available to all Parse users and don't need to be manually added to your cloud/ folder.

1. Creating Modules

JavaScript has long lacked the ability organize code into multiple files. To solve this problem, the CommonJS modules standard was created. Along with many JavaScript libraries and services, Cloud Code uses this standard to allow creating more modular JavaScript projects.

1.1. Loading Files with require

All of the JavaScript modules you want to use in Cloud Code must be placed in the cloud/ directory. To include a module in your project you can use the require("/path/to/module") method.

var myModule = require('cloud/myModule.js');

To include a Cloud Module (a module hosted by Parse and made available to everyone), you can simply provide its name and Parse will take care of the rest.

var Mailgun = require('mailgun');

1.2. The exports Object

The require function returns an object automatically created in all modules called exports. When you create a module you use this exports object to define the set of functionality that will be available to users of your module. Take a look at this simple example.

// myMathModule.js
exports.addTwoNumbers = function(x, y) {
    return x+y;
}
    
// cloud.js
var math = require('cloud/myMathModule.js');
console.log('3 + 4 is ' + math.addTwoNumbers(3,4));

You don't need to declare or create the exports object anywhere. It is always available when creating modules. All fields and functions added to the exports object are handed down by the require function. This means that anything not set on the exports object remains private to the module. In the following example, the value of PI is not directly accessible from cloud.js.

// myMathModule.js
var PI = 3.14; // Private
exports.getPI() { // Public
    return PI;
}

// cloud.js
var math = require('cloud/myMathModule.js');
console.log(math.PI);      // Doesn't work!
console.log(math.getPI()); // Works!

2. Implementing the Mailgun Module

Now that we have a good understanding of modules, let's dive into the Mailgun Cloud Module and take a look at how to implement something similar. Our module won't be hosted by Parse and will instead be placed in the cloud/ directory.

2.1. The initialize method

The first part of the module is the initialize method. Since most services will require users to provide credentials, creating an initialize method is a great way to centralize the location where these are set.

var url = 'api.mailgun.net/v2';
var domain = '';
var key = '';

module.exports = {
  initialize: function(domainName, apiKey) {
    domain = domainName;
    key = apiKey;
    return this;
  },
  ...
}

The module starts by declaring three private properties. When the initialize method is called, the credentials are stored in the private variables. Along with the credentials, we've also stored the api's url in a private property. When the Mailgun API is updated, we will only need to change the url here instead of everywhere in the module.

It would be possible to pass the credentials with each function that uses the Mailgun API. But, by using an initialize method, the users of the module only need to set their credentials once like this:

// cloud.js

// Initialize Your Module
var client = require('cloud/myMailModule-1.0.0.js');
client.initialize('myDomainName', 'myAPIKey');

// All my Cloud Code functions can use the Mailgun module
Parse.Cloud.beforeSave...
Parse.Cloud.define...
...

2.2. Sending an Email

The main use of our module is to send emails. The function used to do this is remarkably simple, but requires some understanding of the Mailgun API, Parse HTTP requests and general HTTP networking concepts. Let's start by looking at the code.

module.exports = {
  ...
  sendEmail: function(params, options) {
    return Parse.Cloud.httpRequest({
      method: "POST",
      url: "https://api:" + key + "@" + url + "/" + domain + "/messages",
      body: params,
    }).then(function(httpResponse) {
      if (options && options.success) {
        options.success(httpResponse);
      }
    }, function(httpResponse) {
      if (options && options.error) {
        options.error(httpResponse);
      }
    });
  }
}

This function simply calls Parse.Cloud.httpRequest with the appropriate parameters. As discussed in the Cloud Code docs, the httpRequest function allows you to send a request to an external web server. This is the key to integrating with third-party services as it allows us to communicate with other APIs.

To determine the values for the method, url and body parameters, we need to take a look at Mailgun's API reference documentation. From this page we can find out that sending an email requires doing a POST request to the URL https://api.mailgun.net/v2/{DomainName}/messages. But how do we provide our Mailgun credential? Well, the majority of web APIs support basic HTTP authentication. This means we can add the credentials to the URL in the following format.

https://api:apikey@api.url.here

In the case of Mailgun, if we combine the URL and the credential we get:

https://api:{ApiKey}@api.mailgun.net/v2/{DomainName}/messages

So the value of method needs to be POST and the value of url should be the address shown above. As you can see from the function's code (repeated below for convenience), the value of body is simply set to the params variable which is supplied to the sendEmail function.

module.exports = {
  ...
  sendEmail: function(params, options) {
    return Parse.Cloud.httpRequest({
      method: "POST",
      url: "https://api:" + key + "@" + url + "/" + domain + "/messages",
      body: params,
    }).then(function(httpResponse) {
      if (options && options.success) {
        options.success(httpResponse);
      }
    }, function(httpResponse) {
      if (options && options.error) {
        options.error(httpResponse);
      }
    });
  }
}

There are a variety of parameters that third party services will accept in the body of their requests, and these are subject to change at any time. Instead of hard coding a list of accepted parameters, our module lets the user provide a list of them and then relays them to Mailgun. This makes the module easier to update in the future and allows the module's API to be much more flexible. In the case of sending an email with Mailgun, the list of accepted body parameters can be found in their API reference documentation.

The success and error parameters are two callback functions that are provided to the sendEmail function through the options parameters. The httpRequest method returns a Promise. The promise's then method invokes the appropriate success or error callback based on whether the promise is resolved or rejected.

Let's see what a call to the sendEmail method looks like.

// First we initialize our module
var client = require('cloud/myMailModule-1.0.0.js');
client.initialize('myDomainName', 'myAPIKey');

// Then we create a cloud function
Parse.Cloud.define("sendEmailToUser", function(request, response) {
  client.sendEmail({
    to: "email@example.com",
    from: "MyMail@CloudCode.com",
    subject: "Hello from Parse!",
    text: "Using Parse and My Mail Module is great!"
  }).then(function(httpResponse) {
    response.success("Email sent!");
  }, function(httpResponse) {
    console.error(httpResponse);
    response.error("Uh oh, something went wrong");
  });
});

In the example above, a Cloud Function named sendEmailToUser is defined that calls the sendEmail module method, passing in the parameters needed to send out an email. The success and error cases are echoed back to the user in the response.

2.3. Versioning

Versioning the module helps developers know which version they're currently running. While this is not a requirement, it's a good practice. We've named our module file myMailModule-1.0.0.js to indicate that this is version 1.0.0. Additionally, let's add a property to our module that provides versioning information.

module.exports = {
  ...
  version: '1.0.0',
  ...

This makes the version information accessible via code. The example below shows a modified sendEmailToUser Cloud Function that includes the version in the text of the email sent out.

// Modify the message sent to include the version
Parse.Cloud.define("sendEmailToUser", function(request, response) {
  client.sendEmail({
    to: "email@example.com",
    from: "MyMail@CloudCode.com",
    subject: "Hello from Parse!",
    text: "Using Parse and My Mail Module version " + client.version + " is great!"
  }).then(function(httpResponse) {
    response.success("Email sent!");
  }, function(httpResponse) {
    console.error(httpResponse);
    response.error("Uh oh, something went wrong");
  });
});

And that's all there is to know about creating modules for Cloud Code! Make sure to take a look at the

If you have any questions or comments, send us an email at feedback@parse.com.