Skip to content

Instantly share code, notes, and snippets.

@awesome
Forked from wrburgess/gist:3767468
Created November 17, 2016 23:55
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save awesome/3c9fc93d4b12405a2eaf224ee7158220 to your computer and use it in GitHub Desktop.
ActionMailer Setup in Rails 3

##Refs

Generate a Mailer Model and View

In terminal:

rails g mailer UserMailer

or create a mailers/user_mailer.rb

class UserMailer < ActionMailer::Base
  layout 'mailer_default'

  def user_email(user)
    @user = user
    @url = "http://example.com/login"
    mail(
      charset:       "utf-8",
      content_type:  "text/html",
      from:          Settings.mailer.from,
      subject:       "Email Test",
      to:            user.email
    )
  end
end

Create Mailer Templates

create a layout for emails as views/layouts/mailer_default.html.haml

!!!
%html{ lang: "en" }
  %head
  %body
    #wrapper
      =yield

create a partial for the email header at views/shared/_mailer_header_default.html.haml

#header{ style: "color: blue;" }
  %p
    This is header content

create a partial for the email footer at views/shared/_mailer_footer_default.html.haml

#footer{ style: "color: red;" }
  %p
    This is footer content

create a view for emails as views/user_mailer/user_email.html.haml

= render :partial => "shared/mailer_header_default"
  #content{ style: "color: green;" }
    %p 
      This is the content of the User Email
= render :partial => "shared/mailer_footer_default"

Create Settings for Mailer

Add to file config/settings.yml

mailer:
  from: "FirstName LastName <username@example.com>"
  address: "smtp.gmail.com"
  port: 587
  domain: "gmail.com"
  user_name: <%= ENV["MAILER_USERNAME"] %>
  password: <%= ENV["MAILER_PASSWORD"] %>
  authentication: "plain"
  enable_starttls_auto: true

Initialize Mailer Settings

create a file name config/intializers/mailer_settings.rb

ActionMailer::Base.smtp_settings = {  
  address:              Settings.mailer.address,  
  port:                 Settings.mailer.port,  
  domain:               Settings.mailer.domain,  
  user_name:            Settings.mailer.user_name,  
  password:             Settings.mailer.password,  
  authentication:       Settings.mailer.authentication,  
  enable_starttls_auto: Settings.mailer.enable_starttls_auto  
}

Set Up Environment Variables

On heroku:

$ heroku config:add MAILER_USERNAME=gmail.com --remote stage
$ heroku config:add MAILER_PASSWORD=password --remote stage

On local:

$ export MAILER_USERNAME=gmail.com --remote stage
$ export MAILER_PASSWORD=password --remote stage

Send an Email

Fire off an email using this line of ruby:

UserMailer.user_email(@user).deliver

Install and Setup MailView Gem for Email Previews

Install gem

Add to your Gemfile (:test and :dev) with specific Github commit to prevent breaking

group :test, :development do
  gem 'mail_view', git: 'git://github.com/37signals/mail_view.git', ref: '6a4bc7f01a'
end

In Terminal run bundle install

Add Preview Code

Add lines to the Mailer models

class UserMailer < ActionMailer::Base
  layout 'mailer_default'

  def user_email(user)
    @user = user
    mail(
      charset:       "utf-8",
      content_type:  "text/html",
      from:          Settings.mailer.from,
      subject:       "User Email Test",
      to:            user.email
    )
  end

  #add this code
  class Preview < MailView
    def user_email
      user = User.first
      mail = UserMailer.user_email(user)
      mail
    end
  end

end

Mount Views in Routes

Add new routes to config/routes.rb

if Rails.env.development?
  mount UserMailer::Preview => 'preview_email'
end

Visit the Preview

Go to http://example.com/preview_email to review

Setting up Tests

Ensure the test environment won't send emails

Check that this line is un-commented in config/environments/test.rb

config.action_mailer.delivery_method = :test

Add a method to a model that will send an email

Add to app/models/user.rb

def send_user_email(user)
  UserMailer.user_email(user).deliver
end

Add a spec to the model to test the send method

require 'spec_helper'

describe User do

  describe 'mailers' do

    it "sends a user_email" do
      user = FactoryGirl.create(:user, email: "test@example.com", password: "secret")
      user.send_user_email(user)
      ActionMailer::Base.deliveries.last.to.should == [user.email]
    end

  end

end

Add a spec for the mailer

create a file named spec/mailers/user_mailer_spec.rb

require "spec_helper"

describe UserMailer do

  describe 'user_email' do
    let(:user) { FactoryGirl.create(:user, email: "test@example.com", password: "secret") }
    let(:mail) { UserMailer.user_email(user) }
 
    #ensure that the subject is correct
    it 'renders the subject' do
      mail.subject.should == 'User Email Test'
    end
 
    #ensure that the receiver is correct
    it 'renders the receiver email' do
      mail.to.should == [user.email]
    end
 
    #ensure that the sender is correct
    it 'renders the sender email' do
      mail.from.should == ["test@example.com"]
    end
 
    #ensure that the @name variable appears in the email body
    it 'assigns @name' do
      mail.body.encoded.should match(user.name)
    end
 
    #ensure that the @confirmation_url variable appears in the email body
    it 'assigns @confirmation_url' do
      mail.body.encoded.should match("http://application_url/#{user.id}/confirmation")
    end
    
  end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment