For web developers

PostageApp Blog

Rails Rumble – Postage Quick Start Guide

October 15th, 2010 by scott@twg.ca  |  No Comments

We’re a proud sponsor of this year’s Rails Rumble event where people are competing to see who can turn out the best Rails application in only 48 hours.

In a competition like this, there’s barely enough time for anything. Getting your app configured to send email is one of those things that can prove to be far more time-consuming than you expect if you’re not prepared.

All Rumble teams are eligible for a free account to be used for the competition upon request. Look for the link inside your competition page if you’re participating. We’ll set an account that’s ready to send email, but you’ll need to do some simple configuration to make it work within your app. There’s also free plans that can be used for testing your app if you’re not participating.

Here’s a quick-start guide for getting your Rails application set up and ready to rumble in only a few minutes.

1. Install the PostageApp Gem

If you’re using Rails 3, you’re likely using bundler. Installing the PostageApp gem is as easy as adding a line to the Gemfile in your application directory:

1
gem 'postageapp'

Once added, install it using the bundler tool:

bundle install

This will download and install the PostageApp gem along with any others defined in the Gemfile.

Rails 2 uses config/environment.rb to declare required gems, so you can set it up there, too, like you would any other gem. If you need help, the Ruby on Rails quick-start guide on the main page of a new project has a more detailed explanation.

2. Configure Your Application API Key

Log in to your PostageApp account and make sure you have at least one project. It’s easy to create one by simply giving it a name. On the Project Overview in your PostageApp account there should be quick-start guide which covers these first few steps, but it also includes the line to configure your application’s API key. It looks something like this:

rails g postageapp --api-key q1Kw5XEqpgzzIblZZpfxhVrRoNifzwRS

By this point you should have a working PostageApp installation and you should be able to send out your first test message. If you run rake routes you should see the PostageApp task listed. Run it and you should receive a test message for all email addresses associated with your account:

rake postageapp:test

For Rumble teams we’ll set up accounts that can send messages directly, or you can configure your own SMTP server if you have one handy.

3. Create a Message Layout

It’s not hard to send great looking email messages if you have the right tools. Email clients are notoriously particular about what kind of HTML they accept, and even support for CSS is extremely limited. One big feature of PostageApp is that you’re able to create a nice HTML template, add in a CSS file, and the two will be combined in an email-friendly markup format that you can preview before sending to ensure it’s working properly.

Every new project comes with a sample layout you can customize with your own logo, CSS theme, and of course content. A layout can be used to establish common headers and footers without having to cut and paste these to every type of message you’ll be making. These are available under the Message Templates tab of any project page.

To explain how this works, let’s create a very simple template by going to the Message Templates tab and clicking on the Create a New Template link just above the list of templates. You’ll get an empty editor screen you can use to create it.

Add a simple layout that looks something like this in the HTML tab edit area:

1
2
3
4
5
6
7
<h2>Team Pigeon</h2>
<hr>
<div>
{{ * }}
</div>
<hr>
<a href="http://pigeon.r10.railsrumble.com/">Pigeon Team Page</a>

The mysterious double-curly symbol-with-a-star-in-it {{ * }} in the middle is the location where the template content will go. This serves the same function that yield does within a block.

You can preview the template at any time and see how it should look in a regular email client. Warnings about your HTML and CSS are reported here, so if you’re making use of exotic, cutting-edge features like background images that some ornery email clients like Outlook don’t support, you’ll get a heads up here. You can always use the Send test email feature located just below the editor to see how the email looks in your own client, or through an email previewing service if you use one.

Without some CSS this is going to look really plain. As you design your app, it’s easy to snip key styles and paste them into the CSS tab of the template editor.

Before you can save this template, you have to give it a template slug. For layouts, this is really just a descriptive name you can use to remember what layout it is. In this case call it something like default_layout so it’s easily identified later.

The Subject and From fields generally only apply to templates themselves, not layouts. Likewise, although layouts can even have parent layouts if you want, where this layout will be wrapped inside another, generally this is not the case.

Save your template and you should be ready for the next step.

4. Create a Message Template

Having a layout is great, but without something to go into it, you won’t get much use out of it. A message template can be created as you usually would, within your Rails application, but it’s usually far easier to have the templates within PostageApp so you can edit them without having to redeploy your application. Think of this as CMS for your email messages where you can make changes at any time and see the results immediately.

A typical application sends out dozens of different messages to its users. When you sign up, when you confirm your registration, when you forget your password, when you haven’t been active in a while, when you invite someone, when you receive a message from someone, or even for general announcements or special offers. It can be difficult to maintain these if you have to check in and deploy your application to make even the smallest change.

A good example is an invitation email sent by one user to someone else. Create a New Message Template again. This time we’ll use the layout created in the last step to give an otherwise boring email some style.

Here’s a sample invitation that can be pasted into the HTML tab edit area:

1
2
3
<p>You've been invited to join {{team_name}}!</p>

<p><a href="{{signup_link}}">Sign up</a> now and receive five free invites you can share with your friends!</p>

There are two variables here you can customize with user data when sending the message, {{team_name}} and {{signup_link}}. Through the API you can set some of these the same for everyone, or customize each field individually for each recipient.

Set the parent layout to be the layout created in the earlier step.

You can set the default From address here, or assign it later when making the API call. The same goes for the Subject. You can also use template variables in the subject to personalize it. In this case, set the subject to:

{{team_name}} - Invitation from {{user_name}}

If you preview the message now, you should see the template wrapped neatly inside the layout.

Set the Template Slug to be invitation and save the message.

You’re now ready to set up something to trigger this message.

5. Create a Rails Notifier

While you can send messages directly through the PostageApp API using the gem, a more Rails-friendly approach is to use a notifier.

Set up a simple user notifier to handle these tranactional messages:

rails g mailer user_notifier

This will create app/mailers/user_notifier.rb which will need to be customized:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class UserNotifier < PostageApp::Mailer
  # Sends an invitation email for a team from a user to a number of
  # emails provided as an array.
  def invitation(team, user, emails)
    # Use the "invitation" template
    postageapp_template 'invitation'

    # Set up variables that apply to all messages sent
    postageapp_variables :team_name => ERB::Util.h(team),
      :user_name => ERB::Util.h(user)
   
    # Create customized variables for each recipient
    recipient_list = { }
   
    emails.each do |email|
      recipient_list[email] = {
        # Each new sign-up is tracked by referral
        :signup_link => new_signup_url(:email => email, :referral => user, :team => team)
      }
    end

    # Send the message using the API
    mail(
      :from => 'test@example.com',
      :to => recipient_list
    )
  end
end

It’s important to note that the notifier should inherit from PostageApp::Mailer instead of the default. If you forget this, it will try and send the message using conventional SMTP which is not configured correctly and will produce an error.

In any regular application, you’d just trigger this from your controller where required. In this example, we’ll create a simple controller that can display a form and fire off this notification so you can try it out.

6. Create a Controller

Creating a simple controller and view to trigger this notification is only required if you don’t have an app to put this inside of. We’ll do something quick here to show how it works:

rails g controller invitations

Now edit the resulting controller and give it that notification hook:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class InvitationsController < ApplicationController
  def index
    redirect_to(new_invitation_path)
  end
 
  def new
  end
 
  def create
    @team = params[:team]
    @user = params[:user]
    @emails = params[:emails] && params[:emails].reject(&:blank?)
   
    if (@team.present? && @user.present? && @emails.present?)
      UserNotifier.invitation(@team, @user, @emails).deliver
    else
      flash.now[:error] = 'Please enter a team name, user name and at least one email address'
      render(:action => 'new')
    end
  end
end

7. Create the Views

We’ll need two views here, one for the invitation form, and one for the thank-you confirmation screen.

Here’s a simple app/views/invitations/new.html.erb that shows a plain form:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<%- if (flash[:error]) %>
<div class="flash error">
<em><%= flash[:error] %></em>
</div>
<% end %>

<%= form_tag(invitations_path, :method => :post) do %>
  <div>
    <%= label_tag(:team, 'Team Name') %>
  </div>
  <div>
    <%= text_field_tag(:team) %>
  </div>
  <div>
    <%= label_tag(:user, 'User Name') %>
  </div>
  <div>
    <%= text_field_tag(:user) %>
  </div>
  <div>
    <%= label_tag(:emails) %>
  </div>
  <div>
    <%= text_field_tag(:emails, '', :name => 'emails[]') %>
  </div>
  <div>
    <%= text_field_tag(:emails, '', :name => 'emails[]') %>
  </div>
  <div>
    <%= text_field_tag(:emails, '', :name => 'emails[]') %>
  </div>
  <div>
    <%= text_field_tag(:emails, '', :name => 'emails[]') %>
  </div>
  <div>
    <%= submit_tag %>
  </div>
<% end %>

In a real application you’d have actual models to provide information on the user and the team name. Here we’re just using plain-text fields for simplicity. It’s also probably a good idea to HTML escape your output before sending it through to PostageApp.

We’ll also need to have a app/views/invitations/create.html.erb to show once the invitations have been sent:

1
2
3
4
5
<h1>
  Invitations Sent!
</h1>

<p><%= pluralize(@emails.length, 'invitation has', 'invitations have') %> been sent. Thanks!</p>

Now it’s time to set up the routing so that the controller is linked up to a URL.

8. Configure the Routing

We’ll need at least two routes for this to work, one for the invitations controller, and another that’s just stubbed in for the signup page.

1
2
3
4
Demoapp::Application.routes.draw do
  resources :invitations
  resources :signup
end

With a route added, you should be able to connect to the invitations page. You won’t be able to submit the form successfully until a few more configuration details are set properly, though.

9. Configure the Default Host

In order for the ActionMailer to know how to generate full URLs, which are required to make an email, you need to set your default URL options. A good place to establish this is in config/environments/development.rb for testing:

1
2
3
4
5
6
7
8
Myapp::Application.configure do
  # ... other configuration ...

  config.action_mailer.default_url_options = {
    :host => 'localhost',
    :port => 3000
  }
end

Adjust the other environments as required. The host name probably changes between your development environment and the production environment.

10. Launch the Server

rails server

You should be able to access it at the URL http://localhost:3000/invitations if it starts up properly. Fill out the team name, user name, and at least one email.

If you’re logged in to your PostageApp account you should be able to see this immediately in your Sent Messages. This allows you to see what messages have been created using the API as well as any test messages sent from the template editor.

All the files used in this example have been bundled into a GitHub repository you can download to get an even quicker start.

Recap!

From here you can go and customize this as required, add other notifications, and create new templates. Once you’re all set up, it’s usually very easy to copy a template, add a new notifier, and link it in to a new spot in your application.

Hopefully this saves you a bunch of time so you can make an even better application this weekend.

More detailed documentation is available on the support site.

Good luck with the Rumble!