2
votes

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
Have you tried it with an actual email address instead of :userId => 'me'? From their docs: "The special value 'me' can be used to indicate the authenticated user." I'm wondering if your user is not authenticated (I can't tell because I assume that happens as part of creating api_client) - supremebeing7
This may or may not be helpful as well: stackoverflow.com/a/43684252/3477163 - supremebeing7
@Tholle - thanks so much! The issue was that when using multipart uploadType, the body of the request should not be base64 encoded, which I don't think is mentioned anywhere in the docs sadly. - jwg2s

1 Answers

2
votes

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',
    }
  )