Crafting newsletters on Rails

Why send newsletters?

Well, this is common sense. Customers are the most valuable resource you have and once in a while, you need to remind them how thankful you are for this deal. Besides newsletters introducing new features, updates etc, sending detailed information about their last month or week activity, will help them build a clear picture of their profit using your services.

Providing details on customers activity, demands the efficiency to calculate complex statistics and render large amount of information within a single HTML document. When it comes to crafting this shinny part of your software, you realise that your biggest enemy is the hundreds of different email clients and their limitations on the markup they accept. One more obstacle, is how to incorporate this type of newsletter with the rest of our codebase, in a way of keeping it as clean as it was before.

Loving challenges and neat solutions, the following describes the engineering effort we put on sending data intensive newsletters.

crafting-newsletters-on-rails

MVC-ing, without a controller

Based on an old but still applicable concept, we have a pretty fat model, which memoizes every single number we need to render on our mail, by fetching data required from several data stores. Something noteworthy, is that we do not persist any of the statistics we send, as long as the statistics we calculate are volatile and we can reproduce them any time we want, just by providing a time interval.

Our model is also responsible for serving graphs, using the great power of Google Chart Tools, along with its Ruby wrappers using the googlecharts gem, which lets you dynamically generate charts with URL strings.

Graph

The mail markup is an erb file, which exclusively consists of table tags, in supassing any limitations that several mail clients may have. While on development mode, we write our CSS rules in classic static assets and for previewing we use the letter_opener gem to render mail views directly in the browser. Having the gem installed with the configuration steps described, open your rails console and adjust the following line to your feet.

Customers::WeeklyNewsletterMailer.weekly_newsletter(@recipient).deliver

Browser should fire up and render your mail as it would be presented in a mail clinet. When in production, we use premailer-rails3 which inlines every css rule into the HTML, by loading resources from link tags.

Thus, no CSS rules are stripped according to limitations defined by mail clients. By the way, people involved in the Email Standards Project, have done great work on improving web standards support and accessibility in email.

In respect to the MVC framework, so far we have described the model which holds any business representation data as well as the view making up the output of these data. Beyond that, Rails takes care of the ‘contoller like’ role with the ActionMailer module, which provides various helpers to integrate your emails with your model and views. We also use a base mailer class, which is extended by any type of mailer we have in our stack, a lean way to keep our codebase as decoupled and DRY as possible.

Using the above schema, populating mail templates with new statistics becomes easy for any mail template we support. We pay utmost attention for every single feature we build, from the foremost down to the simple ones, giving special attention to aesthetics, usability, performance and technical completeness. We love our jobs and we try to make our customers life easier on a daily basis.