Il sistema di filtri base di Gmail è estremamente limitato: non essendoci i concetti di ordine/priorità tra filtri e di terminazione dell'esecuzione della catena di filtri non è possibile creare dei flussi personalizzati. A questo si aggiunge il sistema di raggruppamento dei messaggi in thread (i filtri si applicano sempre sull'intero thread e non sul singolo messaggio), e la gestione delle espressioni che, per quanto piuttosto flessibile, non sempre riesce a risolvere tutti i problemi.
Se abbiamo tonnellate di mail da smistare, e regole complesse per farlo, i filtri di gmail potrebbero quindi non essere sufficienti.
Ma con un pò di buona volonta possiamo sopperire a questa mancanza attraverso un sistema di filtri "esterno". In particolare, possiamo usare le funzioni di Scripting che ci ci mette a disposizione google con i Google Apps Script.
Questo sistema permette di interagire a basso livello con tantissimi servizi dell'universo google, attraverso degli script javascript. Le possibilità sono enormi, e in questo caso le useremo per smistare la posta come vogliamo noi.
In questo articolo viene proposta una vera e propria libreria di gestione filtri, che chiamo Gmail Advanced Filters.
Installazione
1) Andate nella vostra casella google mail
2) Accedete a Google Drive usando la barra in alto
3) Create un nuovo script premendo su "Crea", "Script", "Crea Script per: Gmail"
4) Cancellate il codice esistente e inserite quello qui sotto:
/** * Google Advanced Filters v1.0.20130105 * by Eric Berdondini * http://myhq.it/google-advanced-filters */ // Label che viene impostata nei nuovi messaggi in ingresso. Es: "Root/Child") var PROC_LABEL = "_PROC_"; var PROC_DONE_LABEL = false; //"_PROCDONE_"; var TEST_MODE = false; var VERBOSE = true; // Numero massimo di thread elaborati a ogni esecuzione var MAX_THREADS_PROCESSED = 20; var currentThread = null; var currentMessage = null; var currentThreadMessage = null; var threadLabelsLoaded = {}; var labelsPool = {}; var starttime = null; // ------------------------------------------------------------------------------------------- function _processThread(thread) { // ... } // ------------------------------------------------------------------------------------------- // FILTRI E AZIONI function fromIs(email) { return _emailIs(currentThreadMessage.getFrom(), email); } function fromMatch(match) { return currentThreadMessage.getFrom().match(match); } function toIs(email) { return _emailIs(currentThreadMessage.getTo(), email); } function toMatch(match) { return currentThreadMessage.getTo().match(match); } function hasLabel(labelname) { return _hasGmailLabel(currentThread, labelname); } function subjectStartsWith(t) { return currentThreadMessage.getSubject().indexOf(t) == 0; } function doArchive() { if (!TEST_MODE) currentThread.moveToArchive(); logVerbose("archive"); } function doDelete() { if (!TEST_MODE) currentThread.moveToTrash(); logVerbose("delete"); } function doRead() { if (!TEST_MODE) currentThread.markRead(); logVerbose("read"); } function doUnimportant() { if (currentThread.isImportant()) { if (!TEST_MODE) currentThread.markUnimportant(); logVerbose("unimportant"); } } function doSetLabel(labelname) { _delAllGmailLabel(currentThread); _addGmailLabel(currentThread, labelname); } function doAddLabel(labelname) { _addGmailLabel(currentThread, labelname); } function doRemoveLabel(labelname) { _delGmailLabel(currentThread, labelname); } function doRemoveAllLabels() { _delAllGmailLabel(currentThread); } function doFixLabel(labelname) { if (hasLabel(labelname)) doSetLabel(labelname); } function _emailIs(messageEmail, match) { return messageEmail == match || messageEmail.indexOf("<" + match + ">") >= 0 || messageEmail.indexOf(match) == 0 || messageEmail.indexOf(", " + match) > 0; } // ------------------------------------------------------------------------------------------- /** * Funzione da eseguire via trigger */ function process() { starttime = Date.now(); var label = _getGmailLabel(PROC_LABEL); //var labelDone = PROC_DONE_LABEL ? _getGmailLabel(PROC_DONE_LABEL) : false; var threads = label.getThreads(0, MAX_THREADS_PROCESSED); Logger.log("THREADS TO BE PROCESSED: " + threads.length); //var st = Date.now(); var messages = GmailApp.getMessagesForThreads(threads); //logVerbose("GmailApp.getMessagesForThreads", st); for (var i = 0; i < threads.length; i++) { currentThread = threads<img class="icon" src="/sites/all/libraries/fugue/icons/information-button.png" width="16" height="16" alt="i" />; currentThreadMessage = messages<img class="icon" src="/sites/all/libraries/fugue/icons/information-button.png" width="16" height="16" alt="i" />[0]; currentMessage = messages<img class="icon" src="/sites/all/libraries/fugue/icons/information-button.png" width="16" height="16" alt="i" />[messages[i].length - 1]; logInfo("OPEN THREAD: " + currentThreadMessage.getId() + " | " + currentThreadMessage.getSubject() + " | " + currentThreadMessage.getTo()); _processThread(threads<img class="icon" src="/sites/all/libraries/fugue/icons/information-button.png" width="16" height="16" alt="i" />); _delGmailLabel(currentThread, PROC_LABEL); if (PROC_DONE_LABEL) { _addGmailLabel(currentThread, PROC_DONE_LABEL); } logInfo("CLOSE THREAD: " + currentThread.getFirstMessageSubject()); } _applyGmailLabels(); }; // ------------------------------------------------------------------------------------------- function _getGmailLabels(thread) { var id = thread.getId(); if (id in threadLabelsLoaded) { var labels = {}; for (var labelname in labelsPool) { if (labelsPool[labelname].threads[id] && labelsPool[labelname].threads[id].current) labels[labelname] = labelsPool[labelname].object; } return labels; } else { var labels = thread.getLabels(); var result = {}; for (var i = 0; i < labels.length; i++) { if (!labelsPool[labels[i].getName()]) labelsPool[labels[i].getName()] = { object : labels<img class="icon" src="/sites/all/libraries/fugue/icons/information-button.png" width="16" height="16" alt="i" />, threads : {} }; labelsPool[labels[i].getName()].threads[id] = { previous : true, current : true }; result[labels[i].getName()] = labels<img class="icon" src="/sites/all/libraries/fugue/icons/information-button.png" width="16" height="16" alt="i" />; } threadLabelsLoaded[id] = thread; logVerbose("labels loaded"); } } function _getGmailLabel(labelname) { if (!(labelname in labelsPool)) { //var st = Date.now(); labelsPool[labelname] = { object : GmailApp.getUserLabelByName(labelname), threads : {} } //logVerbose("GmailApp.getUserLabelByName", st); } return labelsPool[labelname].object; } function _hasGmailLabel(thread, labelname) { var id = thread.getId(); if (!(id in threadLabelsLoaded)) _getGmailLabels(thread); return labelsPool[labelname] && labelsPool[labelname].threads[id] && labelsPool[labelname].threads[id].current; } function _addGmailLabel(thread, labelname) { var id = thread.getId(); if (!(id in threadLabelsLoaded)) _getGmailLabels(thread); if (!(labelname in labelsPool)) _getGmailLabel(labelname); if (!labelsPool[labelname].threads[id]) labelsPool[labelname].threads[id] = { previous : false, current : true }; else labelsPool[labelname].threads[id].current = true; logVerbose("add label " + labelname + " (cache)"); } function _delGmailLabel(thread, labelname) { var id = thread.getId(); if (!(id in threadLabelsLoaded)) _getGmailLabels(thread); if (labelsPool[labelname].threads[id] && labelsPool[labelname].threads[id].current) labelsPool[labelname].threads[id].current = false; logVerbose("del label " + labelname + " (cache)"); } function _delAllGmailLabel(thread) { var id = thread.getId(); if (!(id in threadLabelsLoaded)) _getGmailLabels(thread); for (var labelname in labelsPool) { if (labelsPool[labelname].threads[id] && labelsPool[labelname].threads[id].current) labelsPool[labelname].threads[id].current = false; } logVerbose("del all labels (cache)"); } function _applyGmailLabels() { for (var labelname in labelsPool) { if (labelsPool[labelname].object) { var threadsAdd = []; var threadsAddLog = ""; var threadsRemove = []; var threadsRemoveLog = ""; for (var tid in labelsPool[labelname].threads) { var data = labelsPool[labelname].threads[tid]; if (data.current && !data.previous) { threadsAdd.push(threadLabelsLoaded[tid]); threadsAddLog += tid + " "; } else if (!data.current && data.previous) { threadsRemove.push(threadLabelsLoaded[tid]); threadsRemoveLog += tid + " "; } } if (!TEST_MODE) { if (threadsAdd.length) labelsPool[labelname].object.addToThreads(threadsAdd); if (threadsRemove.length) labelsPool[labelname].object.removeFromThreads(threadsRemove); } if (threadsAdd.length) logVerbose("label " + labelname + " added to " + threadsAddLog); if (threadsRemove.length) logVerbose("label " + labelname + " removed from " + threadsRemoveLog); } } } // ------------------------------------------------------------------------------------------- function logInfo(message) { Logger.log("i: " + message + " [" + (Date.now() - starttime) + "ms]"); } function logVerbose(message, st) { if (VERBOSE) Logger.log("d: " + message + " [" + (Date.now() - starttime) + "ms]" + (st ? " [" + (Date.now() - st) + "ms]" : " -")); }
5) Impostate un trigger del processo (menu "Risorse", "Trigger del processo"), con i parametri "process", "basato sul tempo", "timer minuti", "ogni minuto"
6) Impostate il nome "Google Advanced Filter" e salvate. (Più tardi ci occuperemo di configurare i filtri)
7) Tornate su Google Mail, andate in "Impostazioni", "Filtri" e aggiungete questo filtro:
L'installazione è terminata!
Configurazione
Editando lo script è possibile configurare i vari filtri.
Nella prima parte ci sono alcune opzioni che in genere possono essere lasciate così come sono (ma se volete potete giocarci).
Nella seconda parte, all'interno di "function _processThread(thread) {", potete inserire il codice dei filtri.
Il codice non è altro che javascript, che ha a disposizione diverse funzioni di filtraggio e di azioni a disposizione. L'elenco di queste funzioni lo potete vedere nella terza parte dello script, subito sotto a _processThread, e i nomi spero siano auto-documentali :)
Ecco un esempio di filtro, per capire come funziona:
function _processThread(thread) { if (subjectStartsWith("[LIST]") || subjectStartsWith("List Message:")) { doSetLabel("Debug/Lists"); doArchive(); doRead(); } if (toIs("my@address.com") && (subjectStartsWith("[LIST1]") || subjectStartsWith("[LIST2]") || subjectStartsWith("[LIST3]"))) doSetLabel("Varie/Lists"); doFixLabel("Varie/Lists"); doFixLabel("Varie"); }
Mi soffermo sulla sola funzione doFixLabel, che da sola potrebbe risolvere uno dei problemi più importanti della gestione filtri base: l'assenza di priorità.
La funzione in se è molto semplice: se il thread ha la label specificata, elimina tutte le altre label.
Può venirci in aiuto se continuiamo a usare i filtri Gmail, ma abbiamo dei messaggi che soddisfano più regole associate a delle label (di solito delle regole gerarchiche, una piu' restrittiva dell'altra), e noi vogliamo che alla fine il messaggio abbia una sola label (quella più restrittiva). In pratica vogliamo smistare i messaggi in un albero di label in maniera esclusiva (se un messaggio fa parte di una label non fa parte di quella sopra).
In questo caso e' sufficiente impostare tra i filtri avanzati dei "doFixLabel" ordinati dal più restrittivo al meno restrittivo (Nell'esempio prima "Varie/Lists", e poi il più generico "Varie").
Grazie a questo sistema in uno dei miei account Gmail continuo a usare i filtri base, e tramite dei soli doFixLabel ordinati per bene ottengo il risultato voluto (i messaggi ben smistati in maniera esclusiva tra le varie label).
4 Comments
Errori paiono ovvi. Codice che non capisco? Riordinare filtri?
Inviato da Bert64It (non verificato) il
Non mi risulta nessuna delle
Inviato da admin il
ok ok :-)
Inviato da Bert64It (non verificato) il
Vuoi provare a convincere
Inviato da admin il
Aggiungi un commento