Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
225 views
in Technique[技术] by (71.8m points)

javascript - GmailApp - Add label to specific message, not the thread

I'm building a script to automatically move my emails from one label to the next on a day by day basis (so that a message that is stored labelled "5 days" will automatically be labelled "4 days" tomorrow then "3 days" the day after that, and so on).

The problem is that it applies the label to the entire thread, not just the message - which is problematic if you have Conversation View turned off and the various emails seperated under different labels.

Here is my script (which has a daily trigger):

function moveUp(previousLabel, newLabel) {
  var threads = GmailApp.getUserLabelByName(previousLabel).getThreads()
  var numThreads = threads.length
  if (numThreads>0) {
    for(var i = 0; i < numThreads; i++) {

      if(GmailApp.getUserLabelByName(previousLabel).getThreads().length>0) {
        var lastThread = GmailApp.getUserLabelByName(previousLabel).getThreads()[0]
        GmailApp.getUserLabelByName(newLabel).addToThread(lastThread.markUnread());
        GmailApp.getUserLabelByName(previousLabel).removeFromThread(lastThread)
        Utilities.sleep(200)
      } else {
        {break;}
      }
    }
  }
}

function myFunction() {
  var threads = GmailApp.getUserLabelByName("-To Do/1 Day").getThreads()
  var numThreads = threads.length
  if (numThreads>0) {
    for(var i = 0; i < numThreads; i++) {

      if(GmailApp.getUserLabelByName("-To Do/1 Day").getThreads().length>0) {
        var lastThread = GmailApp.getUserLabelByName("-To Do/1 Day").getThreads()[0]
        lastThread.moveToInbox().markUnread();
        GmailApp.getUserLabelByName("-To Do/1 Day").removeFromThread(lastThread)
        Utilities.sleep(200)
      } else {
        {break;}
      }
    }
  }
    moveUp("-To Do/2 Days", "-To Do/1 Day")
    moveUp("-To Do/3 Days", "-To Do/2 Days")
    moveUp("-To Do/4 Days", "-To Do/3 Days")
    moveUp("-To Do/5 Days", "-To Do/4 Days")
}

So does anyone know how to only apply the labels to specific messages? Or a workaround to achieve that same result?

Thanks

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can do this using the GMail API instead. You need to enable the API for your project. In the editor, select Resources > Advanced Google services, then click on "These services must also be enabled in the Google Developers Console." There, enable the GMail API.

modifyMessage

Example of use:

modifyMessage('me', messageId, ['stack','overflow']);       // add two labels
modifyMessage('me', messageId, null, ['stack','overflow']); // remove two labels

TL;DR The full code is available in this gist, and below in a hidden code snippet.

/**
 * Modify the Labels a Message is associated with.
 * Throws if unsuccessful.
 * see https://developers.google.com/gmail/api/v1/reference/users/messages/modify
 *
 * @param  {String} userId           User's email address. The special value 'me'
 *                                   can be used to indicate the authenticated user.
 * @param  {String} messageId        ID of Message to modify.
 * @param  {String[]} labelsToAdd    Array of Label names to add.
 * @param  {String[]} labelsToRemove Array of Label names to remove.
 *
 * @returns {Object}                 Users.messages resource, see reference. 
 */
function modifyMessage(userId, messageId, labelsToAdd, labelsToRemove) {
  labelsToAdd = labelsToAdd || [];
  labelsToRemove = labelsToRemove || [];
  // see https://developers.google.com/gmail/api/v1/reference/users/messages/modify
  var url = 'https://www.googleapis.com/gmail/v1/users/${userId}/messages/${id}/modify'
            .replace("${userId}","me")
            .replace("${id}", messageId );
  var headers = {
    Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
  };
  var addLabelIds = [];
  for (var i=0; i<labelsToAdd.length; i++) {
    addLabelIds[i] = getLabelId( labelsToAdd[i] );
  }
  var removeLabelIds = [];
  for (var i=0; i<labelsToRemove.length; i++) {
    removeLabelIds[i] = getLabelId( labelsToRemove[i], false );
  }
  var request = {
    'addLabelIds': addLabelIds,
    'removeLabelIds': removeLabelIds
  };
  var params = {
    method: "post",
    contentType: "application/json",
    headers: headers,
    payload: JSON.stringify(request),
    muteHttpExceptions: true
  };
  //var check = UrlFetchApp.getRequest(url, params); // for debugging
  var response = UrlFetchApp.fetch(url, params);

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

/**
 * Get the Label ID for the given LabelName. If Label isn't found, it will be created
 * depending on the state of ok2Create.
 * Throws if unsuccessful.
 * See https://developers.google.com/gmail/api/v1/reference/users/messages/modify.
 *
 * @param {String}   labelName        Name of label to retrieve ID for.
 * @param {Boolean}  ok2Create        (optional) Set true if a label should be created when not found.
 *                                    Default is true.
 *
 * @returns {String}                  ID of Label, or null if not found or created.
 */
function getLabelId( labelName, ok2Create ) {
  if (typeof ok2Create == 'undefined') ok2Create = true;
  
  var id = null;
  // see https://developers.google.com/gmail/api/v1/reference/users/labels/list
  var url = 'https://www.googleapis.com/gmail/v1/users/${userId}/labels'
            .replace("${userId}","me")  // The user's email address. The special value me can be used to indicate the authenticated user.
  var headers = {
    Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
  };
  var params = {
    method: "get",
    contentType: "application/json",
    headers: headers,
    muteHttpExceptions: true
  };
  
  //var check = UrlFetchApp.getRequest(url, params); // for debugging
  var response = UrlFetchApp.fetch(url, params);

  var result = response.getResponseCode();
  if (result == '200') {  // OK
    var labels = JSON.parse(response.getContentText()).labels;
    var found = false;
    for (var i=0; i<labels.length & !found; i++) {
      if (labels[i].name == labelName) {
        found = true;
        id = labels[i].id;
      }
    }
    if (!found && ok2Create) {
      id = createLabel( labelName );
    }
    return id;
  }
  else {
    // This is only needed when muteHttpExceptions == true
    var err = JSON.parse(response.getContentText());
    throw new Error( 'Error (' + result + ") " + err.error.message );
  }
}

/**
 * Create Label for given `labelName`.
 * Throws if unsuccessful.
 * See https://developers.google.com/gmail/api/v1/reference/users/messages/modify.
 *
 * @param {String}   labelName        Name of label to create
 *
 * @returns {String}                  ID of Label.
 */
function createLabel( labelName ) {
  var id = null;
  // see https://developers.google.com/gmail/api/v1/reference/users/labels/create
  var url = 'https://www.googleapis.com/gmail/v1/users/${userId}/labels'
            .replace("${userId}","me")  // The user's email address. The special value me can be used to indicate the authenticated user.
  var headers = {
    Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
  };
  var request = {
    'name': labelName
  };
  var params = {
    method: "post",
    contentType: "application/json",
    headers: headers,
    payload: JSON.stringify(request),
    muteHttpExceptions: true
  };
  
  //var check = UrlFetchApp.getRequest(url, params); // for debugging
  var response = UrlFetchApp.fetch(url, params);

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...