Почтовое вложение неправильный тип носителя Gmail API

Я пытаюсь отправить сообщение с прикрепленным файлом jpeg через API Gmail на стороне клиента Javascript. Код, который я написал до сих пор, выглядит следующим образом:

$.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 для носителя согласно спецификация, но в приведенном выше примере указано иное.

Что я делаю неправильно? Мы были бы очень признательны, если бы кто-нибудь мог пролить свет на это!


person Tholle    schedule 23.07.2014    source источник
comment
Я пытаюсь сделать то же самое с objective-c. Можешь мне помочь? stackoverflow.com/questions/28532808/   -  person amone    schedule 16.02.2015


Ответы (2)


РЕДАКТИРОВАТЬ

Этот первый фрагмент кода работает с вложениями общим размером в несколько мегабайт. Если вы хотите использовать разрешенный лимит в 35 мб, отметьте правку в конце ответа.


После того, как Стив подтолкнул меня в правильном направлении (вся почта должна быть в "исходном" параметре), я просто попробовал Python API и просмотрел сгенерированную им почту.

Почта без прикрепленных файлов

Content-Type: text/plain; charset="UTF-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
to: [email protected]
from: [email protected]
subject: Subject Text

The actual message text goes here

Письмо с вложением

Content-Type: multipart/mixed; boundary="foo_bar_baz"
MIME-Version: 1.0
to: [email protected]
from: [email protected]
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: [email protected]\r\n',
    'from: [email protected]\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 МБ.

Для письма, созданного как пример под заголовком Почта с вложением, измененный ajax-запрос выглядит следующим образом:

$.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, URL-адрес получил новый параметр uploadType=multipart, и, что наиболее важно, почта больше не кодируется в формате Base64, а поставляется в формате rfc822.

person Tholle    schedule 25.07.2014
comment
у меня такая же проблема, но на сервере. У вас есть идея, какую библиотеку узлов мне следует искать? - person anurag_29; 28.07.2014
comment
Я изменил этот код для nodejs. Работает отлично. Спасибо за вашу помощь. :) - person anurag_29; 29.07.2014
comment
Двойная новая строка после границы недопустима. Пытался редактировать, но stackoverflow не позволяет редактировать до 6 символов ... - person Mikael; 25.02.2015
comment
Как я могу получить свой токен доступа? - person Grant Miller; 15.05.2017
comment
@goatmeal Вы можете использовать площадку OAuth для тестирования. Просто выберите Gmail API в списке слева и следуйте инструкциям, чтобы получить токен. - person Tholle; 15.05.2017
comment
Хорошо, теперь я понимаю, что должен обменять код авторизации на токен обновления и токен доступа. Есть ли процедура Gmail Javascript API, которую можно использовать для возврата самого кода авторизации? - person Grant Miller; 15.05.2017
comment
Как кодировать прикрепленное изображение или файл, потому что у меня проблемы с кодированием изображения. Я использую java - person AJN; 10.11.2017

Документы немного сбивают с толку, поскольку документы по загрузке представляют собой общие инструкции о том, как загрузка работает с Google API, а пример не совсем подходит для Gmail. Тем не менее, есть более подробное объяснение того, как отправлять сообщения и вложения с помощью gmail API, который его покрывает.

Короче говоря, вложение необходимо закодировать в самом необработанном сообщении перед его отправкой.

person Steve Bazyl    schedule 23.07.2014
comment
Спасибо за ответ, Стив! Я все еще не совсем понимаю, поскольку аккуратный API Python абстрагирует некоторые вещи, которые мне нужно делать вручную в обычном Ajax-вызове в Javascript. Есть ли что-то, что мне нужно добавить к ответу на этот вопрос, чтобы получить вложение по почте? stackoverflow.com/questions/24460422/, я использовал его подход для письма без вложений, и он отлично сработал! - person Tholle; 23.07.2014
comment
Да, без библиотеки немного больно. Для JS вы можете использовать github.com/connrs/node-email-stream для построения необработанных сообщений. - person Steve Bazyl; 25.07.2014
comment
Может быть, мне следовало бы быть более конкретным в своем вопросе. Я пытаюсь сделать это на стороне клиента, поэтому классная библиотека, которую вы только что связали, к сожалению, не будет работать. У тебя есть еще одна карта в рукаве? - person Tholle; 25.07.2014
comment
Один из вариантов - просто использовать browserify, чтобы упаковать его для использования на клиенте. Или просто позаимствуйте код оттуда по мере необходимости. - person Steve Bazyl; 26.07.2014