Manuel Serrenti
Manuel Serrenti

Reputation: 41

search messages with Gmail API in Google Apps Script

i've searched through StackOverflow with (small) success, so I ask help to a more expert coder than me.

I've read this topic on SO gmailapp-add-label-to-specific-message-not-the-thread which leads me to this GIST, where I've taken the code for labelling a single message (and not the entire thread).

Now i need to use the search functions of the Gmail API in Google Apps Script; I've found a Javascript snippet on Google Developer's Site here. I'm trying to adapt this code using the code found in GIST as example, but without success.

I need the search function to get an array of message ID's to pass to another function (that works, for now ;) ).

Here's the code I've wrote:

/**
 * Retrieve Messages in user's mailbox matching query.
 *
 * @param  {String} userId User's email address. The special value 'me'
 * can be used to indicate the authenticated user.
 * @param  {String} query String used to filter the Messages listed.
 * @param  {Function} callback Function to call when the request is complete.
 */
function GAPIlistMessages(userId, query) { //callback option removed from original code

 // GET https://www.googleapis.com/gmail/v1/users/userId/messages
  var url = 'https://www.googleapis.com/gmail/v1/users/${userId}/messages'
  .replace("${userId}","me")
            var headers = {
    Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
  };

    var request = {
      'userId': userId,
      'q': query
  };

  var params = {
    method: "GET",
    contentType: "application/json",
    headers: headers,
    muteHttpExceptions: true, // for debugging
    payload: JSON.stringify(request)
    };

  var check = UrlFetchApp.getRequest(url, params); // for debugging
  var response = UrlFetchApp.fetch(url, params);

  var result = response.getResponseCode();
  if (result == '200') {  // OK
    var msgIds = JSON.parse(response.getContentText()).msgIds;
  Logger.log(msgIds)
  }
  else {
    // This is only needed when muteHttpExceptions == true
    var err = JSON.parse(response.getContentText());
    throw new Error( 'Error (' + result + ") " + err.error.message );
  } 
}

When i launch the function, passing this parameters: userId = 'me' query = 'deliveredto:[email protected]'

I receive this error

[16-02-24 06:37:29:218 PST] Avvio dell'esecuzione
[16-02-24 06:37:29:236 PST] ScriptApp.getOAuthToken() [0 secondi]
[16-02-24 06:37:29:237 PST] UrlFetchApp.getRequest([https://www.googleapis.com/gmail/v1/users/me/messages, {headers={Authorization=Bearer <<<token removed>>>}, method=GET, payload={"userId":"me",...) [0 secondi]
[16-02-24 06:37:29:308 PST] UrlFetchApp.fetch([https://www.googleapis.com/gmail/v1/users/me/messages, {headers={Authorization=Bearer <<<token removed>>>}, method=GET, payload={"userId":"me",...) [0,07 secondi]
[16-02-24 06:37:29:308 PST] HTTPResponse.getResponseCode() [0 secondi]
[16-02-24 06:37:29:308 PST] HTTPResponse.getContentText() [0 secondi]
[16-02-24 06:37:29:311 PST] Esecuzione non riuscita: Error: Error (400) 'raw' RFC822 payload message string or uploading message via /upload/* URL required (riga 212, file "Test Tools") [0,075 secondi di esecuzione totale]

I feel that I'm close to the solution, but I can't figure out where is the problem. Any help would be VERY appreciated

Manuel

Upvotes: 0

Views: 1755

Answers (2)

Manuel Serrenti
Manuel Serrenti

Reputation: 41

Thanks for the comments, I've found the solution and rewrite the code:

function GAPIlistMessages(userId, query) {
  var url = 'https://www.googleapis.com/gmail/v1/users/'+userId+'/messages'+'?q='+query+'&fields=messages%2Fid' // JSON array of message ID
  var headers = {
    Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
  };

  var params = {
    method: "GET",
    contentType: "application/json",
    headers: headers,
    muteHttpExceptions: true, // for debugging 
    };

  var check = UrlFetchApp.getRequest(url, params); // for debugging
  var response = UrlFetchApp.fetch(url, params);

  var result = response.getResponseCode();
  if (result == '200') {  // OK
    var msgIds = JSON.parse(response.getContentText());
    //Logger.log(response.getContentText())
  return msgIds;

  }
  else {
    // This is only needed when muteHttpExceptions == true
    var err = JSON.parse(response.getContentText());
    throw new Error( 'Error (' + result + ") " + err.error.message );
  }
}

Now I can retrieve all the message IDs for the given query and pass that list to another function for extracting attachments + other tasks. The real advantage of this approach is that i can work on single messages, instead of working on entire threads using the simple GAS commands.

Upvotes: 2

Tholle
Tholle

Reputation: 112787

If you look at the documentation, it says that the payload is the body of the request. Your query should not be in the body, but a query string parameter:

function GAPIlistMessages(query) { 
  var url = 'https://www.googleapis.com/gmail/v1/users/me/messages?q=' + 
    encodeURIComponent(query)

  var response = UrlFetchApp.getRequest(url, {
    headers: {
      Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
    }
  });
}

Upvotes: 2

Related Questions