I have a rails application in which I wanted to send email using Gmail API(using google-api-client
for ruby). I have created one application in google developers and I have generated a service account key. I am using google specification for storing that credential JSON file(storing in /home/user/.config/gcloud/applicaton_default_credentials.json
).
For starters, I wanted to fetch user labels
below is my code
require 'google/apis/gmail_v1'
gmail_v1 = Google::Apis::GmailV1
service = gmail_v1::GmailService.new
service.authorization = Google::Auth.get_application_default([gmail_v1::AUTH_SCOPE, gmail_v1::AUTH_GMAIL_COMPOSE, gmail_v1::AUTH_GMAIL_MODIFY, gmail_v1::AUTH_GMAIL_READONLY])
user_id = 'me'
result = service.list_user_labels(user_id)
But this is giving me Google::Apis::ClientError: failedPrecondition: Bad Request
error.
My end goal is to send email using an email for which I have generated the credentials JSON file, as I don't want to put my username and password in the smtp config of the ActionMailer.
After many hours of debugging, I finally found a working solution. DalmTo is right about the concept that a service account can't access Gmail as Gmail requires a User account, but we can leverage the power of impersonation
in this case. The steps to do impersonation are:
We need to change our code for this setup like below
service = gmail_v1::GmailService.new
service.authorization = Google::Auth.get_application_default([gmail_v1::AUTH_SCOPE, gmail_v1::AUTH_GMAIL_COMPOSE, gmail_v1::AUTH_GMAIL_MODIFY, gmail_v1::AUTH_GMAIL_READONLY])
auth_client = service.authorization.dup
auth_client.sub = 'user@domain'
user_id = 'me'
result = auth_client.list_user_labels(user_id)
Note: For this, to work, we need to go to our G-suit account and give proper permission to our service account.