GMail: Mails älter als X Tage automatisch löschen

gmail-mails-aelter-als-x-tage-automatisch-loeschen-labels-banner-nong-vang-427138-unsplash-s

Alte Mails automatisch löschen

Im vorletzten Artikel habe ich über das Aufräumen von Speicherplatz in GMail gesprochen. Es ging darum, Mail-Anhänge herunterzuladen und damit besonders große Speicherfresser loszuwerden. Der heutige Artikel wird primär aufräumen, weniger den Fokus auf Mailgröße.

Es geht im Detail darum, alte Mails loszuwerden, flexibel konfigurierbar. GMail selbst löscht Mails nur aus dem Papierkorb automatisch – Mails älter als 30 Tage werden dauerhaft gelöscht. Leider wird diese Funktionalität nicht für alle anderen Mails angeboten. Dies lässt sich jedoch nachrüsten, mit Google Apps Scripts, einer eigenen Programmiersprache von Google, ähnlich Javascript.

Ziel soll es sein, alte Mails bestimmter Labels automatisch nächtlich löschen zu lassen. Dabei lassen sich die Labels und die Anzahl der Tage für jedes Label beliebig einstellen. Die Reinigung kann entweder manuell oder eben täglich ausgeführt werden, wie es eben gerade gebraucht wird.

Das Skript und die Nutzung

Das Skript könnt ihr hier öffnen und anschließend benutzen. Es basiert auf einem Skript von labnol.org, wurde von mir aber stark erweitert.

  1. Wartet ein paar Sekunden, bis die Seite mit dem Skript fertig geladen ist.
  2. Ihr könnt das Skript via File -> Make a Copy auch erst in euren Google Account kopieren und dann fortfahren. Das kann auch Probleme lösen, wenn Google meckert: „Die Anmeldung mit Google ist für diese App vorübergehend deaktiviert“ usw.
  3. Startet Run -> Run function -> Initialize: Hierbei wird ein Popup von euch die Berechtigungen erfragen („Review permissions“), die das Skript braucht. Es öffnet sich dann ein Popup, ihr wählt den gewünschten GMail Account aus -> setzt fort mit „Erweitert“/“Advanced“ -> Sicherheitshinweis bestätigen -> Rechte mit „Erlauben“/“Allow“ bewilligen, fertig eingerichtet.
    Genau genommen wird das Bearbeiten eurer GMail Daten bewilligt, was zum automatischen Löschen eurer Mails nötig ist. Keine Sorge, hier passiert kein Mist, kein Datenscreening, der komplette Code ist unten oder im Skriptfenster selbst für euch einsehbar. 
    Die erteilten Berechtigungen könnt ihr jederzeit im Sicherheitscheck „Zugriff durch Drittanbieter-Apps“ nachsehen:
    gmail-mails-aelter-als-x-tage-automatisch-loeschen-labels-permissions
  4. Folgende Funktionsweise:
    Ganz oben die Variablen PURGE_LABELS und PURGE_CATEGORIES enthalten jeweils, Komma getrennt, alle Labels bzw. Kategorien jeweils mit der Anzahl an Tagen hinter dem Doppelpunkt, alles in einem paar geschweifte Klammern.
    var PURGE_LABELS = { „Auto“: 2000, „Deals“: 365 }
    würde demnach im Label Auto alle Mails, die älter sind als 2000 Tage und alle Mails innerhalb von Deals älter als 1 Jahr, löschen.
    var PURGE_CATEGORIES = { „Social“: 1000, „Updates“: 2000, „Promotions“: 3000 } löscht Mails der Kategorien „Soziale Netzwerke“, „Benachrichtigungen“ und „Werbung“.
    Mehr zum Thema Labels vs. Kategorien und wie die korrekten Namen der eigenen Labels aussehen, findet ihr unten im nächsten Absatz.
    gmail-mails-aelter-als-x-tage-automatisch-loeschen-labels-vs-categories
  5. Die Zeile var TEST_PURGE = „yes“; bestimmt, ob die Ausführungen nur testen, also keine Mails tatsächlich löschen. Bei „yes“ wird ein Durchgang simuliert, über den Logger (STRG+Enter oder View->Logs) erhaltet ihr dann alle Infos der Ausführung. Wird hier ein beliebiger anderer Wert eingetragen, z.B. „no“, werden Mails auch gelöscht.
  6. Legt nun also los, schreibt die PURGE_LABELS / PURGE_CATEGORIES für eure Zwecke um (es geht auch nur 1 Element, ohne Komma am Ende dann), belasst TEST_PURGE erst einmal auf „yes“ und startet das Skript über Run -> Run functions -> purgeGmail.
    Eine gelbe Infomeldung über dem Code zeigt euch, dass das Tool läuft, solange es läuft. Verschwindet die Info, könnt ihr euch im Logger (STRG+Enter oder View->Logs) die Ergebnisse anschauen. Enthalten sind Infos wieviele Konversationen pro Label gefunden wurden und wieviele Mails gelöscht worden wären. Es sind meist mehr Mails als Konversationen, da GMail Mails mit gleichem Betreff einer Konversation zuordnet. Mögliches Resultat im Logger:
gmail-mails-aelter-als-x-tage-automatisch-loeschen-logs-mit-labels-und-kategorien
Die neue Skript Version bereinigt sowohl eigene Labels als auch Google’s Kategorien

Label, Kategorie, interne Namen, was ist was?

Die lesbaren Bezeichner „Posteingang“, „Gesendet“ usw. haben eigentlich andere interne Namen, die von meinem Skript korrekt angesprochen werden müssen. Das Skript unterscheidet in Labels und Kategorien und die internen Namen sind meist englisch oder anders formatiert. Das kann zuweilen etwas verwirrend sein. Daher hier eine schnelle Übersicht über die vordefinierten Elemente:

  • Posteingang: Label „inbox“
  • Markiert: Label „starred“
  • Zurückgestellt: Label „snoozed“
  • Wichtig: Label „important“
  • Gesendet: Label „sent“
  • Entwürfe: Label „draft“
  • Alle E-Mails: Label „all“
  • Soziale Netzwerke: Kategorie „social“
  • Benachrichtigungen: Kategorie „updates“
  • Foren: Kategorie „forums“
  • Werbung: Kategorie „promotions“
Auch interessant:  Excel: Zeit-Informationen des Dokuments anzeigen (2019)

Bei den eigenen Labels müsst ihr ein bisschen aufpassen, wie die interne Benennung tatsächlich lautet. Leerzeichen sowie einige Sonderzeichen werden intern durch ein Minus ersetzt, das Ausrufezeichen bleibt aber beispielsweise so:

  • Eigenes Label „Invest & Mehr“: Label „invest—mehr“
  • Eigenes Label „Wohnung!“: Label „wohnung!“
Dankenswerterweise zeigt euch GMail den internen Namen eurer Labels oben in der Suchleiste an, wenn ihr diese öffnet:

gmail-mails-aelter-als-x-tage-automatisch-loeschen-label-namen
Bei den internen Namen der Labels werden Leerzeichen und manche Sonderzeichen durch Minus ersetzt

400 – Limit

Das Bild zeigt direkt die Schwäche des Skripts: Es kann pro Ausführung maximal 400 Konversationen löschen, welche jedoch beliebig viele E-Mails pro Konversation enthalten können. Das Limit ist technisch bedingt durch die API – bis 500 konnte ich gehen, aber ich wollte einen Sicherheitspuffer. Hier kann man mit „paged calls“ ansetzen, also mehrere Aufrufe nacheinander triggern, was jedoch in diesem Aufbau, in dem mehrere Labels bearbeitet werden, zu komplex ist.

In einem Label mit zigtausenden alten Mails, muss das Skript also erst mehrfach durchlaufen. Wenn ein Durchlauf in einem Label mehr als 400 Konversationen findet, wird eine weitere Suche nach der Bereinigung durchgeführt und die Restanzahl angezeigt. Ist diese erneut 400, sind es wohl noch mehr Konversationen und weitere Durchläufe sind nötig.

2 Möglichkeiten:

  1. Wenn ihr es eilig habt, dann könnt ihr einfach mehrfach nacheinander Run -> Run function -> purgeGmail ausführen. Jede Ausführung aber zu Ende arbeiten lassen, bis die gelbe Notification weg ist. Prüft ruhig nach jedem Durchlauf euer GMail parallel, dass dort die Anzahl der Mails weniger wird.
  2. Installiert das Skript einfach über Run function -> Install und lasst es in Ruhe. Nachts wird es ausgeführt und löscht 400 Konversationen. Das macht es nun jede Nacht und irgendwann sind dann alle Mails weg, egal wieviele es waren.
Auch interessant:  Excel: Zeit-Informationen des Dokuments anzeigen (2019)

Code

Hier jetzt noch der Code – wenn es Fragen gibt, schreibt ein Kommentar oder mir eine Mail und wir klären das. Die API-Dokumentation von Google ist ein guter Anlaufpunkt bei Fragen zu den Google-basierten Funktionen.

Der Quelltext hier hier einsehbar: Code anzeigen

// Hint: Execution will generate logs for you to see whats going on - view logs with CTRL+Enter or View -> Logs at any time (while execution or after it, Logs are saved until the next run).

// format needed = { "Barketing": 800, "Auto & mehr": 365 } - would delete mails from label "Barketing" if older than 800 days and from "Auto & mehr" if older than 1 year.
// If you encounter problems detecting label mails: If your Label contains whitespace or other non-alphabetical characters, please go to GMail, open (click on) your label and look into the search bar. 
// Here you will see your label name that you need to put in here. It might be "test-label" for "Test Label" or "car---more" for "Car & more". For me, both label naming types worked well but maybe it helps in special cases.
var PURGE_LABELS = { "Deals": 2000 }
// You also can purge predefined GMail categories like "Werbung", "Soziale Netzwerke", "Foren" and "Benachrichtigungen", but you have to you english keywords for these.
// Use it as with labels, but use these keywords, combined with a number of days: "Werbung"="Promotions"; "Foren"="Forums"; "Soziale Netzwerke"="Social"; "Benachrichtigungen"="Updates"
var PURGE_CATEGORIES = { "Social": 1000, "Updates": 2000, "Promotions": 3000 }

// set this to "yes" to run a purge without deleting emails. The function will just detect how many emails would be affected and print the count to Logger (CTRL+ENTER or View -> Logs)
// assign any other value to run a real purge.
var TEST_PURGE = "yes";

/*
  
  For more details, please refer https://it-stack.de/15/08/2018/gmail-mails-aelter-als-x-tage-automatisch-loeschen
  
  Original script from: http://labnol.org/?p=276053
  Modified by: Hannes Schurig (Aug 2018 + Okt 2019), https://it-stack.de
  
  T U T O R I A L
  - - - - - - - - 
  
  Step 1. Update the values of fields PURGE_LABELS, PURGE_CATEGORIES and TEST_PURGE above.
  
  Step 2. Go to Run -> Run function -> Initialize and authorize the script.
  
  Step 3.  Go to Run -> Run function -> Install to install the script. It will be executed every night.
  Step 3.1 Or run it manually: Run -> Run function -> purgeGmail
  
  Also, you may go to Run -> Uninstall to stop the purging script.

*/

function Intialize() {
  return;
}

function Install() {
  // start right after install, wait a minute to take effect, view Logs (CTRL+Enter) to look for execution
  ScriptApp.newTrigger("purgeGmail")
           .timeBased()
           .at(new Date((new Date()).getTime() + 1000*10))
           .create();
  // install for daily execute (at night around 1am)
  ScriptApp.newTrigger("purgeGmail")
           .timeBased().everyDays(1).create();
}

function Uninstall() {
  var triggers = ScriptApp.getScriptTriggers();
  for (var i=0; i<triggers.length; i++) {
    ScriptApp.deleteTrigger(triggers[i]);
  }
}

function purgeGmail() {
  for(var label in PURGE_LABELS) {
    var purgeDays = PURGE_LABELS[label];
    executePurge(label, purgeDays, "label");
  }
  for(var category in PURGE_CATEGORIES) {
    var purgeDays = PURGE_CATEGORIES[category];
    executePurge(category, purgeDays, "category");
  }
}

function executePurge(elem, purgeDays, type) {
  var count = 0,maxAge = new Date();
    maxAge.setDate(maxAge.getDate() - purgeDays); 
    var purgeBefore  = Utilities.formatDate(maxAge, Session.getScriptTimeZone(), "yyyy-MM-dd"),
        search = type + ":" + elem + " before:" + purgeBefore;
    
    Logger.log("Looking at " + type + " '" + elem + "' and purge mails older than " + purgeDays + " days (before " + purgeBefore + ")...");
    if (TEST_PURGE === "yes") {
      Logger.log("Test_purge active, no e-mails will be deleted. You can view the amount of affected mails in the Logger (CTRL+ENTER).")
    }
    
    try {
      var threads = GmailApp.search(search, 0, 400);
      
      Logger.log("Threads: "+threads.length);
      if (threads.length == "400") {
        Logger.log("Maximum threads (and possibly more applicable mails) for " + type + " '" + elem + "' and " + purgeDays + " days, run it multiple times to purge all.");
      }
      
      for (var i=0; i<threads.length; i++) {
        var messages = GmailApp.getMessagesForThread(threads[i]);
        for (var j=0; j<messages.length; j++) {
          var email = messages[j];       
          if (email.getDate() < maxAge) {
            if (TEST_PURGE !== "yes") {
              email.moveToTrash();
            }
            count++;
          }
        }
      }
      
      Logger.log(type + " '" + elem + "' purged, deleted " + count + " mails.");
      
      if (threads.length == 400) {
        var threads2 = GmailApp.search(search, 0, 400);
        Logger.log("Remaining threads after this purge: "+threads2.length);
        if (threads2.length == "400") {
          Logger.log("Maximum threads of 400 (and possibly more applicable mails) for " + type + " '" + elem + "' and " + purgeDays + " days even after this purge, run it multiple times to purge all.");
        }
      }
      
    } catch (e) {
      Logger.log("Error: " + e);
    }
    
    Logger.log("############################### " + elem + " done");
}

8 Kommentare

  1. Hallo Hannes Schurig,

    ich bin von diesem Blogeintrag begeistert! Das ist genau das, was ich brauche, um Newsletter automatisch zu löschen. Aber, bei mir gibt es eine Fehlermeldung nach dem Schritt „Initialize“ gleich zu Beginn. Ich wähle mein Gmail-Konto aus und es erscheint diese Meldung. Kannst du mir da weiterhelfen? Danke schonmal im Voraus.
    Fehlermeldung:
    Die Anmeldung mit Google ist für diese App vorübergehend deaktiviert
    Die Verwendung von Google Log-in wurde für diese App noch nicht bestätigt.

  2. Ooohhh… ich habe die Vermutung Google hat meine App eingeschränkt. Ich bekam irgendwann mal eine Mail das Google irgendwie die API ändert oder höhere Sicherheitsstandards einführt und scheinbar muss ich hier noch was machen. Ich schau mir das beizeiten mal an.
    Aber du kannst auch einfach den Code 1:1 in ein eigenes Projekt kopieren und dann nutzen, das sollte gehen. Also auf https://script.google.com/home/start ein neues Projekt starten, Code rein, unter einem Namen speichern und Initialisieren.

  3. Hallo Hannes Schurig
    Das mit dem kopieren des Codes funktioniert soweit gut. Gibt es aber auch eine Möglichkeit die Ordner „Werbung“ und / oder „Benachrichtigungen“ mit einzubeziehen? Diese laufen gem. „Einstellungen“ unter dem Namen „Kategorien“ und nicht „Labels“. Meine bisherigen Versuche ergaben immer, dass kein Mail gelöscht wird. Alle anderen Labels können aber problemlos beeinflusst werden.

    1. Hallo,
      das Script sucht offenbar nur nach Labels „label:“.
      Kategorien werden in Gmail mit „category:“ bezeichnet. Das sieht man auch im Suchfenster, wenn man die Kategorie einfach auswählt. Vielleicht baut uns Herr Schurig das ja ein 🙂

      1. Ja klar, das kann sich Herr Schurig zeitnah mal 😉
        Bearbeitungsaufwand schätze ich gerade gering, wie du schon sagst, GMail macht das über „category:promotions“ usw. schon sehr transparent.
        Ich versuche parallel gerade auch immernoch, meine App bei Google wieder freigeben zu lassen, was Tschonny angesprochen hatte. Aber Google ist in dem Bereich super umständlich und nicht intuitiv – aber ich gebe nicht auf.
        Also keine Zeitversprechen aber wird schon.

    2. @André @Stefan: Ist erledigt, das Skript kann jetzt Labels und Kategorien, PURGE_LABELS und PURGE_CATEGORIES erledigen das jetzt auf die bekannte Art und Weise. Eine neue Prüfung meines Skripts zur Freigabe habe ich auch bei Google eingereicht, vielleicht läuft das auch bald wieder.

  4. Hallo,
    vielleicht habe ich das Script nicht richtig verstanden, aber gibt es auch die Möglichkeit Nachrichten direkt aus dem Posteingang – die keinem Label zugeordnet sind – zu löschen?

    1. Hallo Clemens, ich habe es in dem Artikel nicht nochmal extra erwähnt und es ist auch nicht unbedingt besonders logisch: Der Posteingang („inbox“) ist ein Label. Du kannst also beispielsweise mit PURGE_LABELS: { „inbox“: 1000 } auch über 1000 Tage alte Posteingang-Mails löschen lassen. Ich werde das im Artikel mal ergänzen.
      PS: So, ich habe dem Artikel einen ganzen Absatz zum Label-/Kategorie-Thema hinzugefügt.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.