Home > Net >  Error while trying to send email from google workspace from asp.net core web api app using Google.Ap
Error while trying to send email from google workspace from asp.net core web api app using Google.Ap

Time:10-27

I'm trying to send email from my google workspace account using this code:

using (var stream =
          new FileStream("credentials.json", FileMode.Open, FileAccess.Read))
{
    var credential = ServiceAccountCredential.FromServiceAccountData(stream);
    service = new GmailService(new BaseClientService.Initializer()
    {
        HttpClientInitializer = credential,
        ApplicationName = ApplicationName,
    });

    var email = MimeMessage.CreateFromMailMessage(new System.Net.Mail.MailMessage("EMAILADDRESS", destinationEmailAddress, "Verification code", $"Your verification code is {messageBody}"));

    Message message = new Message();

    byte[] blob;

    using (var memory = new MemoryStream())
    {
        email.WriteTo(memory);
        blob = memory.ToArray();
    }

    message.Raw = await credential.SignBlobAsync(blob);
    await service.Users.Messages.Send(message, "me").ExecuteAsync();
}

but I get the following exception:

Google.Apis.Requests.RequestError\nPrecondition check failed. [400]\nErrors [\n\tMessage[Precondition check failed.] Location[ - ] Reason[failedPrecondition] Domain[global]\n]\n

what am I doing wrong? and is there a straight forward guide to do this right?

CodePudding user response:

The issue you are having is that you are using Gmail with a service account and you have not properly configured domain wide delegation to a user on your workspace account. Follow this guide to configure your workspace account with the service account. Perform Google Workspace Domain-Wide Delegation of Authority

The following code should show you how to authorize it. Note the CreateWithUser method this sets up the user you wish to delegate the service account as.

class Program
    {
        private static readonly string[] Scopes = {GmailService.Scope.GmailSend};

        private static readonly string PathToServiceAccountKeyFile =
            @"C:\YouTube\workspaceserviceaccount-e4823a933ae3.json";

        private static readonly string workspaceAdmin = "[email protected]";
        private static readonly string sendEmailTo = "[email protected]";

        static async Task Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            var credential = LoadGoogleCredentials();
            var service = CreateDirectoryService(credential);

            var mailMessage = new System.Net.Mail.MailMessage
            {
                From = new System.Net.Mail.MailAddress(workspaceAdmin),
                ReplyToList = {workspaceAdmin},
                To = {sendEmailTo},
                Subject = "Welcome",
                Body = "welcome new workspace user",
            };


            var mimeMessage = MimeMessage.CreateFromMailMessage(mailMessage);

            var gmailMessage = new Message
            {
                Raw = Encode(mimeMessage)
            };

            var request = await service.Users.Messages.Send(gmailMessage, workspaceAdmin).ExecuteAsync();

            Console.ReadLine();
        }

        public static string Encode(MimeMessage mimeMessage)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                mimeMessage.WriteTo(ms);
                return Convert.ToBase64String(ms.GetBuffer())
                    .TrimEnd('=')
                    .Replace(' ', '-')
                    .Replace('/', '_');
            }
        }

        private static GmailService CreateDirectoryService(GoogleCredential credential)
        {
            return new(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Daimto Testing Workspace with service account"
                }
            );
        }

        private static GoogleCredential LoadGoogleCredentials()
        {
            return GoogleCredential.FromFile(PathToServiceAccountKeyFile)
                .CreateScoped(Scopes)
                .CreateWithUser(workspaceAdmin);
        }
    }

Note: this code is the same for all types of applications even though my test code is a console app the methods used will work for your asp .net core app as well

from comments

Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested

this error message means that your servcie account is not authorized with the proper scope. the gmail send method requires a scope that allows access to sending emails GmailService.Scope.GmailSend for instance as i have use din my code remember to add it in workspace as well.

  • Related