使用带有 Gmail API 的可恢复上传附加文件

Posted

技术标签:

【中文标题】使用带有 Gmail API 的可恢复上传附加文件【英文标题】:Attaching a file using Resumable upload w/ Gmail API 【发布时间】:2017-06-11 08:59:23 【问题描述】:

我正在尝试使用 Gmail 的可恢复选项将附件上传到电子邮件。文档参考:https://developers.google.com/gmail/api/guides/uploads#resumable.

目前我可以使用可恢复的 URI 发送电子邮件,但没有附件(使用 Postman)。文档没有提供关于请求具体应该是什么样子的非常清晰的示例,并且在搜索互联网后似乎没有很多示例。

我的请求分为两部分:

    初始请求 -

    Request URL:
    POST /upload/gmail/v1/users/me/messages/send?uploadType=resumable
    Host: www.googleapis.c om (can't post links so I interrupted the url)
    
    Headers: 
    Authorization: Bearer my_token_here
    Content-Length: 113
    Content-Type: application/json
    X-Upload-Content-Length: 67
    X-Upload-Content-Type: message/rfc822
    
    Body:
    "raw":"VG86IG5pcnZhbmEucm9ja2VyQGdtYWlsLmNvbQpTdWJqZWN0OiBUZXN0RW1haWxTdWJqZWN0MwoKTWVzc2FnZSBjb250ZW50cyAjMy4"
    

正文是包含收件人、主题和电子邮件内容的 64 位编码字符串。然后Gmail会返回一个空体的响应,和一个“位置”报头看起来如下:googleapis.com/upload/gmail/v1/users/me/messages/send?uploadType=resumable&upload_id=BRnB2UoAsKwzNMoQAy-JtmP6mu5agltqOWZ9uerI3k-KNTDJ73PWEjKuAHpko4RN6weSEysddH2kjj4G24uFw6E9oPv1XP69l7_KcmNuW- RAoz_5oS1T_4_E。 (删除了 https:// 因为这个账号在帖子中只能有一个链接)

然后,我向位置标头中返回的那个 URL 发出 PUT 请求。

    第二个请求如下所示:

    Request URL: 
    PUT /upload/gmail/v1/users/me/messages/send?uploadType=resumable&upload_id=BRnB2UoAsKwzNMoQAy-JtmP6mu5agltqOWZ9uerI3k-KNTDJ73PWEjKuAHpko4RN6weSEysddH2kjj4G24uFw6E9oPv1XP69l7_KcmNuW-RAoz_5oS1T_4_E
    Host: www.googleapis.c om
    
    Headers: 
    Content-Length: 67
    Content-Type: message/rfc822
    
    Body:
    "raw":"VG86IG5pcnZhbmEucm9ja2VyQGdtYWlsLmNvbQpTdWJqZWN0OiBUZXN0RW1haWxTdWJqZWN0MwoKTWVzc2FnZSBjb250ZW50cyAjMy4"
    --- OR ---
    I choose the binary option, and attach the file I am looking to upload via Postman.
    

我收到来自 Gmail 的回复,其中包含如下对象:

    
      "id": "159d7ded3125e255",
      "threadId": "159d7ded3125e255",
      "labelIds": [
        "SENT"
      ]
    

电子邮件已成功发送,但电子邮件中没有附件。当我在 Gmail 中显示原始电子邮件时,没有任何附件证据。原文如下:

    Received: from 325276275830 named unknown by gmailapi.google.com with HTTPREST; Wed, 25 Jan 2017 15:03:33 -0800
    To: some.name@gmail.com
    Subject: TestEmailSubject3
    Date: Wed, 25 Jan 2017 15:03:33 -0800
    Message-Id: <CEROA6F=0ohk33RD9XyC_gW1DZO88xYF4bXYqrCSct62MUuytDw@mail.gmail.com>
    From: name_here@gmail.com

    Message contents #3.

我错过了什么?我是否需要以不同的方式对某些特定内容进行编码,或者将某些数据放在不同的位置?我没有收到任何错误。我已经研究了几天了,我就是想不通。

【问题讨论】:

尝试使用相关SO post 中的代码,它是多部分的,但它可以帮助您了解附件的工作原理。希望这会有所帮助。 Rebot 先生 - 感谢您的回复。我还没有找到一个可行的解决方案。我已经能够获得一个可恢复的请求来上传文件并成功通过电子邮件发送它 - 但是这是当启动请求为空并且我在以下请求中发送了一个完全组合的消息/rfc822 格式的消息时,包括一个 base64 编码的文件。 Content-Type: multipart/mixed; boundary=foo_bar_baz MIME-Version: 1.0 to: nirvana.rocker@gmail.com from: drew@azuqua.com subject: File with attachment - Resumable Upload --foo_bar_baz Content-Type: text/plain; charset=UTF-8 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit This is supposed to be the email message! --foo_bar_baz Content-Type: image/jpeg MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename=BIG_PUPPY_PIC.jpg encoded_file_went_here_jkl4fliq43jga43gai --foo_bar_baz-- 这就是我的消息正文在请求中的样子 - 抱歉,它很丑,cmets 不会让我正确格式化。这遵循与我在问题中的原始示例相同的语法。重要的是,我能够通过在原始请求中发送电子邮件的元数据来上传附件,然后在以下请求中仅发送文件内容。 gmail 文档在他们的示例请求中明确演示了这种语法。令人惊讶的是,人们在网上查找此内容的示例非常少。即使在这里,也只有几个问题,没有答案。 【参考方案1】:

我遇到了同样的问题,我使用 Nodemailer 创建带有附件的电子邮件,将结果保存到文件中,然后使用 this 上传。

【讨论】:

【参考方案2】:

您可以将所有电子邮件数据和附件数据作为 mime 消息发送,而不是分两部分发送电子邮件。像这样。

我正在使用 javascript 客户端,所以你可以这样做:


// MIME Mail Message data.
let mail = [
  'Content-Type: multipart/mixed; boundary="foo_bar_baz"\r\n',
  "MIME-Version: 1.0\r\n",
  "to: to@gmail.com\r\n",
  "from: from@gmail.com\r\n",
  "subject: i am subject\r\n\r\n",

  "--foo_bar_baz\r\n",
  'Content-Type: text/plain; charset="UTF-8"\r\n',
  "MIME-Version: 1.0\r\n",
  "Content-Transfer-Encoding: 7bit\r\n\r\n",

  "The actual message text goes here\r\n",
  "--foo_bar_baz\r\n",
  "Content-Type: application/json; name=package.json\r\n",
  "Content-Transfer-Encoding: base64\r\n",
  "Content-Disposition: attachment; filename=package.json\r\n\r\n",

  "<base64 file data. data according to content type>",
  "\r\n",
  "--foo_bar_baz--",
].join("");

// get resumable upload link.
let resumableURL = "";
gapi.client
    .request(
      path: "/upload/gmail/v1/users/me/messages/send?uploadType=resumable",
      headers: 
        "X-Upload-Content-Type": "message/rfc822",
      ,
      method: "post",
    )
    .then(
      (res) => 
        resumableURL = res.headers.location;
        console.log(res);
      ,
      (err) => console.log(err)
    );

// send email
gapi.client
    .request(
      path: resumableURL,
      headers: 
        "Content-Type": "message/rfc822",
      ,
      method: "post",
      body: mail,
    )
    .then(
      (res) => 
        console.log(res);
      ,
      (err) => console.log(err)
    );

要将gapi.client.request 转换为Fetch API 调用,您只需将Authorization: Bearer &lt;access_token&gt; 添加到标题字段。我曾尝试使用 Fetch API,但由于 cors 错误导致响应被阻止,因此应使用像 Postman 这样的 api 客户端。

更多关于可恢复上传方法检查文档:Upload Attachment

【讨论】:

以上是关于使用带有 Gmail API 的可恢复上传附加文件的主要内容,如果未能解决你的问题,请参考以下文章

如何将带有附加数据的 FormData 文件发送到 asp.net web api ajax 调用

Gmail“无法附加空文件”

createWriteStream Node.js 上的可恢复和验证

用于发送带有附件的电子邮件的 GMAIL API

使用 Gmail API 发送的邮件中缺少附件,但仅适用于收件人

在 Javascript 中使用 GMAIL API 发送带有附件文件(超过 10 MB)的电子邮件