本文介绍了GmailApp - 将标签添加到特定邮件,而不是线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个脚本,以每天自动将我的电子邮件从一个标签移动到下一个标签(以便存储标记为5 天"的邮件明天将自动标记为4 天",然后"3 天"之后的第二天,依此类推).

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?

谢谢

推荐答案

您可以使用 GMail API.您需要为您的项目启用 API.在编辑器中,选择 Resources >高级 Google 服务,然后点击这些服务也必须在 Google Developers Console 中启用."在那里,启用 GMail API.

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('me', messageId, ['stack','overflow']);       // add two labels
modifyMessage('me', messageId, null, ['stack','overflow']); // remove two labels

TL;DR 完整代码可在 中获得这个要点,以及下面隐藏的代码片段.

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 );
  }
}
/**
 * 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 );

GMail API 是一种 RESTful API,与使用内置 GMailApp 服务相比,它可以更灵活、更详细地访问线程、消息、标签、草稿和历史记录.在我们的脚本中,我们通过 URL 访问 API - 在这里,我们首先在 modify Message 方法的基本 URL 中填写详细信息.

The GMail API is a RESTful API with more flexible and detailed access to Threads, Messages, Labels, Drafts, and History than is provided using the built-in GMailApp Service. From our script, we access the API by URLs - here, we start by filling in details in the base URL for the modify Message method.

  var headers = {
    Authorization: 'Bearer ' + ScriptApp.getOAuthToken()
  };

除了为我们的项目启用 API 之外,每个请求都需要用户身份验证,这是通过嵌入一个 Bearer Token 在命令头中.

In addition to enabling the API for our project, each request requires user authentication, which is done by embedding a Bearer Token in the command header.

接下来,我们将构建其余的命令参数.

Next, we will build the rest of the command parameters.

  var addLabelIds = [];
  for (var i=0; i<labelsToAdd.length; i++) {
    addLabelIds[i] = getLabelId( labelsToAdd[i] );
  }
  var removeLabelIds = [];
  for (i=0; i<labelsToRemove.length; i++) {
    removeLabelIds[i] = getLabelId( labelsToRemove[i], false );
  }
  var request = {
    'addLabelIds': addLabelIds,
    'removeLabelIds': removeLabelIds
  };

modify 的规范调用 POST 操作,其有效负载包含标签 ID 列表.这些 ID 无法通过内置 GMail 服务获得,因此我们还将为此使用 GMail API - getLabelId() 是另一个与此类似的函数,专门用于检索标签的 ID按名称,并根据需要创建新标签.请参阅该代码的要点或片段.

The specification for modify calls for a POST operation, with a payload containing lists of Label IDs. Those IDs are not available through the built-in GMail Service, so we'll also use the GMail API for that - getLabelId() is another function similar to this one, specialized for retrieving the ID of labels by name, and creating new labels as needed. See the gist or snippet for that code.

  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);

最后,我们为命令组装了 params 对象,其属性包含带有我们的身份验证令牌的 headers 和带有命令参数,stringify-d 用于传输.设置 muteHttpExceptions: true 会在失败的情况下抑制系统生成的异常,以便我们自己处理.

Finally, we have assembled the params object for the command, with properties containing the headers with our authentication token, and payload with the command parameters, stringify-d for transport. Setting muteHttpExceptions: true squelches system-generated exceptions in case of failure, so that we can handle them ourselves.

我已经注释掉了对 UrlFetchApp.getRequest() 的调用 - 在发送命令之前验证命令的内容非常方便.

I've commented out a call to UrlFetchApp.getRequest() - it's handy for validating the content of a command before sending it.

UrlFetchApp.fetch() 的调用将我们的命令传输到在我们建立的 URL 上运行的服务.

The call to UrlFetchApp.fetch() transmits our command to the service running at the URL we built up top.

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

当收到响应时,我们首先检查命令的result,其形式为HTTP 状态代码.200 OK 告诉我们我们成功了,所以我们继续从响应中提取我们的结果.JSON.parse() 将消息中的 JSON 字符串 转换为JavaScript 对象,我们将其返回给调用者.

When a response is received, we first check the result of the command, which is in the form of an HTTP Status Code. A 200 OK tells us that we were successful, so we go ahead and pull our result out of the response. JSON.parse() turns the JSON string in the message into a JavaScript object, which we return to the caller.

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

不过,如果我们遇到错误,我们会抛出自己的异常.根据命令的详细信息,我们可能希望以不同方式处理特定错误.例如,在这个 modify 命令上,如果我们提供了一个不存在的标签 ID,我们将收到一个错误:

If we encountered an error, though, we throw our own exception. Depending on the details of a command, we may want to handle specific errors differently. For example, on this modify command, if we provide a Label ID that does not exist, we will receive an error:

错误:错误(400)无效标签:无效标签"

这篇关于GmailApp - 将标签添加到特定邮件,而不是线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 14:08