Gmail API C# 桌面应用程序中草稿的可恢复上传

Gmail API Resumable Upload for Drafts in C# Desktop Application

我编写了一个 C# WinForms 应用程序,它使用 Gmail API 创建带有附件的邮件草稿并将它们上传到 Gmail。直到几个月前,这一直运作良好。这是代码:

var service = new GmailService(new BaseClientService.Initializer()
{
    HttpClientInitializer = credential,
    ApplicationName = ApplicationName,
});

MailMessage msg = new MailMessage();
msg.IsBodyHtml = true;
Attachment file = new Attachment(FileLocation);
msg.Attachments.Add(file);

MimeMessage messageMIME = MimeMessage.CreateFromMailMessage(msg); //using MimeKit here

Google.Apis.Gmail.v1.Data.Message m = new Google.Apis.Gmail.v1.Data.Message();

m.Raw = Base64UrlEncode(messageMIME); //private method for Convert.ToBase64String
Draft draft = new Draft();
draft.Message = m;
service.Users.Drafts.Create(draft, "me").Execute();

以上代码现在仅在草稿邮件大小小于 1 MB 时有效。当 message/attachment 超过此限制时,代码现在会发出此错误:

Google.GoogleApiException: Google.Apis.Requests.RequestError
Request payload size exceeds the limit: 1048576 bytes. [400]

我认为 Google 更改了它的 API 现在需要使用 resumable upload protocol 上传附件超过 1 MB 的草稿。

现在上面代码片段的最后一行有一个重载

service.Users.Drafts.Create(draft, "me", stream, @"message/rfc822");

使用 CreateMediaUpload Class Reference,它允许支持断点续传协议的上传。但是,无论我如何创建草稿正文或对流进行编码,我都无法正确使用此重载来创建和上传任何大小的草稿。构建我的代码以使此重载起作用的正确方法是什么?或者是否有其他方法可以使用来自 Gmail API 的可恢复上传协议从 C# 桌面应用程序上传带有附件的草稿消息?非常感谢所有帮助。

更新

如果我去掉添加附件的两行代码,这行代码:

service.Users.Drafts.Create(draft, "me", stream, @"message/rfc822").Upload();

将在 Gmail 中创建带有正文的草稿。但是,我想不出任何东西都可以使用此重载创建 and/or 流式传输草稿的附件。我尝试过使用多部分 MIME 消息、文件流、内存流,并尝试在附件中使用和不使用 base64 编码。感谢您阅读到这里。

今天早上之前,我从未在 C# 中使用过 Google Gmail api,所以我对你的问题很感兴趣。我复制了您的附件问题,并使用下面的代码通过包含附件的成功测试电子邮件解决了它,所以您应该可以开始了(如果是这样,请标记为已解决,或者如果您仍然遇到问题,请在评论中告诉我,并且我再看看。

基本上,我所做的是

  1. 使用将流对象作为参数的 Create() 方法的不同重载。
  2. 这个不同的重载是一个函数,returns一个 CreateMediaUpload 类型。
  3. 此 CreateMediaUpload 类型有一个上传(和上传异步)方法,它支持后台可恢复上传,从而绕过了原始消息大小限制。

我发送的测试文件是 1.6 兆字节,比您(和我)之前收到的请求负载最大阈值高得多。

祝您邮件愉快!再一次,如果您仍然有问题,请在评论中告诉我……我也会在将其投入任何生产之前删除最后的调试/秒表/发送内容。它只是用于测试。

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


        var file = new Attachment(FileLocation);

        MailMessage msg = new MailMessage();
        msg.IsBodyHtml = true;
        msg.Attachments.Add(file);
        msg.Body = "Tester Body";
        msg.To.Add("MyTestDestinationEmailAddress@Gmail.com");

        MimeMessage messageMIME = MimeMessage.CreateFromMailMessage(msg); //using MimeKit here
         MemoryStream memory = new MemoryStream();
        messageMIME.WriteTo(memory);


        Draft draft = new Draft();

        var createRequest = service.Users.Drafts.Create(draft, "me", memory, @"message/rfc822");


        var startTime = Stopwatch.StartNew();
        var uploadProgress = createRequest.Upload();

        if (uploadProgress.Status == UploadStatus.Completed)
        {
            Debug.WriteLine(String.Format("Elapsed Time: {0}", startTime.Elapsed));
            Debug.WriteLine(String.Format("Status: {0}", uploadProgress.Status.ToString()));
            Debug.WriteLine(String.Format("Bytes Sent: {0}", uploadProgress.BytesSent));

            //to send the draft email, uncomment the lines below

            //draft = createRequest.ResponseBody;
            //var send =  service.Users.Drafts.Send(draft, "me");
            //send.Execute();

        }
        else
        {
            Debug.WriteLine(String.Format("Exception: {0}", uploadProgress.Exception.Message));
        }