邮件附件错误的媒体类型 Gmail API

IT技术 javascript ajax email gmail-api
2021-03-15 17:42:17

我正在尝试通过 Javascript 客户端中的 Gmail API 发送带有 jpeg 文件的消息。到目前为止,我编写的代码如下:

$.ajax({
  type: "POST",
  url: "https://www.googleapis.com/upload/gmail/v1/users/me/messages/send?uploadType=multipart",
  headers: {
    'Authorization': 'Bearer ' + accessToken,
    'Content-Type': 'multipart/related; boundary="foo_bar_baz"'
  },
  data: data
});

data这里找到的示例那样构建的字符串在哪里

--foo_bar_baz
Content-Type: application/json; charset=UTF-8

{ 
  "raw": "RnJvbTogRW1pbCBUaG9saW4gPGVtdGhvbGluQGdtYWlsLmNvbT4KVG86IEV4YW1wbGUgTmFtZSA8ZW10aG9saW5AZ21haWwuY29tPgpTdWJqZWN0OiBzZHNkCgpzZHNk"
}

--foo_bar_baz
Content-Type: image/jpeg

data:image_jpeg;base64,_9j_4AAQSkZJRgABAQEAYABgAAD_2wBDAAIBAQIBAQICAgICAgIC…bHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3-Pn6_9oADAMBAAIRAxEAPwD-f-iiigD_2Q==

--foo_bar_baz--

我得到的错误是Media type 'image/jpeg' is not supported. Valid media types: [message/rfc822],这是可以理解的,因为[message/rfc822]根据规范是媒体的唯一有效 MIME 类型,但上面链接的示例另有说明。

我究竟做错了什么?如果有人能对此有所了解,将不胜感激!

2个回答

编辑

第一段代码适用于合并大小为几 mb 的附件。如果您想使用 35 mb 的允许限制,请检查答案末尾的编辑。


在史蒂夫将我推向正确的方向后(整个邮件必须在“原始”参数中),我只是尝试了 Python API 并查看了由此生成的邮件。

不带附件的邮件

Content-Type: text/plain; charset="UTF-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
to: receiver@gmail.com
from: sender@gmail.com
subject: Subject Text

The actual message text goes here

带附件的邮件

Content-Type: multipart/mixed; boundary="foo_bar_baz"
MIME-Version: 1.0
to: receiver@gmail.com
from: sender@gmail.com
subject: Subject Text

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

The actual message text goes here

--foo_bar_baz
Content-Type: image/jpeg
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="example.jpg"

{JPEG data}

--foo_bar_baz--

所以我只是围绕这个写了我的代码,而且效果很好!

var reader = new FileReader();
reader.readAsDataURL(attachment);
reader.onloadend = function (e) {
  // The relevant base64-encoding comes after "base64,"
  var jpegData = e.target.result.split('base64,')[1];
  var mail = [
    'Content-Type: multipart/mixed; boundary="foo_bar_baz"\r\n',
    'MIME-Version: 1.0\r\n',
    'to: receiver@gmail.com\r\n',
    'from: sender@gmail.com\r\n',
    'subject: Subject Text\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\r\n',

    '--foo_bar_baz\r\n',
    'Content-Type: image/jpeg\r\n',
    'MIME-Version: 1.0\r\n',
    'Content-Transfer-Encoding: base64\r\n',
    'Content-Disposition: attachment; filename="example.jpg"\r\n\r\n',

    jpegData, '\r\n\r\n',

    '--foo_bar_baz--'
  ].join('');

  // The Gmail API requires url safe Base64 
  // (replace '+' with '-', replace '/' with '_', remove trailing '=')
  mail = btoa(mail).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');

  $.ajax({
    type: "POST",
    url: "https://www.googleapis.com/gmail/v1/users/me/messages/send",
    headers: {
      'Authorization': 'Bearer ' + accessToken,
      'Content-Type': 'application/json'
    },
    data: JSON.stringify({
      raw: mail
    })
  });
}

编辑

上面的代码有效,但需要进行一些更改才能使用 35 mb 的最大限制。

Mail with attachment标题下的邮件为例,更改后的 ajax-request 如下所示:

$.ajax({
  type: "POST",
  url: "https://www.googleapis.com/gmail/v1/users/me/messages/send?uploadType=multipart",
  headers: {
    'Authorization': 'Bearer ' + accessToken,
    'Content-Type': 'message/rfc822'
  },
  data: mail
}); 

Content-Type现在message/rfc822,而不是application/json,网址已经得到了新的参数uploadType=multipart,而且最重要的邮件不再是Base64编码,但在提供rfc822-format。

我有同样的问题,但在服务器上。您知道我应该查看哪个节点库吗?
2021-04-21 17:42:17
@goatmeal 您可以使用OAuth Playground进行测试。只需在左侧列表中选择 Gmail API,然后按照概述的步骤获取令牌。
2021-05-09 17:42:17
我为nodejs修改了这段代码。效果很好。谢谢你的帮助。:)
2021-05-10 17:42:17
如何获得我的“accessToken”?
2021-05-14 17:42:17
边界后的双新行是非法的。试图编辑,但 stackoverflow 不允许编辑 6 个字符以下...
2021-05-15 17:42:17

这些文档有点令人困惑,因为上传文档是关于上传如何与 Google API 一起工作的通用说明,并且该示例不太适合 gmail。也就是说,有更详细的解释说明如何使用涵盖它的 gmail API 发送邮件和附件

简而言之,附件需要在发送之前在原始消息本身中进行编码。

也许我应该在我的问题中更具体。我正在尝试做这个客户端,因此您刚刚链接的酷库将无法正常工作。你有另一张卡片吗?
2021-04-17 17:42:17
是的,没有图书馆会有点痛苦。对于 JS,您可以使用github.com/connrs/node-email-stream来构建原始消息。
2021-04-27 17:42:17
谢谢你的回复史蒂夫!我还是不太明白,因为简洁的 python API 抽象了一些我需要在 Javascript 中的常规 Ajax 调用中手动执行的操作。我需要在这个问题的答案中添加很多内容才能在邮件中获取附件吗?stackoverflow.com/questions/24460422/...我用他的方法处理没有附件的邮件,效果很好!
2021-04-28 17:42:17
一种选择是仅使用 browserify 将其打包以在客户端上使用。或者只是根据需要从那里借用代码。
2021-05-14 17:42:18