15
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Ruby on RailsでGmailAPI経由でGmailを取得する方法、、めっさムズイ。。

Last updated at Posted at 2018-06-07

背景

RailsでGmailを大量に取り込んで解析みたいなアプリを作る必要があった。

で便利なGemがあるみたいなのだが、
本家のgoogle-api-client以外だとGmailの設定で安全性の低いアプリからのアカウントへのアクセスを許可するというのをやらんといかんらしい。

で、本家のgoogle-api-clientがムズイムズイ。

結局HOWTO access the Gmail API with Rubyにお世話になった。

英語、、、なので、ちょっと日本語でその雰囲気を書いていきます。

まずはGmailAPIを有効化

GoogleデベロッパーコンソールでGmailAPIを有効化。
それで、Client IDClient secretをゲットする。

またリダイレクトURIはhttp://XXXXXX.XXX/gmail/callbackとかにしておく。

このあたりまでは、ググってなんとかイケる。

gem 'google-api-client'の導入

ここも普通にGemfileに書き込んでbundle

Authorization CodeとAccess Token

そしてムズイのがこれ。

Gmailを取得するには、

  1. まずAuthorization Codeを取得して、
  2. Authorization CodeをつかってAccess Tokenを取得して
  3. Access Tokenをつかってメールを取得

せねばならない。
これをコントローラーに落とし込んでいくのだ。

コントローラの全体像

先ほどのリダイレクトURIであるhttp://XXXXXX.XXX/gmail/callbackgmailコントローラを作成。

app/controllers/gmail_controller.rb
class GmailController < ApplicationController
end

で、

  1. 最初のアクションであるredirectアクションを作成し
  2. callbackアクションを作成し(ここは先ほどのリダイレクトURIであるhttp://XXXXXX.XXX/gmail/callbackに合わせる)
  3. 最後にgetmailアクションを作成する
app/controllers/gmail_controller.rb
class GmailController < ApplicationController
  def redirect
  end

  def callback
  end

  def getmail
  end
end

redirectアクションにてAuthorization Codeを取得してcallbackアクションにリダイレクト

app/controllers/gmail_controller.rb
class GmailController < ApplicationController
  def redirect
    client = Signet::OAuth2::Client.new({
      client_id: ENV.fetch('GOOGLE_API_CLIENT_ID'),
      client_secret: ENV.fetch('GOOGLE_API_CLIENT_SECRET'),
      authorization_uri: 'https://accounts.google.com/o/oauth2/auth',
      scope: Google::Apis::GmailV1::AUTH_GMAIL_READONLY,
      client.redirect_uri = url_for(action: :callback)
    })

    redirect_to client.authorization_uri.to_s
  end

  def callback
  end

  def getmail
  end
end

これで、Googleの認証ページに移動し、Authorization CodeをつかってリダイレクトURIであるhttp://XXXXXX.XXX/gmail/callbackにリダイレクトします。
(あー、わけわからん)

callbackアクションでAccess Tokenを取得

app/controllers/gmail_controller.rb
class GmailController < ApplicationController
  def redirect
    client = Signet::OAuth2::Client.new({
      client_id: ENV.fetch('GOOGLE_API_CLIENT_ID'),
      client_secret: ENV.fetch('GOOGLE_API_CLIENT_SECRET'),
      authorization_uri: 'https://accounts.google.com/o/oauth2/auth',
      scope: Google::Apis::GmailV1::AUTH_GMAIL_READONLY,
      client.redirect_uri = url_for(action: :callback)
    })
    redirect_to client.authorization_uri.to_s
  end

  def callback
    client = Signet::OAuth2::Client.new({
      client_id: ENV.fetch('GOOGLE_API_CLIENT_ID'),
      client_secret: ENV.fetch('GOOGLE_API_CLIENT_SECRET')
    })
    client.token_credential_uri = 'https://www.googleapis.com/oauth2/v3/token'
    client.redirect_uri = url_for(action: :callback)
    client.code = params[:code]
    response = client.fetch_access_token!
    session[:access_token] = response['access_token']
    redirect_to url_for(action: :getmail)
  end

  def getmail
  end
end

redirectアクションと同じようにclientをnewしますが、fetch_access_token!メソッドでAccess Tokenを取得できます。
こいつをsessionに入れておきます。
そしてgetmailアクションにリダイレクトします。

Access TokenをつかってGmailAPIでメッセージを取得

最後に、Access TokenをつかってGmailAPIでメッセージを取得します。

app/controllers/gmail_controller.rb
class GmailController < ApplicationController
  def redirect
    client = Signet::OAuth2::Client.new({
      client_id: ENV.fetch('GOOGLE_API_CLIENT_ID'),
      client_secret: ENV.fetch('GOOGLE_API_CLIENT_SECRET'),
      authorization_uri: 'https://accounts.google.com/o/oauth2/auth',
      scope: Google::Apis::GmailV1::AUTH_GMAIL_READONLY,
      client.redirect_uri = url_for(action: :callback)
    })
    redirect_to client.authorization_uri.to_s
  end

  def callback
    client = Signet::OAuth2::Client.new({
      client_id: ENV.fetch('GOOGLE_API_CLIENT_ID'),
      client_secret: ENV.fetch('GOOGLE_API_CLIENT_SECRET')
    })
    client.token_credential_uri = 'https://www.googleapis.com/oauth2/v3/token'
    client.redirect_uri = url_for(action: :callback)
    client.code = params[:code]
    response = client.fetch_access_token!
    session[:access_token] = response['access_token']
    redirect_to url_for(action: :getmail)
  end

  include GmailCallbacksHelper
  def getmail
    token = session[:access_token]
    query = "検索キーワード"
    @messages = get_messages(token, query)["messages"]
  end
end

ちょっと長くなるので、以下のHelper使ってます。
include GmailCallbacksHelperを忘れないように!
Helperからコントローラーに呼び出していいかは分からんが、とりあえず呼び出したった。

app/helpers/gmail_helper.rb
module GmailHelper
  def get_messages(token, query)
    uri = URI.parse("https://www.googleapis.com/gmail/v1/users/me/messages?q=#{query}")
    request = Net::HTTP::Get.new(uri)
    request["Authorization"] = "Bearer #{token}"
    req_options = { use_ssl: uri.scheme == "https" }
    response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
      http.request(request)
    end
    JSON.parse(response.body)
  end
end

@messagesにメールが入ってます。

ルーティング

ルーティングも忘れずに設定しましょう。

config/routes.rb
Rails.application.routes.draw do
  get '/gmail/redirect'
  get '/gmail/callback'
  get '/gmail/getmail'
end

むずかった。ほんま。

15
11
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?