使用适用于 G Suite 的 google Gmail api 时下降的前提条件
Posted
技术标签:
【中文标题】使用适用于 G Suite 的 google Gmail api 时下降的前提条件【英文标题】:Faling precondition while using google Gmail api for Gsuite 【发布时间】:2018-07-08 19:09:14 【问题描述】:试图完成这项工作,我完全发疯了。我需要使用 gmail api 从我们的域发送邮件。每次我得到这个结果时:
Google.Apis.Requests.RequestError
Bad Request [400]
Errors [
Message[Bad Request] Location[ - ] Reason[failedPrecondition] Domain[global]
]
我快疯了!
我已经阅读了所有这些,但我仍然没有弄清楚:
https://developers.google.com/admin-sdk/reports/v1/guides/delegation https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth#service-account Can we access GMAIL API using Service Account? Gmail REST API : 400 Bad Request + Failed Precondition如何让它发挥作用?
这些是我已经完成的步骤:
-
在 console.developers.google.com 中创建了一个新项目
启用 gmail api
创建了服务帐号
为服务帐号创建了 key.p12 文件
已配置域范围的权限
在 admin.google.com 中启用了 gmail api
在 security->advanced->Api accesses 中添加了 api 范围
添加并验证了我的域名
屏幕:
这是我的代码:
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 套件(这会造成问题吗?)。
【问题讨论】:
【参考方案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 和模拟代码发布答案。以上是关于使用适用于 G Suite 的 google Gmail api 时下降的前提条件的主要内容,如果未能解决你的问题,请参考以下文章
Asp.Net Core google-signin oauth 限制访问并获取 g-suite 角色
G Suite帐户在Calendar API中缺少displayName参数
Google Apps/G Suite/Google Workspace for MailChimp 上的多个 DKIM 和 SPF 记录