Search code examples
c#.net-coregoogle-apigmail-apigoogle-authentication

Getting All Users and Mailboxes with One API


I am supporting an IT admin, who is himself facilitating the use of compliance software. To that end, I have written some C# code that iterates through all users in a directory, and performs operations on their messages. My current solution uses two different APIs to accomplish this (code snippet below), but obviously it would be better to only use one API. Having scanned through other posts here, I failed to find a satisfactorily clear answer on how to make that happen. My app is a service account, with Google Workspace domain-wide delegation enabled. How can I use only one API to accomplish what I am doing with two?

[working code snippet]

string domain; // domain name
string adminEmail; // admin e-mail
string directoryClientEmail; // client e-mail for Directory API
string directoryPrivateKey; // private key for Directory API
string directoryPrivateKeyId; // private key ID for Directory API
string gmailClientEmail; // client e-mail for Gmail API
string gmailPrivateKey; // private key for Gmail API
string gmailPrivateKeyId; // private key ID for Gmail API
CancellationToken cancellationToken; // a cancellation token

DirectoryService directoryClient = new DirectoryService(
    new BaseClientService.Initializer
    {
        HttpClientInitializer = new ServiceAccountCredential(
            new ServiceAccountCredential.Initializer(creds.DirectoryClientEmail)
            {
                User = adminEmail,
                Scopes = new[] { DirectoryService.Scope.AdminDirectoryUser },
                Key = RSA.Create(directoryPrivateKey),
                KeyId = directoryPrivateKeyId
            }.FromPrivateKey(directoryPrivateKey))
    });

UsersResource.ListRequest userListRequest = directoryClient.Users.List();
userListRequest.Domain = domain;
Users userList = await userListRequest.ExecuteAsync(cancellationToken);

foreach (User user in userList)
{
    GmailService gmailClient = new GmailService(
        new BaseClientService.Initializer
        {
            HttpClientInitializer = new ServiceAccountCredential(
                new ServiceAccountCredential.Initializer(gmailClientEmail)
                {
                    User = user.PrimaryEmail,
                    Scopes = new[] { GmailService.Scope.MailGoogleCom },
                    Key = RSA.Create(gmailPrivateKey),
                    KeyId = gmailPrivateKeyId
                }.FromPrivateKey(gmailPrivateKey))
        });

    ListRequest listRequest = new ListRequest(gmailClient, "me");
    ListMessageResponse listMessageResponse = await listRequest.ExecuteAsync(cancellationToken);

    foreach (Message message in listMessageResponse.Messages)
    {
        // do stuff
    }
}

Solution

  • To achieve what you want, you can't only use one API. As the Gmail API will not give you the users in the domain, but you can get a user's messages with it; which you need. So Gmail API is a requirement.

    Then if you want an up-to-date domain users list, then you need to use the Directory API, so unless you have a list of users somewhere else, you require this API too.