Using Gmail API to Send Attachments Larger than 10

2019-08-11 14:51发布

问题:

I'm struggling to find a good example of the full set of requests necessary to send an email through the Gmail API containing an attachment larger than 10mb.

I've seen https://developers.google.com/gmail/api/v1/reference/users/messages/send and https://developers.google.com/gmail/api/guides/uploads#resumable, but there's nothing that ties it all together.

We're using the ruby client, but we're unable to complete this flow. With the following code, we get the following error trying to make the second request: Google::APIClient::ClientError: Recipient address required

The full body of the response is the following:

{"error"=>{"errors"=>[{"domain"=>"global", "reason"=>"invalidArgument", "message"=>"Recipient address required"}], "code"=>400, "message"=>"Recipient address required"}}

Here's the code used to generate the request:

raw = Base64.urlsafe_encode64 message_string
result1 = api_client.execute!(
  :api_method => gmail_api.users.messages.to_h['gmail.users.messages.send'],
  :parameters => {
    :uploadType => 'resumable',
    :userId => 'me'
  },
  :headers => {
    'Content-Type' => 'application/json',
    'X-Upload-Content-Type' => 'message/rfc822',
    'X-Upload-Content-Length' => raw.bytesize.to_s
  }
)

upload_id = result1.headers['x-guploader-uploadid']

result2 = api_client.execute!(
  :api_method => gmail_api.users.messages.to_h['upload.gmail.users.messages.send'],
  :body_object => {
    :raw => raw
  },
  :parameters => {
    :uploadType => 'resumable',
    :upload_id => upload_id,
    :userId => 'me'
  },
  :headers => {
    'Content-Type' => message.content_type,
    'Content-Length' => raw.bytesize.to_s
  }
)

回答1:

So the issue (thank you to @tholle) was that when sending attachments greater than 5mb and less than 35mb (but also works on messages without attachments), you do NOT base64 encode the body of the request, and use multipart as the uploadType. Unfortunately the docs don't mention this at all, and the error messages don't indicate that either.

Here's a working example that was able to send a 20mb attachment. Hopefully this will help anyone else who has wasted countless hours trying to figure this one out!

  result = api_client.execute!(
    :api_method => gmail_api.users.messages.to_h['gmail.users.messages.send'],
    :body => rfc822_message_string,
    :parameters => {
      :uploadType => 'multipart',
      :userId => 'me'
    },
    :headers => {
      'Content-Type' => 'message/rfc822',
    }
  )