【问题标题】:Faling precondition while using google Gmail api for Gsuite使用适用于 G Suite 的 google Gmail api 时下降的前提条件
【发布时间】:2018-07-08 19:09:14
【问题描述】:

试图完成这项工作,我完全发疯了。我需要使用 gmail api 从我们的域发送邮件。每次我得到这个结果时:

Google.Apis.Requests.RequestError
Bad Request [400]
Errors [
    Message[Bad Request] Location[ - ] Reason[failedPrecondition] Domain[global]
]

我快疯了!

我已经阅读了所有这些,但我仍然没有弄清楚:

如何让它发挥作用?

这些是我已经完成的步骤:

  1. 在 console.developers.google.com 中创建了一个新项目
  2. 启用 gmail api
  3. 创建了服务帐号
  4. 为服务帐号创建了 key.p12 文件
  5. 已配置域范围的权限
  6. 在 admin.google.com 中启用了 gmail api
  7. 在 security->advanced->Api accesses 中添加了 api 范围
  8. 添加并验证了我的域名

屏幕:

这是我的代码:

public class TestMailController : Controller
    {

        static string ApplicationName = "IdiciumGmail";
        private static String serviceAccountEmail = "idiciumgmail@turing-thought-193608.iam.gserviceaccount.com";

        public IActionResult Index()
        {

            string debugMessage = "";

            var certificate = new X509Certificate2(@"key.p12", "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);

            ServiceAccountCredential credential = new ServiceAccountCredential(
                new ServiceAccountCredential.Initializer(serviceAccountEmail)
                {
                    Scopes = new[] { GmailService.Scope.MailGoogleCom }
                }.FromCertificate(certificate));

            if (credential.RequestAccessTokenAsync(CancellationToken.None).Result)
            {
                // Create Gmail API service.
                var service = new GmailService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = ApplicationName,
                });

                /*
                var message = new MimeMessage();
                message.From.Add(new MailboxAddress("Bestuur", "bestuur@indicium.hu"));
                message.To.Add(new MailboxAddress("Tester", "william.wl@live.nl"));
                message.Subject = "Is this working";
                message.Body = new TextPart(TextFormat.Html)
                {
                    Text = "Ja ja als je dit krijgt werkt het.... EINDELIJK. <br><br> <b>ook html werkt</b>"
                };

                 */

                Message m = new Message();
                m.Raw = "RnJvbTogQmVzdHV1ciA8YmVzdHV1ckBpbmRpY2l1bS5odT4gClRvOiBXaWxsaWFtIExvb3NtYW4g\nPHdpbGxpYW0ud2xAbGl2ZS5ubD4gClN1YmplY3Q6IERpdCBpcyBlZW4gdGVzdAoKVGhpcyBpcyBh\nIG1lc3NhZ2UganVzdCB0byBzYXkgaGVsbG8uIFNvLCAiSGVsbG8iLg==";

                try
                {
                    //var result = service.Users.Messages.Send(m, "bestuur@indicium.hu").Execute();

                    var result = service.Users.Messages.List("bestuur@indicium.hu").Execute();

                    debugMessage += "Send email: " + result;
                }
                catch (Exception e)
                {
                    debugMessage += e.Message;
                    //throw;
                }


                debugMessage += "The END!";
            }

            return Content(debugMessage);
        }

我在 api explorer 中测试了 base 64 原始字符串,它在那里工作!所以我想这不是问题。有人可以帮我解决这个问题,我越来越绝望。顺便说一句,我们为非营利组织使用免费版本的 G 套件(这会造成问题吗?)。

【问题讨论】:

    标签: c# google-api asp.net-core-mvc google-oauth gmail-api


    【解决方案1】:

    我也在为同样的问题而苦苦挣扎,但我的原因略有不同。您仍然需要遵循@botenvouwer 列出的步骤

    我有这段代码,我从文档中获取,但没有工作并给出提到的错误:

                ServiceAccountCredential credential;
    
                using (Stream stream = new FileStream(serviceAccountCredentialFilePath, FileMode.Open, FileAccess.Read))
                {
                    credential = GoogleCredential.FromStream(stream).CreateScoped(scopes).UnderlyingCredential as ServiceAccountCredential;
                }
    
                // Create the  Calendar service.
                return new GmailService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "isatisservice",
                });
    

    我忘记的部分是在创建服务时指定要为哪个用户使用它。您不能在调用 API 时指定用户,但必须在此处指定:

                credential = GoogleCredential.FromStream(stream).CreateScoped(scopes).CreateWithUser("user@yourdomain.com").UnderlyingCredential as ServiceAccountCredential;
    

    所以它在 CreateWithUser 部分。添加后,它就开始工作了。

    请注意,电子邮件地址是您要访问的域用户的地址。所以不是您的服务帐户电子邮件。

    【讨论】:

      【解决方案2】:

      为了帮助@Yeronimo,特此回答(希望对您有所帮助):

      设置

      这是实现中最重要的部分。重要的是要了解 G Suite 帐户和普通 Google 帐户之间存在巨大差异。您需要 G Suite 的管理员帐户才能进行设置。

      第 1 步

      !重要!使用谷歌套件的管理员帐户完成所有步骤!

      转到google developers console 并设置您的项目和 api 密钥,这是我做了几次但没有成功。但我做对了。这是随处可见的。

      • 创建新项目
      • 创建服务帐号
      • 等等..

      第 2 步

      转到google G suite admin 页面并为您的 G 套件设置权限。

      • 转到 Api-rights(我有一个荷兰语控制台 -> 所以我只是尝试翻译)
      • 开启你要使用的api
      • 相信内部应用

      • 然后转到高级设置(这被愚蠢地隐藏了)
      • 在那里您可以转到类似以下内容的页面:维护 api-client 访问权限
      • 去那里
      • 使用您要使用的 api 端点添加 serviceaccount 客户端 ID

      您可以在此处找到客户端 ID:console.developers.google.com -> 登录 -> 服务帐户 -> 维护服务帐户 -> 选项 -> 显示客户端 ID。

      我给你我的截图,这样你就可以找到它。我无法将控制台设置为英语。

      然后复制该客户端 ID 并使用它。还可以找到您需要的端点here

      提示!查看更多详细步骤here

      使用 google 文档中的代码

      使用json或证书文件进行授权。这取决于您使用的是哪个库。我使用 c# 的 lib,所以我必须使用证书文件。在为您的服务帐户创建凭据时,您可以选择。请注意,您可能需要一段时间才能使用服务帐户。我以为它不起作用,而 5 分钟后它突然起作用了。这很烦人,但当它最终起作用时,它就像一个魅力。

      如果您需要代码方面的帮助或其他问题,请咨询我。我试图尽快回答。希望对您有所帮助。

      【讨论】:

      • 我的控制台等也是荷兰语 ;-) 所以不用担心。我会尽快检查这个!除了“信任内部应用程序”之外,我想我做了所有这些。
      • 好的,如果您需要更多帮助,请告诉我。
      • 到目前为止还没有运气。我什至换成了P12版本。 Google 在最新版本中添加了 json 支持。但 p12 也不起作用。同一个服务帐户实际上可以完全控制日历 API。唯一的问题是,用户仍然必须与服务电子邮件地址(以 iam.gserviceaccount.com 结尾)共享他们的日历。 gmail是否有用户需要允许的东西?
      • 我成功了。 Google 记录的 FromStream 选项不包括我通过设置 User 属性在您的 P12 解决方案中找到的模拟部分。将使用我的 JSON 和模拟代码发布答案。
      猜你喜欢
      • 2020-05-26
      • 2021-06-10
      • 1970-01-01
      • 2018-11-05
      • 1970-01-01
      • 1970-01-01
      • 2022-08-15
      • 2017-01-08
      • 2020-05-27
      相关资源
      最近更新 更多