Available for hire
Gmail Gem & Omniauth-google-oauth2 Setup in a Rails App

There are a number of ways to access a Gmail mailbox, the way I’ll describe it today is using the Gmail gem and omniauth-google-oauth2 gem.

Setting up google api’s.

There are plenty of tutorials on how to set up google apis so I won’t be going into it. But ensure you have Contacts Api, Google Plus and Gmail Api enabled to follow along with this post.

Code, Lets get Coding!

Include the gems

1
2
3
4
# Gemfile

gem "gmail"
gem "omniauth-google-oauth2"

Omniauth requires configuration which lives in the config/initializers/omniauth.rb. Here we define the provider and scope of access we require. This should align with the API’s we have chosen in the last screen, but it could be a subset.

1
2
3
4
5
6
7
8
9
# config/initializers/omniauth.rb

OmniAuth.config.logger = Rails.logger

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_SECRET'], {
    scope: ['https://mail.google.com/','contacts','plus.login','plus.me','userinfo.email','userinfo.profile']
  }
end

Next we’ll set up a User model to store the information from the users.

1
2
rails g model user provider uid name email image oauth_token oauth_refresh_token  oauth_expires_at:datetime
rake db:migrate

Next we’ll set up a method to create a user or load them from the database.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# app/models/user.rb

class User < ActiveRecord::Base
  def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_initialize.tap do |user|
      user.provider = auth.provider
      user.uid = auth.uid
      user.name = auth.info.name
      user.email = auth.info.email
      user.image = auth.info.image
      user.oauth_refresh_token = auth.credentials.refresh_token if auth.credentials.refresh_token
      user.oauth_token = auth.credentials.token
      user.oauth_expires_at = Time.at(auth.credentials.expires_at)
      user.save!
    end
  end
end

Next we’ll define a method to grab the current_user. We’ll put this in our ApplicationController

1
2
3
4
5
6
7
8
9
10
# app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  helper_method :current_user

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end
end

We’ll use the SessionsController to handle the login and logout actions for a user. The create action will be used as the callback url we’ll give to google, and the destroy action will log a user out.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# app/controllers/sessions_controller.rb

class SessionsController < ApplicationController
  def create
    user = User.from_omniauth(env["omniauth.auth"])
    session[:user_id] = user.id
    redirect_to root_path
  end

  def destroy
    session[:user_id] = nil
    redirect_to root_path
  end
end

Now that we have our controller set up, lets set up some routes. In your Google Credential set up you would of been asked for Redirect URL’s, Given the below routes, you can use whatever domain you wish and the path /auth/google_oauth2/callback and /auth/failure.

1
2
3
4
5
6
7
# config/routes.rb

get 'auth/:provider/callback', to: 'sessions#create'
get 'auth/failure', to: redirect('/')
get 'signout', to: 'sessions#destroy', as: 'signout'

resources :sessions, only: [:create, :destroy]

I’d recommend putting some auth stuff in a partial, and including it where it’s needed.

1
2
3
4
5
6
7
8
# app/views/application/_auth.html.erb

<% if current_user %>
  Signed in as <strong><%= current_user.name %></strong>!
  <%= link_to "Sign out", signout_path, id: "sign_out" %>
<% else %>
  <%= link_to "Sign in with Google", "/auth/google_oauth2", id: "sign_in" %>
<% end %>

And that’s omniauth-google sorted. Start the app, and auth yourself so we have a token to play with.

Gmail Gem.

So the Gmail gem can be auth’d via a number of methods like username and password, or oauth1 but we’ll be using oauth2. It’s quite simple now to connect to a user’s account!

Load up your rails console, and put this in!

1
2
3
4
5
user = User.first
Gmail.connect(:xoauth2, user.email, user.oauth_token)

# You should see
=> #<Gmail::Client0x7f8f95b6ec58 (users@emailaddress.com) connected>

From there you can utilise any of the Gmail gem methods. i.e.

1
2
3
4
user = User.first
gmail = Gmail.connect(:xoauth2, user.email, user.oauth_token)
gmail.inbox.count
=> 42

Comments