giant robots smashing into other giant robots

Written by thoughtbot

dancroak

Delivering email on behalf of users

A recipe for a better user experience in emails sent between users via my Rails app.

Why?

When I receive an email from an automated system like a Rails app, it is disorienting if the sender shows up in my email program as “admin” or “donotreply”.

What I want is something like this:

image

Ingredients

Install email-spec

I’m a fan of Ben Mabey’s email-spec gem, so I’ll install that:

group :test do
  gem 'email_spec'
end

I create a features/support/email.rb file:

require 'email_spec' # add this line if you use spork
require 'email_spec/cucumber'

Then generate some step definitions into features/step_definitions/email_steps.rb:

rails generate email_spec:steps

Feature

Now I’ll write my user story:

Scenario: Guitarist shares song with guitarist
  Given the following user exists:
    | name         | email            |
    | Eric Clapton | eric@example.com |
  And I sign in as "eric@example.com/password"
  And I am on the share page for "Layla"
  When I fill in "Share with" with "jimi@example.com"
  And I press "Share Song"
  And "jimi@example.com" opens the email
  Then he should see "Eric Clapton " in the email "From" header
  And he should see "eric@example.com" in the email "Reply-To" header

The “From” and “Reply-To” headers

I think the “From” and “Reply-To” headers can provide a better user experience.

I don’t set the author’s email as the “From” header because I hear it’s bad spam practice to send email on behalf of users in that way. ISPs use the From header (among other things) to determine if the originator is sending spam.

Making the feature pass

Ease my worried mind:

class Mailer < ActionMailer::Base
  def share_song(song, friend)
    mail(
      to: friend.email,
      from: %{"#{song.artist.name}" },
      reply_to: song.artist.email,
      subject: 'Good song'
    )
  end
end

I’ve used this format so the sender’s name shows up in the receiver’s email program:

"Name" 

In this case, I want Jimi to be able to reply directly to Eric, so I’ve set the “Reply-To” header to be the sender’s address. I’ve explicitly not put the sender’s name in the “Reply-To” header because that doesn’t work.

In other cases, I want the receiver to reply to the email and have that sent through the Rails app, but that’s a story for another day.

Written by .

dancroak

Deliver email with Amazon SES in a Rails app

Amazon SES came out last week and… you know… shiny.

Why use Amazon SES?

Right now, price. At our current email rates, we would save more than $10,000 in 2011 using Amazon SES over SendGrid for Airbrake.

However, SendGrid’s a reliable entity with more features (analytics, spam reports, etc.) so even with those savings, we’re leaving SendGrid yet on Airbrake.

In the meantime, we’re trying Amazon SES on another project that is in private beta to see how well it performs in terms of deliverability, blacklisting, etc.

Open source library

A week after Amazon announced the service, there were plenty of libraries on Github for Amazon SES. I chose drewblas/aws-ses (the aws-ses gem).

Comparing SendGrid implementation in a Rails app

How to use SendGrid in a Rails app:

MyRailsApp::Application.configure do
  config.action_mailer.smtp_settings = {
    address: ENV['SMTP_ADDRESS'],
    authentication: :login,
    domain: 'staging.myrailsapp.com',
    password: ENV['SMTP_PASSWORD'],
    port: 25,
    user_name: ENV['SMTP_USERNAME']
  }
end

You don’t need a special gem: it’s just SMTP.

Using the aws-ses gem in a Rails app

Amazon SES requires some HMAC‘ing and other stuff, but when using a library, it’s still pretty easy and it has the same dependencies as Rails.

Add the gem to your Gemfile:

gem 'aws-ses', '~> 0.4.4', require: 'aws/ses'

Extend ActionMailer in config/initializers/amazon_ses.rb:

ActionMailer::Base.add_delivery_method :ses, AWS::SES::Base,
  access_key_id: ENV['AMAZON_ACCESS_KEY'],
  secret_access_key: ENV['AMAZON_SECRET_KEY']

Set the delivery method in config/environments/{staging,production}.rb:

config.action_mailer.delivery_method = :ses

That’ll do it. Happy emailing!

Written by .