See the follow up to this post here: Using Mandrill with the Node API and an Angular Client

The rise of Angular has coincided with the increasing popularity of the ‘thin web client’ that uses distributed systems for basically all your traditional backend needs. Services like Divshot and the cheap boxes at Digital Ocean make for some unique opportunities to deliver your static resources, such as a JavaScript application, easily and cheaply but still quickly. They still leave you, however, with the need to deliver basic functions such as database and email delivery.

For email, I have become a big fan of Mandrill. It’s a great transactional email service for sending and receiving the basic sort of emails that any good web application would expect to be able to do. In addition, it’s built by the same team that did MailChimp, and if you are familiar with that service you know how strong their service, analytics, and infrastructure really are.

So without much more introduction, I thought I’d share a couple of insights about using the Mandrill JSON API from within an Angular application.

#0 – Setup a Mandrill Account, API keys

For all the things I love about Mandrill, I can still get a little turned around when setting everything up inside my Mandrill account.

Once logged in, click on ‘Settings’ in the lefthand sidebar. Once in ‘Settings’, go to ‘Domains’ to setup your ‘Sending Domain’. You do not have to do anything more than ‘Add’ a domain in the account. Once you have done that much, you are good to go. For production, you probably should add the SPF/DKIM records to ensure delivery. I also strongly recommend verifying the domain while you are setting everything up. They make it pretty easy, it prevents anyone else from using your domain, so really – why wouldn’t you? Look over your ‘Sending Defaults.’ These are specific to your needs, so I won’t get into what you should and shouldn’t do here. Go back to ‘API Info’ and create a new API Key. There are a handful of security measures available. Use them as you like. Take note of your API Key, for later.

#1 – Establish Your Design Pattern

There are clearly a lot of ways to skin the cat when it comes to how, when, and where to use Mandrill inside of an Angular app. A classic example, though, could be sending an email at sign up.

So let’s say that you have a form in your view. Using ng-click on the sign up button, you can execute a function in your corresponding controller.

<form role="form"> ...inputs collecting User data... <button ng-click="createUser(User)">Sign Me Up!</button> </form>

Inside of that controller, you might inject a Profile factory, that will create the user profile, and a Mandrill factory, that will interact with Mandrill.

angular.module('YourAngularApp') .controller('PersonCreateCtrl', ['$http', '$scope', '$location', 'Profile', 'Mandrill', function ($http, $scope, $location, Profile, Mandrill) { $scope.createUser = function() { var thisProfile = { // get your profile data from User }; var promise = Profile.makeProfile(thisProfile); promise.then(function(resp) { if(resp.code === 'EMAIL_TAKEN'){ $scope.thisErrorMessage = 'That email is already registered.'; } else if(resp.$id) { $scope.thisErrorMessage = 'Your account has been created. Please log in.'; $location.path('/person/view/' + resp.$id).search('new', '1'); } else { $scope.thisErrorMessage = 'There has been an error.'; Mandrill.errorMsg(resp).then(function(data) { if(data.data[0].status === 'sent') { $scope.thisErrorMessage += ' The error has been sent to dev team and we\'ll get it fixed. Please try again.'; } else { $scope.thisErrorMessage += ' This message was not sent to the dev team for an unknown reason. Please try again.'; } }); } }); }; }]);

This particular design doesn’t do a ton other than wait and listen for the ng-click, which in turn sends the submitted user data to your Profile factory as a Promise. The specifics of Promise methods or account/user creation are outside the scope of this post, but suffice it to say your Profile factory will return different response codes depending on the result – if the account was created, and if it wasn’t, if that was for a normal reason or not. If the reason was for something considered odd, it will immediately alert the dev team via an email sent through your Mandrill factory (which, you guessed it, uses Mandrill).

Like I said before, your own needs will determine how exactly everything gets organized, so just treat this as a really basic use case to establish some sort of context.

#2 – Setup Your Mandrill Factory

Before I really get into anything, let me first share a sample factory pattern using the Mandrill JSON API.

.factory('Mandrill', ['$http', 'KEYS', function($http, KEYS) { /*=======================*/ /* Insert Emails Here /*=======================*/ var fromEmail = 'email'; var fromName = 'email_name'; var toEmail = 'email'; var toName = 'email_name'; var replyTo = 'email'; return { errorMsg: function(resp) { return $http.post('https://mandrillapp.com/api/1.0//messages/send.json', { 'key': KEYS.mandrill, 'message': { 'html': '<p>Unknown Error Message</p><p>' + resp + '</p><p>Error Code:' + resp.code + '</p>', 'text': resp, 'subject': 'Unknown Error Message', 'from_email': fromEmail, 'from_name': fromName, 'to': [ { 'email': toEmail, 'name': toName, 'type': 'to' } ], 'headers': { 'Reply-To': replyTo } } }) .success(function(data, status, headers, config){ // log success }); } }; }]);

The documentation for the JSON API is not too difficult to read through on your own. These are the basics that you will need to get started, but I have left plenty of options for you to dig into – all the way down to google_analytics_campaign integrations, attachments, and background async that can handle bulk sends. Even templates can be set up, and those can use the either handlebar.js syntax or the MailChimp ‘mergetag’ syntax.

#3 – Expanding on the Basic Design

As you get more complex in your Mandrill use, you will probably also find a need to rethink your initial design. The Factory paradigm from above works fine up to a point, but you will probably begin to see a lot of repeated code if you strictly follow it over and over again. A slight but thoughtful rework would probably be warranted.

.factory('Mandrill', ['$http', 'KEYS', var messagePost = { key: mandrillkey, message: { from_email: 'email', from_name: 'email_name', headers: { Reply-To: 'email' } } }; var htmlHeader = "// standard logo, date, etc"; var htmlFooter = "// standard about us, unsubscribe, etc"; this.errorMsg = function(msgData) { messagePost.message = { subject: msgData.Subject, html: htmlHeader + '<p>Unknown Message</p><p>' + msgData.Header + '</p><p>Code:' + msgData.messageText + '</p>' + htmlFooter, text: msgData, to: [ { email: msgData.toEmail, name: msgData.toName, type: 'to' } }; } this.friendRequest = function(msgData) { messagePost.message = { subject: msgData.Subject, html: htmlHeader + '<p>Hey</p><p>' + msgData.theUser + '</p><p>We wanted to let you know that' + msgData.theFriend + 'wants to be your friend.</p>' + htmlFooter, text: msgData, to: [ { email: msgData.toEmail, name: msgData.toName, type: 'to' } }; } return $http.post('https://mandrillapp.com/api/1.0//messages/send.json', { messagePost }) .success(function(data, status, headers, config){ // log success }); })

Depending on your needs and the parts of the API you are using, you should be able to compartmentalize your service into a series of pieces that make for a far more robust solution.

#4 – Reconsider Using Angular for Production

Not to go all bait and switch, but while I have been able to work up examples using Angular in the design, the more I looked into it and worked with Mandrill, the more I want to ask if it is wise to be using it client-side at all in a production application. Unlike with AWS, I haven’t found a means to use it without exposing your keys. You can use a variety of rule-use restrictions, but with a client side application you lose the benefit of naming your IP address, which seems to be Mandrill’s main line of key-use security.

So what should you actually do? First, I’m not saying the JSON in Angular doesn’t have it’s place – it’s great for prototyping and development on those ‘super thin’ applications. In a world with increasingly distributed services, anything that helps you focus on single areas of work early on is a plus – so quick standing the Mandrill integration through Angular, and then porting your work over to Node for production might be worth while.

I will be, however, working up an example using the Node API in place of the JSON pretty soon, which seems the most appropriate alternative to me. While Mandrill does offer options for Python and Ruby and even PHP, Angular and Node tend to come together so that solution seems the most cohesive. It keeps the appropriate piece of work separated out onto the client and the server, while also keeping everything nice and lightweight. And, as I’ve pointed out before, a Node-over-Angular solution makes for a single-write API that can stand ready for other applications (web, desktop, and mobile) without any additional work once deployed.

See the follow up to this post here: Using Mandrill with the Node API and an Angular Client

So while it works, using Angular with Mandrill might not be as solid a solution as it initially presents itself to be. I’d love for it to be a better solution – to really get at the ‘super thin client’ model, but this ends up being another case that just doesn’t feel appropriate, at least for the long haul.

If you have any questions or comments, or even a suggestion or two, feel free to leave them below or reach out to me on Twitter!