How to Access Gmail API Using Service Account

Can we access GMAIL API using Service Account?

I use the following C# code for accessing Gmail from Service Account

String serviceAccountEmail =
"999999999-9nqenknknknpmdvif7onn2kvusnqct2c@developer.gserviceaccount.com";

var certificate = new X509Certificate2(
AppDomain.CurrentDomain.BaseDirectory +
"certs//fe433c710f4980a8cc3dda83e54cf7c3bb242a46-privatekey.p12",
"notasecret",
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);

string userEmail = "user@domainhere.com.au";

ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
User = userEmail,
Scopes = new[] { "https://mail.google.com/" }
}.FromCertificate(certificate)
);

if (credential.RequestAccessTokenAsync(CancellationToken.None).Result)
{
GmailService gs = new GmailService(
new Google.Apis.Services.BaseClientService.Initializer()
{
ApplicationName = "iLink",
HttpClientInitializer = credential
}
);

UsersResource.MessagesResource.GetRequest gr =
gs.Users.Messages.Get(userEmail, msgId);
gr.Format = UsersResource.MessagesResource.GetRequest.FormatEnum.Raw;
Message m = gr.Execute();

if (gr.Format == UsersResource.MessagesResource.GetRequest.FormatEnum.Raw)
{
byte[] decodedByte = FromBase64ForUrlString(m.Raw);
string base64Encoded = Convert.ToString(decodedByte);
MailMessage msg = new MailMessage();
msg.LoadMessage(decodedByte);
}
}

How to use Service Account to access GMAIL API for a GSuite email account

The documentation specifies:

Rather than manually creating an OAuth2 client, JWT client, or Compute
client, the auth library can create the correct credential type for
you, depending upon the environment your code is running under.

In other words:

  • google.auth.GoogleAuth is a library tool that creates dynamically the correct credentials for you if you do not know which credentials you need
  • google.auth.OAuth2 always creates specifically OAuth2 credentials
  • For most applications where you authenticate as yourself OAth2 is what you need
  • However for using a service account you need to create a JSON Web Token a specified here
  • Double-check that you created service account crendetials, preferably as a json file, enabled domain-wide delegation and provided the service account with the necessary scopes in the admin console.
  • To implement impersonation into your code, add the line subject: USER_EMAIL when creating the JWT client.

Sample

const {JWT} = require('google-auth-library');
//THE PATH TO YOUR SERVICE ACCOUNT CRENDETIALS JSON FILE
const keys = require('./jwt.keys.json');

async function main() {
const client = new JWT({
email: keys.client_email,
key: keys.private_key,
scopes: ['YOUR SCOPES HERE'],
subject: USER_EMAIL
});
const url = `https://dns.googleapis.com/dns/v1/projects/${keys.project_id}`;
const res = await client.request({url});
console.log(res.data);
}

main().catch(console.error);

Create service account credentials for gmail API

To implement impersonation with GoogleCredentials use createDelegated(String user):

final GoogleCredentials creds = ServiceAccountCredentials.fromStream(new FileInputStream("resources/credentials.json"))
.createScoped(GmailScopes.GMAIL_SEND, GmailScopes.GMAIL_COMPOSE, GmailScopes.GMAIL_MODIFY, GmailScopes.MAIL_GOOGLE_COM);
final GoogleCredentials delegatedCreds = creds.createDelegated(userEmail);
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(delegatedCreds);
HttpTransport transport = new NetHttpTransport.Builder().build();
// Construct the gmail object.
Gmail gm = new Gmail.Builder(transport, JSON_FACTORY, requestInitializer)
.setApplicationName(APPLICATION_NAME)
.build();

  • Thereby, the sender of the email will be the user impersonated by the service account userEmail.
  • The owner of the GCP project / creator of the service account is not relevant and does not need to be specified, every Service Account User with the respective permisisons can use the service account for his domain.

Can I use Gmail API send email without Google Workspace (or Service accounts)?

Can I send email without Google Workspace?

Yes you can use gmail api without workspace you will just need to use Oauth2 rather than a service account and authorize a user.

Oauth2 requires that a user consent to the access to their google account. A user will need to authorize your code at least once.

Where as service accounts allow you to preauthroize access defined using domain wide delegation within a google workspace account. So no user interaction would be required.

Can I just Add 'type' into Client ID.json to make it work like Service accounts.json?

No the code is different depending upon the type of client you have created. If you create a web client then you need to use code designed for a web client. If you create installed client credentials then you need to use the code for an installed client.

The following sample Java quickstart is designed for an installed app. It will open the browser consent window on the machine the code is running on.



Related Topics



Leave a reply



Submit