尝试使用 Google.Apis.Gmail 从 asp.net 核心网络 api 应用从 google 工作区发送电子邮件时出错

Error while trying to send email from google workspace from asp.net core web api app using Google.Apis.Gmail

我正在尝试使用此代码从我的 google 工作区帐户发送电子邮件:

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();
}

但我得到以下异常:

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

我做错了什么?是否有直接的指南来正确执行此操作?

您遇到的问题是您将 Gmail 与服务帐户一起使用,并且您没有正确配置对工作区帐户用户的全域委派。按照本指南使用服务帐户配置您的工作区帐户。 Perform Google Workspace Domain-Wide Delegation of Authority

下面的代码应该告诉你如何授权它。请注意,CreateWithUser 方法会设置您希望将服务帐户委派为的用户。

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 = "xxxx@daimto.com";
        private static readonly string sendEmailTo = "xxxx@gmail.com";

        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);
        }
    }

注意:此代码对于所有类型的应用程序都是相同的,即使我的测试代码是控制台应用程序,所使用的方法也适用于您的 asp .net 核心应用程序

来自评论

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

此错误消息表示您的服务帐户未获得适当范围的授权。 gmail 发送方法需要一个允许访问发送电子邮件的范围 GmailService.Scope.GmailSend 例如,因为我使用了 din 我的代码记得将它添加到工作区中。

完整教程Gmail api with google workspace and .net