Search code examples
c#google-oauthservice-accountsgmail-api

Can we access GMAIL API using Service Account?


I have a desktop application to read mail using GMAIL API over REST Interface. I want to use service account so that we can download the mails using domain setting and user interaction is null. I am successfully able to create Gmail Service instance but when I try to access any Gmail API method like fetching mail list or any other I get an exception saying

Google.Apis.Auth.OAuth2.Responses.TokenResponseException: Error:"access_denied", Description:"Requested client not authorized."

I am done with all the setting at developer console and added scopes to my gapps domain.

Does Gmail API support service account? Using the same setting and service account I am able to get list of all files in Google drive using Drive service and API.


Solution

  • 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 = "[email protected]";
    
    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);
        }
    }