1

I am trying the gmail apis. I've done the auth. Now I want to create a draft. But I am getting this error

{ error: 
I20161220-15:53:43.486(4)?       { errors: [Object],
I20161220-15:53:43.487(4)?         code: 400,
I20161220-15:53:43.488(4)?         message: 'Media type \'application/octet-stream\' is not supported. Valid media types: [message/rfc822]' } } }

Gmail api require base64 string with rfc822 standard. I am not sure of any good way to convert a string to rfc822. How do I do that?

I am using meteor for my app and here is my code.

import { Meteor } from 'meteor/meteor'
import { HTTP } from 'meteor/http'

Meteor.startup(() => {
  // Meteor.call('createDraft')


  Meteor.methods({
    'createDraft': function () {
      console.log(this.userId)

      const user = Meteor.users.findOne(this.userId)
      const email = user.services.google.email
      console.log(email)
      const token = user.services.google.accessToken
      const dataObject = {
        message: {
          raw: CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse('dddd'))
        },
        headers: {
          Authorization: `Bearer ${token}`
        }
      }
      HTTP.post(`https://www.googleapis.com/upload/gmail/v1/users/${email}/drafts`, dataObject, (error, result) => {
        if (error) {
          console.log('err', error)
        }
        if (result) {
          console.log('res', result)
        }
      })
    }
  })
})
Hayk Safaryan
  • 1,996
  • 3
  • 29
  • 51
  • 1
    [RFC822](https://www.ietf.org/rfc/rfc0822.txt) is the good old email protocol from the early 1980s. What Gmail means (apparently) is that you need to compose a properly formatted email message, with proper headers and a valid body. It isn't complaining about the format of your strings. – Álvaro González Dec 20 '16 at 12:16

2 Answers2

1

Base64 encode the message and replace all + with -, replace all / with _, and remove the trailing = to make it URL-safe:

const rawMessage = btoa(
  "From: sender@gmail.com\r\n" +
  "To: receiver@gmail.com\r\n" +
  "Subject: Subject Text\r\n\r\n" +

  "The message text goes here"
).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')

const dataObject = {
  message: {
    raw: rawMessage
  },
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Bearer ${token}`
  }
};
Tholle
  • 108,070
  • 19
  • 198
  • 189
  • It didn't work, however I changed ` 'Content-Type': 'application/json'` to `'Content-Type': 'message/rfc822'` and it worked. Thank you. – Hayk Safaryan Dec 20 '16 at 13:16
0

I just needed to send content type as message/rfc822. Here is the working code. Note that the raw message has something wrong in ts because the draft that is created has empty content. But the draft itself is created successfully.

import { Meteor } from 'meteor/meteor'
import { HTTP } from 'meteor/http'

Meteor.startup(() => {
  // Meteor.call('createDraft')

  Meteor.methods({
    'createDraft': function () {
      console.log(this.userId)
      // CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse('dddd'))
      const user = Meteor.users.findOne(this.userId)
      const email = user.services.google.email
      console.log(email)
      const token = user.services.google.accessToken
      const rawMessage = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(
        'From: sender@gmail.com\r\n' +
        'To: receiver@gmail.com\r\n' +
        'Subject: Subject Text\r\n\r\n' +
        'The message text goes here'
      )).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')

      const dataObject = {
        message: {
          raw: rawMessage
        },
        headers: {
          'Content-Type': 'message/rfc822',
          Authorization: `Bearer ${token}`
        }
      }
      HTTP.post(`https://www.googleapis.com/upload/gmail/v1/users/${email}/drafts`, dataObject, (error, result) => {
        if (error) {
          console.log('err', error)
        }
        if (result) {
          console.log('res', result)
        }
      })
    }
  })
})
Hayk Safaryan
  • 1,996
  • 3
  • 29
  • 51