For loop 谷歌应用程序脚本-基于电子邮件正文标记电子邮件[优化代码]

For loop 谷歌应用程序脚本-基于电子邮件正文标记电子邮件[优化代码],for-loop,google-apps-script,gmail-api,For Loop,Google Apps Script,Gmail Api,我的目标是: 收到符合条件的电子邮件,并将其放置在标签文件夹中 收到一封新的电子邮件 这封新邮件的正文是收到的第一封邮件的副本 此新电子邮件跳过收件箱并转到标签B文件夹 下面是我如何实现它的: 所有新邮件都标记为“原始邮件” 当脚本运行时,它会将电子邮件正文与以前的所有正文进行比较 如果正文是副本,则会将其标记为“副本”,移动到“存档”,并删除“原始”标签 代码如下: function emailLabeling() { var DUPLICATE = _getLabel();

我的目标是:

  • 收到符合条件的电子邮件,并将其放置在标签文件夹中
  • 收到一封新的电子邮件
  • 这封新邮件的正文是收到的第一封邮件的副本
  • 此新电子邮件跳过收件箱并转到标签B文件夹
下面是我如何实现它的:

  • 所有新邮件都标记为“原始邮件”
  • 当脚本运行时,它会将电子邮件正文与以前的所有正文进行比较
  • 如果正文是副本,则会将其标记为“副本”,移动到“存档”,并删除“原始”标签
代码如下:

function emailLabeling() {


var DUPLICATE = _getLabel();
  var labels = GmailApp.getUserLabelByName("Original");
  if(labels != null){
    var threads = labels.getThreads();
    for (var i = 0; i < threads.length; i++){
      var messages = threads[i].getMessages();
      for (var j = 0; j < messages.length; j++){
        var message = messages[j];
        for (var k = i; k < threads.length; k++){
        var messages_check = threads[k].getMessages();
          for (var l = j; l < messages_check.length; l++){
            var message_check = messages_check[l];
            if(message_check.getPlainBody() == message.getPlainBody()){
              if(i !=  k || j != l){
                Logger.log(i +""+ j +""+ k +""+ l);
                DUPLICATE.addToThread(threads[i]);
                labels.removeFromThread(threads[i]);
                GmailApp.moveThreadToArchive(threads[i]);
              }
            }
          }
        }
      }
    }
  }
  else{
    Logger.log("Label Not Found!");
  }
}

function _getLabel() {
  var label_text = "Duplicates";
  var label = GmailApp.getUserLabelByName(label_text);
  if (label == null) {
    var label = GmailApp.createLabel(label_text);
  }
  return label;
}
函数emailLabeling(){
var DUPLICATE=_getLabel();
var labels=GmailApp.getUserLabelByName(“原始”);
如果(标签!=null){
var threads=labels.getThreads();
对于(var i=0;i
代码运行良好。问题在于4个嵌套循环,随着“原始”电子邮件数量的增加,运行时间呈指数增长

有没有办法优化此代码? 是否有更明智的逻辑来实现这一想法?


任何帮助都将不胜感激。

提高嵌套循环情况下性能的一种方法——特别是重复标识——是存储遍历内容的记录,而不是重复比较。例如,您可以修改消息体(给定正确的散列函数)并将散列存储为对象属性。请注意,并没有任何限制,所以您可以自己跳过散列(以获得固定长度的属性),只需让Google Apps脚本为您执行即可。当然,在生产中使用这种假设之前,测试消息的大小可能是明智的

function updateEmailLabels() {
  // Use an Object to associate a message's plaintext body with the
  // associated thread/message IDs (or other data as desired).
  var seenBodies = {}, // When a message is read, its plaintext body is stored.
      DUPLICATE = _getLabel("SO_Duplicates"),
      ORIGINAL = _getLabel("SO_Original");

  // getThreads() returns newest first. Start with the oldest by reversing it.
  ORIGINAL.getThreads().reverse().forEach(function (thread) {
    thread.getMessages().forEach(function (message, messageIndex) {
      // Use this message's body for fast lookups.
      // Assumption: Apps Script has no reachable limit on Object property length.
      var body = message.getPlainBody();

      // Compare this message to all previously seen messages:
      if (!seenBodies[body]) {
        seenBodies[body] = {
          count: 1,
          msgIndices: [ messageIndex ],
          threads: [ thread ],
          threadIds: [ thread.getId() ]
        };
      } else {
        // This exact message body has been observed previously.
        // Update information about where the body has been seen (or perform
        // more intricate checks, i.e. compare threadIds and message indices,
        // before treating this thread and message as a duplicate).
        seenBodies[body].count += 1;
        seenBodies[body].msgIndices.push(messageIndex);
        seenBodies[body].threads.push(thread);
        seenBodies[body].threadIds.push(thread.getId());
      }
    }); // End for-each-message. 
  }); // End for-each-thread.

  // All messages in all threads have now been read and checked against each other.
  // Determine the unique threads to be modified.
  var threadsToChange = {};
  for (var body in seenBodies) {
    if (seenBodies[body].count === 1)
      continue;
    var data = seenBodies[body];
    for (var threadIndex = 1; threadIndex < data.threads.length; ++threadIndex)
      threadsToChange[data.threadIds[threadIndex]] = data.threads[threadIndex];
  }
  // Update their labels and archive status.
  for (var id in threadsToChange) {
    var thread = threadsToChange[id];
    DUPLICATE.addToThread(thread);
    ORIGINAL.removeFromThread(thread);
    GmailApp.moveThreadToArchive(thread);
  }
}

function _getLabel(labelText) {
  var label = GmailApp.getUserLabelByName(labelText);
  return label ? label : GmailApp.createLabel(labelText);
}
函数updateEmailLabels(){
//使用对象将消息的明文正文与
//关联的线程/消息ID(或所需的其他数据)。
var seenBodies={},//读取消息时,将存储其明文正文。
DUPLICATE=\u getLabel(“SO\u Duplicates”),
原件=_getLabel(“SO_原件”);
//getThreads()首先返回最新的。从最旧的开始,将其反转。
原始.getThreads().reverse().forEach(函数(线程){
thread.getMessages().forEach(函数(消息,消息索引){
//使用此邮件的正文进行快速查找。
//假设:应用程序脚本对对象属性长度没有可达到的限制。
var body=message.getPlainBody();
//将此消息与以前看到的所有消息进行比较:
如果(!seenBodies[body]){
seenBodies[身体]={
计数:1,
msgIndices:[messageIndex],
线程:[线程],
ThreadId:[thread.getId()]
};
}否则{
//这个确切的消息体之前已经被观察到了。
//更新有关已看到尸体的位置的信息(或执行
//更复杂的检查,即比较线程ID和消息索引,
//在将此线程和消息视为副本之前)。
seenBodies[body]。计数+=1;
seenBodies[body].msgIndices.push(messageIndex);
seenBodies[body].threads.push(thread);
seenBodies[body].threadIds.push(thread.getId());
}
});//每条消息的结尾。
});//每个线程结束。
//所有线程中的所有消息现在都已被读取并相互检查。
//确定要修改的唯一线程。
var threadsToChange={};
for(seenBodies中的变量体){
如果(参见主体[body]。计数==1)
继续;
var数据=seenBodies[主体];
对于(var threadIndex=1;threadIndex

你肯定会想调整重复检测位,因为我并没有确切的合格电子邮件;)我怀疑如果至少有两条消息是相同的,那么我所写的内容会将一个线程归类为重复线程,即使该线程是具有特定消息正文的唯一线程。

请注意,即使在您开始查看新线程之后,您也会在该线程中的
j
th条消息之后继续启动消息检查,而不是0。这意味着您将跳过电子邮件检查。另外,当你发现一个复制的主体时,你会做什么并不清楚——我会在标签中保留前面的线程-
I
,并将后面的线程-
k
——移动到
“复制”
标签上(你必须检查标签是否仍然存在)