Send Emails In Ionic Framework Via The Rackspace Mailgun API

A few years ago a wrote a tutorial for sending emails in an Ionic Framework Android and iOS application.  The tutorial works great, but it requires that a mail application be used to finalize the send.  In other words, you can set default values for email fields, but you still need to select Gmail or similar to actually send the email.

A popular question I receive is how to send emails without launching an email application.  There are a few solutions to this.  You could either set up your own server that sends emails and access it via an API, or you can use a service like Rackspace’s Mailgun.

We’re going to see how to send emails using the Rackspace Mailgun API service.

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 Ionic Framework application. From the Command Prompt (Windows) or Terminal (Mac and Linux), execute the following commands:

A few things to note in the above commands.  First, we are creating an Ionic Framework app, not an Ionic 2 app, hence the --v1 tag.  The Ionic CLI should default to Ionic Framework if you don’t specify the tag.  Second, if you’re not using a Mac then you cannot add and build for iOS.

Building the AngularJS Application Logic

We’re going to start by creating our application logic.  Open the project’s www/js/app.js file and include the following source code:

There is a lot happening in the above file, particularly in the MailgunController, so let’s break it down.

To send emails with Mailgun you need to know your configured domain and the API key for that domain.  For demonstration purposes I’m just using the sandbox domain, but you might be using something different.  The API expects that the API key is base64 encoded.  Since Ionic Framework is just a web application, we can use the window.btoa function to do this.

Now for where the main magic happens, the send function.

The Mailgun API expects a POST request that contains form data, not JSON data.  We can define this requirement in the headers section of the request.  In the headers section we also need to pass in the base64 encoded authorization token.

Finally we have the request content.  Again this is not JSON, so it must be serialized form data.  I just demonstrated the basics when it comes to content, but you could include multiple recipients, as well as a cc or bcc field.

Our application logic is now complete.  Now we can have a look at the UI of the application.

Creating a Relevant Application User Interface

The application now needs a nice UI for sending emails.  Instead of dealing with the AngularJS UI-Router, we’re going to just create this form in the www/index.html file.  It will keep things simple for us.

Open the www/index.html file and include the following code:

Most of this file was provided to us in the blank template, so I’m going to point out what we’re working with.

Because the application contacts remote web services we need to add a whitelist in the head tags:

More can be seen on the topic of whitelisting in my previous post on the subject.

Now we can look at the form we’re creating in this page:

We attach the MailgunController that we created in the AngularJS file and add three form input fields.  By using ng-model the fields are bound to the controller.

The button will call the controller send function when clicked, passing in the fields from the form.

Conclusion

If you don’t want to force your users to send emails via one of the installed mailing applications, you don’t have to.  An example use case would be if you want to create your own custom email form or if you want to send crash logs without prompting the user.  Using a service like the Rackspace Mailgun API this becomes possible, while being essentially free.

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.

  • Ayr

    Hi Nic! Thanks for the tutorial! Just one question: will this code work if the app was created with Ionic Creator?

  • Sri Ram

    Hi Nic, Thanks for this awesome tutorial. But i have one doubt how to send image using mailgun. thanks in advance

    • Sharan Dhanala

      Maybe this is a issue with the scope of formData. Mind sharing the snippet. 🙂

  • Hi Nic,

    I’m trying your tutorial and is doesn’t work. I’m getting an error saying it’s being blocked from the server mailgun because the token is not present in the channel CORS Header… and then I get this:

    ERROR {“data”:null,”status”:-1,”config”:{“method”:”POST”,”transformRequest”:[null],”transformResponse”:[null],”url”:”https://api.mailgun.net/v3/sandboxea4a59d2053545feac3d9a4cf065645d.mailgun.org/messages”,”headers”:{“Content-Type”:”application/x-www-form-urlencoded”,”Authorization”:”Basic YXBpOmI2OWY2YmMwY2YwMzJiYjI0N2M2MzFiNGRjODQ3NjAx”,”Accept”:”application/json, text/plain, /“},”data”:”[email protected]&[email protected]&subject=prueba mailgun&text=probando”},”statusText”:””}
    app.js:47:13

    Is there anything missing in the code (I’ve copied every line of code from you and inserted my api key)?

    Note: I’m trying this with Ionic Serve

    • You should not use Ionic Serve. CORS will not happen correctly with Ionic Serve like it would as a compiled app.

      • Hi Nic,

        after struggling a bit with genyomotion and ADB, I’ve finally been able to emulate the code but I still get an error. This is the log:

        I/Web Console( 1107): ERROR {“data”:”Forbidden”,”status”:401,”config”:{“method”:”POST”,”transformRequest”:[null],”transformResponse”:[null],”url”:”https://api.mailgun.net/v3/sandboxea4a59d2053545feac3d9a4cf065645d.mailgun.org/messages”,”headers”:{“Content-Type”:”application/x-www-form-urlencoded”,”Authorization”:”Basic YXBpOmI2OWY2YmMwY2YwMzJiYjI0N2M2MzFiNGRjODQ3NjAx”,”Accept”:”application/json, text/plain, /“},”data”:”[email protected]&[email protected]&subject=erty&text=qw?”},”statusText”:”UNAUTHORIZED”} at file:///android_asset/www/js/app.js:47

        Any idea with what is wrong?

        Thanks a lot for you help
        Abel

  • Faiz Ansari

    how to send email with attachments. attach a text file from sdcard external location.

  • Ujjwal

    Inline Images aren’t working. So, can you please guide me through a bit? I tried many but none seem to work.

    • You’d have to read the Mailgun API documentation on how to correctly send images in your messages.

      • Ujjwal

        Thanks. I will keep trying. Apparently, I couldn’t get it right yet though I have followed documentation and done some hit and trial. Couldn’t be sure what am I missing.

  • Kasim Sheyi

    hey Nic, I want the user of my app to fill their email as the sender of the email, so i added an input field into d html with ng-model as sender and in the app.js i replace the “from=” + sender but i get error message saying sender is not defined. Please how do i resolve this. Thanks so much

    • The ‘from’ is a required field. If you’re not sending it, the API request will fail. My guess is you’ll need to re evaluate how you’re binding to the form.

  • Sharan Dhanala

    Would you please give me an example of multi part content type? I am trying to send a large form submitted from ionic app over email and the data seems to be cutting off at some point.

  • Anderson Rocha

    Awesome tutorial man it helped a lot. I got an error message that is not allowing me send the email:
    (index):1 XMLHttpRequest cannot load https://api.mailgun.net/v3/sandboxa2cadf6c4a2d4fc9b025c0255dbb4ff3.mailgun.org/messages. Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.

    • Are you trying to use Ionic Serve or any of the reloading features? Your error is related to cross origin resource sharing (CORS) which doesn’t exist when apps are compiled and installed to the device. It will however exist if you’re trying to test in the browser or with any of the features I mentioned.

      Best,

  • Especimen

    This feature works in Ionic 2?

  • rubson lima

    I made this implementation and the console appears (SUCCESS). But the message does not arrive. I need some help with that.