Send Emails In A NativeScript App Via The Rackspace Mailgun API

I get this question a lot, not necessarily for NativeScript, but for other mobile frameworks.  The question is, how do you send emails from within your Android and iOS application without launching one of the already installed mail apps?  In other words how do you send emails via a custom form within the application or in the background?

A solution to this question would be to use a backend web server that can send mail and create an API endpoint to it that can be accessed from your mobile app.  However, this solution takes work and other resources.  Instead you can make use of a transactional email service.

There are many of these email services available, but for this example we’re going to look at using the Mailgun service by Rackspace in a NativeScript application.

Let me start by saying that Mailgun has a free tier that in many cases is more than enough.  The free tier can accomplish everything I need.  You’ll also need to create an account to use Mailgun.

With a Mailgun account established we can now create a new NativeScript application.  From the Command Prompt (Windows) or Terminal (Mac and Linux), execute the following commands:

A few things to note here.  First off, we’re going to be using TypeScript instead of JavaScript, hence the --template tsc flag.  Second, if you’re not using a Mac then you cannot add and build for the iOS platform.

We’re going to work with three different files in this project.  We’re going to manipulate the app/main-view-model.ts file to handle our data bindings with the font-end.  We’re going to modify the app/main-page.ts file to make use of the new class name in our view model.  Finally we’re going to manipulate the app/main-page.xml file to contain an email form.

Let’s start with the view model first.  I’ll break it down in a moment, but open app/main-view-model.ts and add the following code:

The above file is where all the magic happens.

The first thing to notice that didn’t already exist in the file is the importing of the http module.  This is so we can make POST requests against the Mailgun API.  Going deeper, we’ve changed the class name to something that makes a little more sense.  This time we’re calling it MailgunModel.

Now let’s take a look at our five private class variables:

Our email application will only have three fields to it.  What really matters is the _url and _api variables.  The _url is either going to be the Mailgun sandbox URL assigned to you for testing, or the domain you registered with Mailgun.  The _api variable is going to be a base64 encoded username and password string.  The username and password are as follows:

  • username: api
  • password: key-THE-KEY-ASSIGNED-TO-YOU

It is important that your API key is prefixed with key-.  I made the mistake of not including it and was banging my head for some time.

Remember you need the base64 version of this.  In a typical JavaScript setting you would run a command like this:

The problem is that NativeScript doesn’t use window.  You’ll have to rig together your own base64 encoding function or just encode it externally and plug it in.  It doesn’t change so generating externally is fine.

Every form variable will have its own getter and setter methods.  For each of the setters you’re essentially checking if the value has changed and issue a change notification to the observable if it has.

Most of the magic happens in the send() method as seen here:

We’re using the http module that we imported to create a POST request.  The URL was taken from the Mailgun documentation with our domain url slipped in.  We’re using basic authorization with the base64 encoded credentials and we’re sending form data.  The Mailgun API does not accept JSON data unfortunately so we have to create a massive string out of it.

With the view model out of the way we can update the app/main-page.ts file with the new class name.  Open the file and add the following code:

Nothing really changed except the renaming of the class.

Finally we can take a look at the UI file that contains our email form.  It is going to be very simplistic, but open app/main-page.xml and include the following code:

Above is a StackLayout with three input fields and a send button.  There is a two-way bind happening here.  In each of the text properties there is a reference to a variable in our app/main-view-model.ts file.  These variables will be updated when something changes in either direction, whether that be from the front-end or the back-end logic.

At this point you should be good to go.  Try sending an email and see what happens!

Conclusion

Many applications need email features lately.  Maybe you want to create a feedback form within your application, but you don’t want the default mail app to open.  Or maybe you want to send crash logs to an email address without even prompting the user.  Making use of a transactional email service is a great solution to this and Mailgun by Rackspace is a perfect example.

Nic Raboy

Nic is a skilled application developer who has released several native and hybrid mobile applications to iTunes and Google Play. He writes about his development experiences related to making web and mobile app development easier to understand and has experience in Android, Node.js, Apache Cordova, Java, NoSQL, SQL, GoLang, NativeScript, and Unity3D.

  • Gumball

    Hi, I’ve been following your posts and I’ve been learning more here than the docs of nativescript + angular, typescript version. Thank you for doing this!
    I’ve been looking for a btoa function replacement to incorporate it on my app, and you mentioned nativescript doesn’t support ‘window’. I looked around and it doesn’t seem no solution is readily available for tns. I saw on tns docs that it supports native api and its globally declared so I guess calling android.util.Base64.encode is possible, the problem is java and android packages gives error when using on tns.

    • Should work out, but if you start using native features to do the encoding, make sure you do it in iOS as well, otherwise you’ll only have Android support.

      What do your errors say?

      • Gumball

        I’m currently cleaning up my brew and npm, it got messed up somehow, so I won’t be able to run it after I reinstalled everything but IIRC calling ‘android’ or ‘java’ packages returns undefined. I can’t also find where those two globals are declared. It seems they are not included as global defaults, I may be wrong on this.