我正在尝试使用Gmail for Ruby gem连接到Gmail api。我遵循这个谷歌oauth2指南安装的应用程序。
我已经在谷歌开发者控制台中设置了我的应用程序,我可以用我的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
如果我的问题缺少任何信息,请直接询问,我渴望解决这个问题。
范围很重要。以下是正确的:
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]