首页 > 解决方案 > 尝试使用 Google.Apis.Gmail 从 asp.net core web api 应用程序从谷歌工作区发送电子邮件时出错

问题描述

我正在尝试使用以下代码从我的 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\n前置条件检查失败。[400]\n错误 [\n\tMessage[前置条件检查失败。] 位置[-] 原因[failedPrecondition] 域[全局]\n]\n

我究竟做错了什么?是否有直接的指南来做到这一点?

标签: c#asp.net-coregoogle-apigmail-apigoogle-api-dotnet-client

解决方案


您遇到的问题是您正在使用带有服务帐户的 Gmail,并且您没有正确配置域范围内的委派给您工作区帐户上的用户。按照本指南使用服务帐户配置您的工作区帐户。执行 Google Workspace 域范围的授权

以下代码应向您展示如何授权它。请注意 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 核心应用程序

来自评论

客户端未授权使用此方法检索访问令牌,或者客户端未授权任何请求的范围

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

带有 google 工作区和 .net 的完整教程Gmail api


推荐阅读