【问题标题】:Batch Request - SendAs Emails批量请求 - SendAs 电子邮件
【发布时间】:2019-03-01 12:14:42
【问题描述】:

有没有办法进行批量请求以获取来自多个或所有用户的 SendAs 电子邮件?

目前我们正在使用模拟用户的服务帐户来遍历每个用户并获取 SendAs 电子邮件列表 - 大量请求。

  1. GmailService 即服务 - 这被冒充为用户。
  2. service.Users.Settings.SendAs.List("me").Execute();

附:我在 google 群组中发布了这个,但刚刚阅读了一篇帖子,上面说论坛现在是只读的!奇怪的是它允许我发一个新帖子(显然我认为这个帖子必须被批准)

谢谢!

    static string[] Scopes = {  GmailService.Scope.MailGoogleCom,
                                GmailService.Scope.GmailSettingsBasic,
                                GmailService.Scope.GmailSettingsSharing,
                                GmailService.Scope.GmailModify};

    /// <summary>
    /// Gets default send as email address from user's gmail - throws error if valid domain is not used as default sendAs
    /// </summary>
    /// <param name="primaryEmailAddress">User's email address to use to impersonate</param>
    /// <param name="excludedDomains">Domains to exclude in the results - example: @xyz.org</param>
    /// <returns>default SendAs email address</returns>
    public static string GetDefaultSendAs(string primaryEmailAddress, string[] excludedDomains)
    {
        string retVal = string.Empty;
        GmailService service = new GmailService(new BaseClientService.Initializer()
        {
            HttpClientInitializer = 
                Auth.GetServiceAccountAuthorization
                    (scopes: Scopes, clientSecretFilePath: Constant.ClientSecretFilePath, impersonateAs: primaryEmailAddress)
        });


        var result = service.Users.Settings.SendAs.List("me").Execute();

        SendAs s = result.SendAs.First(e => e.IsDefault == true);
        bool incorrectSendAs = false;

        if (s != null)
        {
            foreach (string domain in excludedDomains)
            {
                // Check if email ends with domain
                if (s.SendAsEmail.ToLower().EndsWith("@" + domain.TrimStart('@'))) // removes @ and adds back - makes sure to domain start with @.
                {
                    incorrectSendAs = true;
                }
            }             
        }

        if (s != null && !incorrectSendAs)
            retVal = s.SendAsEmail;
        else
            throw new Exception($"{primaryEmailAddress}, valid default SendAs email not set."); 

        System.Threading.Thread.Sleep(10);

        return retVal;
    }

授权码:

class Auth
{
    internal static ServiceAccountCredential GetServiceAccountAuthorization(string[]scopes, string clientSecretFilePath, string impersonateAs = "admin@xyz.org")
    {
        ServiceAccountCredential retval;

        if (impersonateAs == null || impersonateAs == string.Empty)
        {
            throw new Exception("Please provide user to impersonate");
        }
        else
        {

            using (var stream = new FileStream(clientSecretFilePath, FileMode.Open, FileAccess.Read))
            {
                retval = GoogleCredential.FromStream(stream)
                                             .CreateScoped(scopes)
                                             .CreateWithUser(impersonateAs)
                                             .UnderlyingCredential as ServiceAccountCredential;
            }
        }

        return retval;
    }

API 客户端访问:

【问题讨论】:

  • 请编辑您的问题并附上您的授权码。我想看看您是如何使用服务帐户登录的。如果您不介意,我希望看到 gsuite 的一些屏幕截图,您可以在其中设置服务帐户的域委派,随时将不应该共享的内容留空。
  • 更新了!谢谢!
  • 管理员可以看到其他用户的 SendAs 电子邮件地址吗?也许我们只需要使用一些企业级管理员用户来模拟。
  • x 我的最后一条评论 - 如果我们尝试使用企业管理员获取其他用户的 SendAs,则会收到委托错误。错误:消息[Delegation denied for admin@xyz.org] Location[-] Reason[forbidden] Domain[global]
  • 感谢您发布您的代码,多年来我一直在寻找用户模拟的示例。问题出现了,我没有一个可以链接的工作示例,因为我不再可以访问 gusite 帐户。您的代码将来可能会对其他人有所帮助。

标签: c# google-api-dotnet-client service-accounts google-workspace


【解决方案1】:

批处理注意事项

首先我要问你为什么要使用批处理。如果您希望它可以节省您的配额使用量,那么批处理不会受到与正常 api 调用相同的配额使用量的影响。批处理能给你的唯一帮助是发送更少的 HTTP 调用,并在那里花费一些东西。

您的客户端进行的每个 HTTP 连接都会产生一定的开销。某些 Google API 支持批处理,以允许您的客户端将多个 API 调用放入单个 HTTP 请求中。

外部批次请求的 HTTP 标头(Content-Type 等 Content-标头除外)适用于批次中的每个请求。如果您在外部请求和单个调用中都指定了给定的 HTTP 标头,则单个调用标头的值将覆盖外部批处理请求标头的值。单个调用的标头仅适用于该调用。

例如,如果您为特定调用提供授权标头,则该标头仅适用于该调用。如果您为外部请求提供 Authorization 标头,则该标头适用于所有单独的调用,除非它们使用自己的 Authorization 标头覆盖它。

授权

当您向某个 API 授权时,该授权是针对单个用户的。

GmailService service = new GmailService(new BaseClientService.Initializer()
    {
        HttpClientInitializer = 
            Auth.GetServiceAccountAuthorization
                (scopes: Scopes, clientSecretFilePath: Constant.ClientSecretFilePath, impersonateAs: primaryEmailAddress)
    });

上述服务将只能访问您所冒充的那个用户的数据。

Anwser

有没有办法进行批量请求以获取来自多个或所有用户的 SendAs 电子邮件?

不,没有。正如您从上面所读到的,批处理请求的授权标头涵盖了批处理中的所有项目。与 GmailService 一起为您的批处理请求创建的授权标头仅涵盖单个用户。

【讨论】:

  • 原因可能是请求过多或时间过长。如果我们需要获取 1000 个用户的 SendAs 列表,这将是 1000 个请求并且它需要永远(约 3 分钟 40 秒。)我没想到有一种方法可以在批处理请求中获取所有用户的电子邮件设置列表,但是不得不问以防万一。听起来好像没有,所以我们可能会缓存 SendAs 供以后使用。
  • 下一个问题是我们应该如何处理更新缓存,因为当 SendAs 更改时,我们在 Data.User 中看不到 DateUpdated 字段,这完全有意义,因为邮件和用户完全不同的实体。有什么建议吗?
  • 防洪配额无论如何都会阻止你快速前进。
  • 我认为没有办法让批处理请求与多个用户一起工作。无论如何,我从来没有看到批处理有什么意义。欢迎您留下问题,看看是否有其他人回应。但是,如果您查看我的个人资料,我想您会注意到我是回答大多数 google api 问题的人 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 2013-02-10
  • 2019-03-11
  • 1970-01-01
  • 1970-01-01
  • 2021-02-08
相关资源
最近更新 更多