[Python] eMails gefiltert abrufen, auswerten und Werte in eine csv schreiben

  • Ein neues Projekt nach langer Zeit.

    Die Projektbeschreibung steht in Kurzform im Titel.

    Anfangen möchte ich mit

    • Verbindung zum Mailserver aufbauen
    • Mails filtern
    • Werte auslesen
    • Werte in eine csv schreiben.

    Ich bin gespannt was es für Ideen und Vorschläge gibt.

    Static Badge GitHub-Projekte

    Edited 2 times, last by nicoletta (September 28, 2025 at 6:03 PM).

  • nicoletta September 28, 2025 at 4:12 PM

    Changed the title of the thread from “[Python] automatisch eMails gefiltert abrufen, auswerten und Daten zur Verfügung stellen (Neue Mail erzeugen)” to “[Python] automatisch eMails gefiltert abrufen, auswerten und Daten in eine csv schreiben”.
  • Zutaten:

    Um eine Verbindung zum Mailserver aufbauen zu können habe ich mich für das Modul "imaplib" entschieden. imaplib unterstützt IMAP4 (RFC 1730).

    Aus dem Modul benötige ich eigentlich nur die Funktion IMAP4

    Python
    from imaplib import IMAP4

    Static Badge GitHub-Projekte

  • Um Mails auslesen zu können bietet sich das Modul "email" an. Da ich nicht genau weiß was ich alles aus dem Modul benötigen werden binde ich es komplett vorläufig ein.

    Python
    from imaplib import IMAP4
    import email

    Static Badge GitHub-Projekte

  • nicoletta September 28, 2025 at 6:03 PM

    Changed the title of the thread from “[Python] automatisch eMails gefiltert abrufen, auswerten und Daten in eine csv schreiben” to “[Python] automatisch eMails gefiltert abrufen, auswerten und Werte in eine csv schreiben”.
  • nicoletta wenn du den Projektbeschrieb, so wie hier plus die Tools für die du dich schon entschieden hast bei Claude reinwirfst - sollte da bereits was funktionierendes rauskommen.

  • class imaplib.IMAP4 -SSL (host '''', port - IMAP4-SSL-PORT, *, ssl-context - Keinem Timeout=None)

    demnach müsste es sein:

    imaplib.IMAP4_SSL('imap.provider.de')

    ohne Portangabe sollte SSL-Port (993) gesetzt sein, laut Beschreibung.

    Python
    from imaplib import IMAP4
    import email
    
    #Zugangsdaten
    mail=imaplib.IMAP4_SSL("imap.provider.de")

    Static Badge GitHub-Projekte

  • Logindaten setzen

    IMAP4.login(user, Passwort)

    dann müsste:

    mail.login("benutzername", "passwort")

    passen.

    Python
    from imaplib import IMAP4
    import email
    
    #Zugangsdaten
    mail=imaplib.IMAP4_SSL("imap.provider.de")
    mail.login("benutzername", "passwort")

    Static Badge GitHub-Projekte

  • Ich möchte den Posteingang nur lesend durchsuchen.

    IMAP4.select(Mailbox ='INBOX', readonly=False)

    ergo:

    mail.select("INBOX")

    nur lesen ist Standard.

    Python
    from imaplib import IMAP4
    import email
    
    #Zugangsdaten
    mail=imaplib.IMAP4_SSL("imap.provider.de")
    mail.login("benutzername", "passwort")
    mail.select("INBOX")

    Das sollte es sein an Zugangsdaten.

    Mir raucht der Kopf. Schluß für heute.

    Static Badge GitHub-Projekte

  • nicoletta wenn du den Projektbeschrieb, so wie hier plus die Tools für die du dich schon entschieden hast bei Claude reinwirfst - sollte da bereits was funktionierendes rauskommen.

    danke, jedoch will ich lernen. Die Dokus sind nicht einfach zu verstehen, aber ich möchte mich da durchwühlen. KI nutzen falls ich mal nicht weiterkomme, oder einen Fehler nicht finde kann ich immer noch machen. Evt. den Code optimieren, oder so. Jedoch wenn ich von Anfang an KI nutze lerne ich nichts.

    Static Badge GitHub-Projekte

  • Wir haben eine Verbindung zum Mailserver (hoffe ich) und wollen Mails "abholen" die wir auswerten wollen. Ich möchte Mails filtern die mich über ablaufende Softwarelizenzen informieren.

    Dazu habe ich im Modul imaplib

    IMAP4.search(charset, criterion[, ...])

    gefunden.

    IMAP4.search(None, "ALL")

    würde alle Mails abholen.

    Ich möchte nur bestimmte Mails von einen bestimmten Absender mit einem definierten Betreff.

    Das sind FROM und SUBJECT. Kennt man von Mails

    Der zweite Parameter steht in "". Mit Python, das weiß ich noch, können "" nicht ineinander verschachtelt werden. Dafür gibt es alternativ die ''. Es gibt zwei zulässige Schreibweisen. Ich habe mich für diese entschieden:

    (None, '(FROM "absender.de" SUBJECT "Auslaufende Softwarelizenzen!")')

    Für unser Script wäre das:

    mail.search(None, '(FROM "absender.de" SUBJECT "Auslaufende Softwarelizenzen!")')

    Python
    from imaplib import IMAP4
    import email
    
    #Verbindung zum Mailserver
    mail=imaplib.IMAP4_SSL("imap.provider.de")
    mail.login("benutzername", "passwort")
    mail.select("INBOX")
    
    #Suche nach Mails nach Absender und Betreff
    mail.search(None, '(FROM "absender.de" SUBJECT "Auslaufende Softwarelizenzen!")')

    Wie wir die gefunden Mails interieren habe ich noch keinen Plan ;)

    Schluss für heute!

    Static Badge GitHub-Projekte

    Edited 3 times, last by nicoletta (September 29, 2025 at 10:38 PM).

  • nicoletta September 29, 2025 at 11:01 PM

    Changed the title of the thread from “[Python] automatisch eMails gefiltert abrufen, auswerten und Werte in eine csv schreiben” to “[Python] eMails gefiltert abrufen, auswerten und Werte in eine csv schreiben”.
  • Also ich hasse sowas ja...

    Dein Codebeispiel hat leider nicht funktioniert, musste etwas googeln. https://coderivers.org/blog/email-api-python/

    - 2FA aktivieren

    - App-Passwort erstellen

    Der Rest ist for-Loop und if/else Zeug

    Meine Projekte:

    GuideOS Logo PiGro-Aid Logo

    Auf Linux seit 2003 | Python-Jünger| Wir reden ja hier über Computer, das sind Arbeitsgeräte und keine Religion.

    --

    Wir sind hier alle Trekkis, Star Wars müffelt!

  • Ein guter Hinweis auf Zugänge mit 2FA. Das Script kann noch gar nicht funktionieren weil wir noch gar nicht so weit sind einen Testlauf machen zu können. Eine Fehlerbehandlung haben wir auch nicht. ;) . Da dudas Script mit Hilfe von einer Suchmashine oder KI weitergestrickt hast scheint ja das Login zu funktionieren. Der Unterschied ist das du erst ein App-Passwort generieren musst für einen google-Zugang. Das ist dann das passwort in Zeile 6.


    Bei einer 2FA muss beim Provider ein APP-Passwort generiert werden.

    Dieses muss dann in unserem Script in Zeile 6 verwendet werden:

    Code
    mail.login("benutzername", "app-passwort")

    Static Badge GitHub-Projekte

    Edited 2 times, last by nicoletta (September 30, 2025 at 8:53 AM).

  • Also ich hasse sowas ja...

    Damit meinte ich übrigens Server-API-Zeug, nicht dass der Code nicht funktioniert hat. War schon spät, gestern :D.

    Bei einer 2FA muss beim Provider ein APP-Passwort generiert werden.

    Ja, ich hab das mit allen Anbietern, die ich nutze probiert. Ist jetzt ein Google-Beispiel.

    Meine Projekte:

    GuideOS Logo PiGro-Aid Logo

    Auf Linux seit 2003 | Python-Jünger| Wir reden ja hier über Computer, das sind Arbeitsgeräte und keine Religion.

    --

    Wir sind hier alle Trekkis, Star Wars müffelt!

  • Wir rufen gefilterte Mails vom Mailserver ab. Jedoch haben wir noch keine Werte die wir verarbeiten können.

    IMAP4 Objekte geben Werte als bytes in einen Tupel zurück. Für IMAP4.select ist das (typ, [data, ...].

    type beinhaltet einen Status wie "OK" und data die email_ID

    typ == 'OK': Die Operation war erfolgreich.
    typ != 'OK': Es gab einen Fehler (z. B. 'NO' oder 'BAD').

    data erhält nur dann einen Wert wenn typ=='OK' ist.

    typ, data=mai.search(...

    Python
    from imaplib import IMAP4
    import email
    
    #Verbindung zum Mailserver
    mail = imaplib.IMAP4_SSL("imap.provider.de")
    mail.login("benutzername", "passwort")
    mail.select("INBOX")
    
    #Suche nach Mails nach Absender und Betreff
    typ, data = mail.search(None, '(FROM "absender.de" SUBJECT "Auslaufende Softwarelizenzen!")')

    Static Badge GitHub-Projekte

  • Wir bekommen die Wete in einen Tupel Status "OK" in typ und die eMail-ID in data zurück.

    data könnte so aussehen: [b"1 2 3 4 5 6"]

    data[0] ist der erste byte-string im Tupel "1 2 3 4 5 6".

    Abgesehen davon das ein Tupel nicht veränderbar ist können wir damit nicht soviel weiter anfangen. Wir müssen die IDs aus den Tupel holen und in einer Liste speichen. Das Eregebnis könnte so aussehen: ["1", "2", "3", "4", "5", "6"]

    das machen wir mit .split().

    split splittet den Tupel bei jeder Leerstelle und gibt die Werte als Liste zurück.

    Mit einer "for" Schleife iteriert jede E-Mail-ID über (num).

    for num in data[0].split():

    Static Badge GitHub-Projekte

    Edited once, last by nicoletta (October 1, 2025 at 9:34 PM).

  • Wir müssen Zeile 1 (jetzt Zeile 3) ändern

    So wie ich mir das gedacht habe würde es ab Zeile 5 nicht funktionieren, da ich einen Alias (mail) für (imaplib) gesetzt habe. Da ich nur die Funktion (IMAP4) herausgenommen habe existiert kein (imaplib.IMAP4...)

    Also müssen wir das gesamte Modul laden, was nicht tragisch ist.

    import imaplib

    Lieben Dank für den Hinweis von @Citizen Erased aus unserer Telegramm-Gruppe.

    Static Badge GitHub-Projekte

    Edited 2 times, last by nicoletta (October 2, 2025 at 10:11 PM).

  • Nun haben wir Mail IDs in einer LIste, jedoch wollen wir auch den Text der Mail haben.

    Also holen wir uns die Rohdaten der Mails. (fetch)

    Rohdaten einer Mail sind der Mail-Header und der Content. Also von wem die Mail kommt, für wen sie bestimmt ist, den Btetraff und den Text. Der Text kann Plaintext, Richtext und htlm sein, RFC822-Format

    Aus dem Module imaplib können w ir dafür nutzen:

    IMAP4.fetch(message-set, message-parts)

    Wir bekommen auch hier einen Tupel zurück mit "typ, msg_data" zurück.

    typ = Status und msg_data = die Rohdaten (RFC822)

    in num haben bereits die ID der wir nun die Mail-Rohdaten im RFC822-Format zuordnen.

    typ, msg_data = mail.fetch(num, '(RFC822)')

    msg_data könnte so aussehen:
    [(b'RFC822 {1234}', b'From: ...\nTo: ...\nSubject: ...\n\nHallo!')]

    # Beispielausschnitt aus Rohdaten:
    Return-Path: <absender@domain.com>
    Received: from mail.domain.com (mail.domain.com [192.0.2.1])
    by mx.google.com with ESMTP id a123456789;
    Fri, 3 Oct 2025 10:00:00 +0200
    From: Max Mustermann <absender@domain.com>
    To: Empfänger <empfaenger@domain.de>
    Subject: Test-E-Mail
    Date: Fri, 3 Oct 2025 10:00:00 +0200
    MIME-Version: 1.0
    Content-Type: text/plain; charset="UTF-8"

    Hallo,
    dies ist eine Test-E-Mail.

    Static Badge GitHub-Projekte

    Edited once, last by nicoletta (October 6, 2025 at 9:10 AM).

  • msg_data[0] ist das erste (und meist einzige) Element der Liste.
    msg_data[0][1] ist der Rohinhalt der E-Mail als Byte-String.

    Wir wollen den Rohinhalt haben

    raw_email = msg_data[0][1]

    Der Innhalt von raw_email wäre:

    b'''From: Max Mustermann <absender@domain.com>
    To: Empfänger <empfaenger@domain.de>
    Subject: Test-E-Mail
    Date: Fri, 3 Oct 2025 10:00:00 +0200
    MIME-Version: 1.0
    Content-Type: text/plain; charset="UTF-8"

    Hallo,
    dies ist eine Test-E-Mail.'''

    Static Badge GitHub-Projekte

  • nicoletta : Tolles Konzept. Deine Herangehensweise, wie Du jeden Schritt hier einzeln durchführst und kommentierst, gefällt mir. Ist ja fast schon traurig, dass nur noch ein Punkt auf Deiner ToDo-Liste übrig ist. ;)

  • nicoletta : Tolles Konzept. Deine Herangehensweise, wie Du jeden Schritt hier einzeln durchführst und kommentierst, gefällt mir. Ist ja fast schon traurig, dass nur noch ein Punkt auf Deiner ToDo-Liste übrig ist. ;)

    Vielen Dank.

    eigentlich sind es noch zwei Punkte, grob betrachtet. Der Rohinhalt muss noch ausgewertet und die gewünschten Daten in eine csv geschrieben werden

    Es ist jedoch ausbaufähig. Wenn du Ideen hast immer her damit.

    Static Badge GitHub-Projekte

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!