Сценарий Google Apps - метка электронной почты, основанная на теле письма [Оптимизировать код] - PullRequest
0 голосов
/ 11 мая 2018

Я стремлюсь сделать следующее:

  • Получено электронное письмо, соответствующее критериям, которое будет помещено в папку с ярлыком А.
  • Получено новое письмо.
  • Тело этого нового электронного письма является копией первого полученного.
  • Это новое электронное письмо пропускает входящие и переходит в папку Label 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;
}

Код работает нормально. Проблема заключается в 4-х вложенном цикле, который экспоненциально увеличивает время выполнения по мере увеличения количества «оригинальных» писем.

Есть ли способ оптимизировать этот код? Есть ли более разумная логика для реализации этой идеи?

Буду признателен за любую помощь.

1 Ответ

0 голосов
/ 11 мая 2018

Один из способов повышения производительности в ситуациях с вложенными циклами, особенно с дублированием идентификации, заключается в сохранении записи пройденного контента, а не в многократном сравнении.Например, вы можете хэш тело сообщения (с учетом правильной хэш-функции) и сохранять хеши как свойства объекта.Обратите внимание, что формального ограничения на длину свойства объекта не существует, поэтому вы можете пропустить его хеширование самостоятельно (для получения свойства фиксированной длины) и просто позволить Google Apps Script сделать это за вас.Естественно, целесообразно проверить, насколько большим может быть сообщение, прежде чем использовать такое предположение в процессе производства.

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

Вы определенно захотите настроить биты обнаружения дубликатов, поскольку у меня точно нет квалификацииэлектронные письма просто лежат вокруг;) Я подозреваю, что написанное мной классифицирует поток как дубликат, если хотя бы 2 сообщения совпадают, даже если этот поток является единственным потоком с этим конкретным телом сообщения.

...