Building an audience for your blog and keeping it engaged is hard. Instead of crossing your fingers and waiting for your visitors to come back, you can invite them to keep in touch by receiving a newsletter. For Ruby on Rails blogs, there is newsletter engine Maktoub. For everything else, there is Mailchimp. And when you want to have the bare minimum, there is Correole. Correole consists of a web API for subscribe + unsubscribe and a command for sending the newsletter. The newsletter is composed automatically from the RSS feed of your blog and a configurable template.

Features

Features are subscribe, unsubscribe, send, and purge.

Subscribes happen via a form in your site. Take for example the subscription form in this blog. The subscription form consists of a textbox and a button. The form asks to enter an email address and the button submits the address to the subscribe endpoint. The script that submits the address is the following.

function subscribe() {
email = $("#spopup-email").val();
callback = function(_jqXHR, success) {
if(success == "success") {
alert("Thank you for subscribing to the newsletter.");
} else {
alert("There was an error subscribing to the newsletter. Try again or subscribe via RSS.");
}
};
$.ajax({ url: "https://correole.herokuapp.com/subscribers/" + email,
type: "PUT",
complete: callback });
};

Transmission of the email address happens by means of SSL, so the address is kept private during transmission to Correole.

Unsubscribes happen via a link you include in your newsletter, like the following.

For email address subscriber@mail.com, the URL of the link is the following.

https://correole.herokuapp.com/unsubscribe/subscriber@mail.com

When the user opens the link in their browser, Correole unsubscribes them and issues a redirect to a confirmation page of your choice, ideally a page in your website with a style that is consistent with the rest of your site, like the following.

Submission of newsletter happens on request via command correole send.

$ correole send
Fetch feed from http://ruslanledesma.com/feed.xml.
There are 10 new items. The items are the following.
[1] http://ruslanledesma.com/2016/06/17/why-does-heap-work.html
[2] http://ruslanledesma.com/2016/05/26/how-to-count-cycles-in-kn.html
[3] http://ruslanledesma.com/2016/05/26/arbitrage.html
[4] http://ruslanledesma.com/2016/04/23/release-connections-thin-and-active-record.html
[5] http://ruslanledesma.com/2016/03/25/stacking-boxes.html
[6] http://ruslanledesma.com/2016/03/21/ecological-bin-packing.html
[7] http://ruslanledesma.com/2016/03/18/the-blocks-problem.html
[8] http://ruslanledesma.com/2016/03/14/the-3n-plus-1-problem.html
[9] http://ruslanledesma.com/2016/03/08/protip-redirect-stdout-stderr-separate-files.html
[10] http://ruslanledesma.com/2016/03/05/jill-rides-again.html
[1/2] Send newsletter to subscriber1@mail.com.
[2/2] Send newsletter to subscriber2@mail.com.
Remember new items.
Done.

Correole does best-effort delivery. When you execute correole send, tries to send the newsletter to each subscriber and does not retry or record failures. Command correole send is ideal for use in Heroku scheduler, so that you concentrate in writting content.

When you execute correole send, Correole automatically composes an email from new RSS items and the configured templates. Each email is multipart, so you know your readers will receive your newsletter just like you intended. Templates for html and plain text are configurable ERB templates. For example, the default HTML template is the following.

<html>
<body>
<h1><%= title %></h1>
<h2>New posts</h2>
<ul>
<% for item in unsent_items %>
<li>
<h3>
<a href="<%= item.link %>"><%= item.title %></a>
</h3>
<% if item.pub_date -%>
<p><i><%= item.pub_date.to_date %></i></p>
<% end -%>
<p><%= item.description %></p>
</li>
<% end %>
</ul>

<a href="<%= unsubscribe_uri %>">Unsubscribe here.</a>
</body>
</html>

The variables that are available in HTML and plain templates are the following.

  • title. Title of your RSS feed.
  • unsent_items. List of RSS items that are new. Each item consists of following properties.
    • item.link. The link of the item.
    • item.pub_date. A DateTime object corresponding to the timestamp of the item.
    • item.description. The description of the item.
  • sent_items. List of RSS items that are given by the RSS feed and are not new. Each item consists of the same properties as the items in list unsent_items.
  • unsubscribe_uri. URI of the unsubscribe endpoint for a given user.

The first time you run the newsletter, you may want to omit items that are too old. You can skip new items by means of command correole purge. For example, before sending out the first newsletter I ran correole purge like so.

$ correole send
Fetch feed from http://ruslanledesma.com/feed.xml.
There are 10 new items. The items are the following.
[1] http://ruslanledesma.com/2016/06/17/why-does-heap-work.html
[2] http://ruslanledesma.com/2016/05/26/how-to-count-cycles-in-kn.html
[3] http://ruslanledesma.com/2016/05/26/arbitrage.html
[4] http://ruslanledesma.com/2016/04/23/release-connections-thin-and-active-record.html
[5] http://ruslanledesma.com/2016/03/25/stacking-boxes.html
[6] http://ruslanledesma.com/2016/03/21/ecological-bin-packing.html
[7] http://ruslanledesma.com/2016/03/18/the-blocks-problem.html
[8] http://ruslanledesma.com/2016/03/14/the-3n-plus-1-problem.html
[9] http://ruslanledesma.com/2016/03/08/protip-redirect-stdout-stderr-separate-files.html
[10] http://ruslanledesma.com/2016/03/05/jill-rides-again.html
Purge the new items by remembering them.
Done.

Try it yourself in Heroku

To configure and run the project on Heroku, follow the instructions in README.md. Correole’s procfile includes processes send and purge, which you can run in one-off dynos, like so.

heroku run send

Dependencies

Correole is possible thanks to the wonderful libraries and services it uses.

Wishlist

The following are features that I may or may not implement.

  • Newsletter archive. Record the messages that Correole has sent.
  • Retry failed submit. For each subscriber, record the newsletters that have been submitted and the ones that have failed. Retry those that failed a given number of times.
  • Send one-off messages. When you want to share exclusive content with your subscribers, a one-off message is the way to go.

Feedback welcome

Would you like to contribute? Submit a pull request with tests following these guidelines.

Correole is released under MIT license, so you fork the project and use it in your propietary application.

Want to read more?

I love to explain and answer questions on programming problems, the kind you find in coding interviews. I publish a new programming problem and its solution every Sunday. Did I mention that I love to answer questions?

If you would like to get the latest problem + solution, subscribe to the newsletter or subscribe via RSS. You can also follow me on Twitter, GitHub, and LinkedIn.

Comments