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 🔷🔶

Es basiert auf einem Skript von labnol.org, wurde von mir aber stark erweitert. Nachfolgende die Schritt-für-Schritt-Anleitung, wie ihr das Skript für euer GMail einrichtet:

  1. Wartet ein paar Sekunden, bis die Editor-Seite mit dem Skript fertig geladen ist.
  2. Erstellt euch in diesem Editor eine eigene Kopie des Skripts via: Datei -> Kopie erstellen bzw. File -> Make a copy. Dadurch wird in eurem Google Account, in eurem Speicherplatz eures Google Skript Editors eine Kopie erstellt.
    Datenschutz-Disclaimer an dieser Stelle, obwohl hoffentlich eindeutig: Ich verarbeite keinerlei Daten von euch, ich erhalte in keinster Weise Zugriff auf euer GMail-Konto, ich kann nicht auf eure Skripte zugreifen, mit der Kopie des Codes ist das Skript in eurem privaten Bereich/Account.
  3. 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.
  4. 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
  5. 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
  6. 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.
  7. 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“

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.

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

28 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.

  5. Klasse Script – VIELEN DANK! Nun habe ich über die Jahre einen wahnsinnigen Backlog angehäuft. Die Idee mittels install das Script regelmäßig laufen zu lassen, ist toll. Da ich nach dem Löschen gerne die restlichen Mails noch etwas aufräumen möchte, ist mir das einmalige Ausführen pro Nacht zu wenig. Wäre es denn nicht möglich vorübergehend das Script so zu installieren, dass er es alle 5 oder 10 min. startet. Wenn das Backlog erledigt ist, würde ich es dann so einsetzen, wie es eigentlich gedacht ist.

    1. Nabend!
      Wie im Artikel erwähnt, kannst du das Skript auch einfach mehrfach nacheinander händisch ausführen – ein Durchlauf dauert ja nicht länger als 1 bis 2 Minuten, wenn du da nicht 10 Labels auf einmal aufräumen willst. Damit wäre das auch schnell erledigt. Alternativ kannst du auch eine ganz einfache Zählschleife um die ganze Sache bauen und es damit mehrfach ausführen lassen, am besten mit nem Timeout nach jedem Lauf.
      Viel Erfolg dabei!

  6. Hallo Hannes,
    das Script ist genau das was ich gesucht habe. Die Beschreibung ist gut sehr gut zu verstehen! Es ist für jemanden, der ein wenig Kenntnis von Programmierung hat, leicht anzupassen. Ich nutze es um viele E-Mails die ich von einer Wildkamera bekomme nach x-Tagen zu löschen.
    Danke Gruß
    Olaf

    1. An sich geht das sicher – das Skript nutzt ja quasi auch nur die Suche und geht dann durch die Suchergebnisse. Mit der Suche kannst du natürlich auch nach Absendern suchen. Allerdings muss man es programmieren 😉
      Zeile 73 definiert die Suche, da kannst du auch ein „from: [xxx]“ einbauen und dann ist das schon fast erledigt.

  7. Hallo,

    das Script hat gut funktioniert, aber nun löscht es keine weiteren Mails mehr obwohl der trigger korrekt ist und ich über 10000 Mails habe und die hälfte sicherlich von 2009 -2016 noch dabei ist.
    irgend eine idee ?

    [20-10-06 21:21:44:896 BST] category ‚Inbox‘ purged, deleted 0 mails.
    [20-10-06 21:21:44:896 BST] ############################### Inbox done
    [20-10-06 21:21:44:896 BST] Looking at category ‚Starred‘ and purge mails older than 1400 days (before 2016-12-06)…
    [20-10-06 21:21:45:032 BST] Threads: 0

  8. Hallo, leider finde ich keine Lösung den Papierkorb mit einem SCRIPT zu löschen. Ich möchte diesen
    genau wie oben beschrieben jeden Tag (besser jede Stunde) löschen. Das Script oben funktioniert leider „bei mir“ mit dem Label *trash* nicht.

    1. Dazu würde ich ein eigenes Script empfehlen, folgende Schritte sind zu erledigen:
      1. Neues Projekt auf https://script.google.com/ anlegen
      2. im Editor folgendes Script eintragen:

      function TrashDelete() {

      var labelName = „HIER_LABEL_NAME_EINTRAGEN“

      var threads = GmailApp.search(„in:trash label:“ + labelName);
      for (var i = 0; i < threads.length; i++) {
      Gmail.Users.Messages.remove('me', threads[i].getId());
      }
      }

      3. Bei "Dienste" folgenden hinzufügen: Gmail API
      4. Unter https://console.developers.google.com/apis/dashboard ein neues Projekt erstellen
      5. Innerhalb des Cloud Projektes ebenfalls oben in der Suche die Gmail API suchen und aktivieren
      6. Innerhalb des Cloud Projektes oben in der Suche nach "OAuth-Zustimmungsbildschirm" suchen und anklicken.
      7. Den OAuth-Zustimmungsbildschirm konfigurieren, zu setzende Einstellung "Extern" und wichtig ist den eigenen Google Account als Testnutzer auf dem vorletzen Bildschirm zu hinterlegen.
      8. Unter Unter https://console.developers.google.com/apis/dashboard unter "Projektinformation" die Projektnummer kopieren.
      9. Jetzt wieder unter https://script.google.com/ das Projekt auswählen und zu den Projekteinstellungen gehen.
      10. Bei Google Cloud Platform-Projekt (GCP) auf "Projekt ändern" klicken und die Projektnummer des Cloud Projektes eintragen.
      11. Jetzt kann man die Funktion testen
      12. Trigger einrichten

  9. Nachdem das Script nun Monate lang problemlos lief, bekomme ich seit zwei Tagen folgenden Hinweis: Authorization is required to perform that action.
    Woher kann das so plötzlich kommen?

Schreibe einen Kommentar