Notification Generator: a simple email template engine

This is a pretty neat feature that we added for one of our customers and I wanted to share. I am going to share as much code as I can but because it is specialized it will be mostly useful on a conceptual level (also the code uses some of our private libraries which I can’t share at this time, so it will need a little bit of adjustments in order to run). Very inventively it was named the Notification Generator. It began its life over 5 years ago as we had a need for a program that could send email notices and take actions on tickets (called Work Orders by this customer). Why not a business process solution like Knowledge Sync or Task Centre? In fact this customer also uses Knowledge Sync but we went with a custom application for 2 reasons: the ability to prioritize emails (their Knowledge Sync queue is always busy), and the ability to apply complex actions on the query results (for example we needed to add some of the work order attachments to the email, using logic depending on the work order type, and concatenate them into a single PDF document). This is possible to do using external commands in Knowledge Sync but it gets unwieldy very quickly. Finally the last feature which was just added (and which is the one I want to brag write about) is the ability for the CRM users to define their own templates within the app, using a rich text editor.

So there are 2 parts to the process:

  • defining the criteria for a notification to be sent
  • defining the content of the notification

Often workflow tools will separate the 2, which makes sense when you are looking at it from a programming or administration perspective, but we felt was going to be confusing to the end users (CRM power users to be sure but not programmers or IT specialists). So the process was streamlined into a single, specialized screen.

Edit Dialog

This uses TinyMCE for the rich editor. I tried to use dojo’s but was not happy with the extensibility options (that and it looks pretty bad). TinyMCE was a breeze to use and I would definitely use it in favor of dojo’s widget in future projects. In fact I found that in general all the dojo widgets save for the simplest ones are very hard to customize. But I digress! Here we wanted to have a menu with the available insert options (i.e. the template expansion variables). Again this makes the screen very tied to this single purpose but that is fine.

Insert Menu

One thing was a bit trickier to figure out – dojo’s dialog has a “focus stealing prevention” built in. We needed to work around that so that the HTML view window could get focus. To do that one needs to add a “dijitPopup” class on the new popup window, marking it as a popup so dojo doesn’t feel like it has to reclaim focus from it.

        ed.on('OpenWindow', function (w) {
            setTimeout(function() {
                // fight focus stealing from dojo dialog by marking as a dojo popup
                w.win.getEl().className += ' dijitPopup';
                w.win.getEl().querySelector('textarea').focus();
            })
        });

Once the templates are set up the Notification Generator app will pick them up, check for matches and send the corresponding messages. I had go give a big face lift to the app itself as it started as a very simple program that we built on over the years. So even though the screen is very specialized, the classes that implement the match / emails have been kept generic enough that they could be adapted to another process if needed (and actually there already was a process in place that I had to refactor into a modular pattern).

One super cool tool I have used for testing this (and similar services) is Mailtrap. This lets me send all emails to a “fake” mailbox where I can monitor them, allowing the system to send out those emails just as if it was using a regular smtp server but obviating the chance of having them delivered to one of our users. This is highly recommended if you are writing any sort of email integration. Together with that I added a “preview” feature on the setup screen that allows for sending a copy of the template to a user-specified address, and equipped the app itself with some much needed automatic tests (unfortunately the previous design was not modular at all so automated testing was very hard – this made the refactor challenging since we could not validate the behavior was unmodified!)

Here is an example email. Love how happy that guy looks. Not sure I am letting him in if he shows up at my house with that expression though.

example email

There are a few things I wish I had had the time to add though! But, you have to pick a place to stop, and there just wasn’t enough value for the customer in those extra feature. Maybe another time!

  • Definitely my top would have been a way to define “master templates”, letterhead, whatever you want to call it, they would have made it easy to use the same design when you have a few templates defined for the same parent account. Thankfully they are only planning to define a handful of templates per account so it can be accommodated with a little bit of copy paste. It would have been challenging to make that into a user friendly feature.
  • Better automated testing! The ones I have depend on the existing data so they are a bit brittle. I didn’t want to go full-on mock though as I needed to ensure this would work with the existing data which is sometimes dirty. So not an easy answer there.
  • The UI for adding templates is not bad but it would be nice if there was a live preview in addition to the email preview. I wanted the email preview to ensure the emails would be 100% the same as what would be sent by the service in actual use

I placed the code on Github, minus a few customer specific parts. Importantly that code won’t run at all as is because I deleted the configuration. I will probably get back to this at some point and make it into something truly generic that I can use for other customers.

Leave a Reply

Your email address will not be published. Required fields are marked *