for loop - Google Apps Script: etiquetar el correo electrónico según el cuerpo del correo electrónico
for-loop google-apps-script (1)
Un método para mejorar el rendimiento en situaciones de bucle anidado, especialmente la identificación duplicada, es almacenar un registro de contenido atravesado, en lugar de compararlo repetidamente. Por ejemplo, puede hash al cuerpo del mensaje (dada la función hash correcta) y almacenar los hash como propiedades del objeto. Tenga en cuenta que no hay un límite formal en la longitud de una propiedad de objeto, por lo que puede omitir el hash (usted mismo para obtener una propiedad de longitud fija) y simplemente dejar que Google Apps Script lo haga por usted. Probablemente sea prudente probar qué tan grande puede ser un mensaje antes de usar tal suposición en la producción, naturalmente.
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);
}
Definitivamente querrás modificar los bits de detección duplicados, ya que no tengo exactamente correos electrónicos calificados simplemente por ahí;) Sospecho que lo que he escrito clasificará un hilo como duplicado si al menos 2 mensajes son iguales, incluso si ese hilo es el único hilo con ese cuerpo de mensaje en particular.
Mi objetivo es hacer lo siguiente:
- Se recibe un correo electrónico que coincide con los criterios que se colocarán en la carpeta Etiqueta A.
- Se recibe un nuevo correo electrónico.
- El cuerpo de este nuevo correo electrónico es un duplicado del primero recibido.
- Este nuevo correo electrónico omite la bandeja de entrada y va a la carpeta Etiqueta B.
Así es como lo implementé:
- Todos los correos electrónicos nuevos están etiquetados como "Original"
- Cuando se ejecuta el script, compara el cuerpo del correo electrónico con todos los anteriores.
- Si el cuerpo es un duplicado, se etiqueta "Duplicar", se mueve a "Archivo" y se elimina la etiqueta "Original".
El código es el siguiente:
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;
}
El código funciona bien. El problema radica en 4 bucles anidados, que aumenta exponencialmente el tiempo de ejecución a medida que aumenta el número de correos electrónicos "originales".
¿Hay alguna manera de optimizar este código? ¿Existe una lógica más inteligente para implementar esta idea?
Cualquier ayuda sería apreciada.