首页 文章

登录时,带有OAUTH2的Ruby Gmail API会响应无效凭据(失败)

提问于
浏览
1

我正在尝试使用Gmail for Ruby gem连接到Gmail API . 我正在关注已安装的应用程序的this google oauth2 guide .

我已经在Google Developer's Console中设置了我的应用程序,我可以使用client_id和client_secret发送请求以获取授权代码 . 然后,我可以使用我的授权码发送请求以获取访问令牌和刷新令牌 . 我能够成功发送刷新访问令牌的请求,并返回一个新的访问令牌 .

当我尝试连接到Gmail时出现问题 . 首先,我设置了一个实例变量@gmail = Gmail.connect(:xoauth2,@ email,@ client.access_token) . 然后,我尝试使用@ gmail.login(true)登录 . 但是,当我尝试时,我收到以下错误:

Couldn't login to given Gmail account: caiden.robinson35@gmail.com (Invalid credentials (Failure)) (Gmail::Client::AuthorizationError)

我在这里不知所措,一切都表明我正在正确执行oauth2流程,除了在登录时我得到无效凭据这一事实 . 在生成授权码时,我会专门点击我的电子邮件并允许我的应用访问 . 我的开发人员控制台中也启用了API . 这是完整的代码:

class GmailClient
  def initialize
    load_client_info
    @email = "caiden.robinson35@gmail.com"
    load_and_set_oauth2_tokens

    sign_in_gmail
    binding.pry
  end

  private

  def sign_in_gmail
    binding.pry
    @gmail = Gmail.connect(:xoauth2, @email, @client.access_token)
    ######################
    # RIGHT HERE IS WHERE IT FAIL
    ######################
    @gmail.login true
    binding.pry
  end

  def load_client_info
    gmail_credentials = YAML.load_file('config/gmail.yml')
    @client_id = gmail_credentials["client_id"]
    @client_secret = gmail_credentials["client_secret"]
    @redirect_uri = 'urn:ietf:wg:oauth:2.0:oob'
  end

  def load_and_set_oauth2_tokens use_cached_tokens = true
    if use_cached_tokens && File.exist?("config/tokens.yml")
      token_hash = YAML.load_file('config/tokens.yml')
      @authorization_code = { code: token_hash["authorization_code"],
                              is_cached: true }
      @client = signet_client(token_hash)
      @token_hash = @client.refresh!
    else
      if !(instance_variable_defined?("@authorization_code") && @authorization_code[:is_cached] == false)
        retrieve_and_set_authorization_code
      end
      @token_hash = set_client_and_retrieve_oauth2_tokens
    end
    write_tokens_to_file
  end

  def retrieve_and_set_authorization_code
      puts "Go to the following url to enable the gmail cli app:"
      puts "https://accounts.google.com/o/oauth2/auth?scope=email&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&client_id=#{@client_id}"
      print "Paste your authorization code here: "
      @authorization_code = { code: gets.chomp,
                              is_cached: false }
  end

  def set_client_and_retrieve_oauth2_tokens
    @client = signet_client
    @client.fetch_access_token!
  end

  def signet_client token_hash = nil
    client = Signet::OAuth2::Client.new(
      client_id: @client_id,
      client_secret: @client_secret,
      redirect_uri: @redirect_uri,
      scope: 'email',
      token_credential_uri: 'https://www.googleapis.com/oauth2/v4/token'
    )
    if token_hash.present?
      client.refresh_token = token_hash["refresh_token"]
    else
      client.authorization_uri = 'https://accounts.google.com/o/oauth2/auth'
      client.code = @authorization_code[:code]
    end
    client
  end

  def write_tokens_to_file
    if File.exist?("config/tokens.yml")
      data = YAML.load_file "config/tokens.yml"
      @token_hash.each { |k, v| data[k] = v }
      File.open('config/tokens.yml', 'w') do |file|
        YAML.dump(data, file)
      end
    else
      File.open('config/tokens.yml', 'w') do |file|
        @token_hash.each { |k, v| file.write("#{k}: #{v}\n") }
        file.write("authorization_code: #{@authorization_code[:code]}\n")
      end
    end
  end
end

如果我的问题缺乏任何信息,请问,我很想解决这个问题 .

1 回答

  • 1

    范围很重要 . 这是正确的:

    scope: ['https://mail.google.com/', 'https://www.googleapis.com/auth/userinfo.email' #,'https://www.googleapis.com/auth/gmail.send' - if you'd like to send emails as well]
    

相关问题