Mail soll Anruf auslösen

  • Moin zusammen,


    zu Anfang möchte ich mich kurz Vorstellen da dies mein erster Beitrag ist.


    Ich bin Johannes und studiere Elektrotechnik mit leider miserablen Programmierkenntnissen. Wir durften bisher C, C++ und C# sowie Java Python und Assembler Programmieren. Alles aber leider nur seeeeehr kurz angeschnitten...


    Ich hätte nun eine Frage in welcher ich eure Hilfe benötige:


    Ich möchte bei Emaileingang auf einer bestimmten Adresse einen Anruf erhalten. Dafür möchte ich mit imaplib den Server auswerten und einen Ausgang schalten. So weit bin ich auch schon.

    Das Programm ruft die Emails ab und gibt mir aus wie viele Emails vorhanden sind. Sofern ungelesene Emails vorhanden sind, wird die grüne LED eingeschaltet, wenn nicht die rote...


    Da auf diese Emailadresse sicherlich nicht nur die Alarmemails eingehen werden, würde ich nun zusätzlich gerne nach Betreff und / oder Absender filtern und nur die grüne LED Leuchten lassen, wenn ich ungelesene Emails von entsprechendem Absender bzw. mit entsprechendem Betreff habe. Zusätzlich würde ich die LED gerne nur eine kurze Zeit eingeschaltet lassen und nach einer halben Stunde erneut einschalten lassen.

    Die LED soll später durch ein Wählgerät getauscht werden und darüber würde ich gerne bei Emaileingang eine Nachricht erhalten.


    Ich habe dazu auch die Suche bemüht, allerdings noch nichts wirklich 100%iges Hilfreiches rausgefunden. Alle Threads sind deutlich älter als 365 Tage, daher dachte ich mach ich mal einen neuen...


    Nun zum Code den ich bisher habe... (Ich hoffe ich füge den so richtig ein..):


    Gedacht hatte ich z.B. bei "unseen = server.folder_status..." eine Zeile dazuzuschreiben, welche das "subject" Kontrolliert. Allerdings war dort bisher immer der Fehler, da mir dort der Befehl fehlte...

    Bei "newmail_count = (unseen...." mit einem "and" die zweite Bedingung anzufügen...


    Habt ihr Ideen?


    LG Johannes

  • Jein. ^^

    Ich habe mir so etwas ähnliches gestrickt, allerdings mit einem gsmHAT, da entfällt das Wählgerät, der Pi kann selbst anrufen bzw. eine SMS senden.

    Wenn man den Pi mit einem Mailclient versieht, dann ist es sicherlich auch möglich aufgrund einer Mail eine Aktion auszulösen.


    Gruss

  • Das gsmHAT wäre auch eine Möglichkeit. Allerdings wäre mir erstmal am wichtigsten wie ich den Betreff auswerten kann... Lässt du jede Email "einfach" melden?


    LG

  • Hallo,

    Ich möchte bei Emaileingang auf einer bestimmten Adresse einen Anruf erhalten

    Schau mal hier bei Getting Started, da wird mit 'search' nach Absender gesucht.

    Die Struktur deines Codes sollte Python-Typisch so aussehen:

    Damit die LED nur für eine bestimmte Zeit an ist, würde ich eine zusätzlich Timer-Funktion schreiben, die dann aufgerufen wird und die verstrichene Zeit runterzählt.


    Grüße

    Dennis

    🎵🎸Die Nordsee schlägt dir ins Gesicht, trotzdem hast du verloren, du bist nicht weit gekommen, du läufst weiter nach vorn 🎵🎸

  • Moin,


    jetzt versuch ich mich mal am Zitat...

    Schau mal hier bei Getting Started, da wird mit 'search' nach Absender gesucht.

    Danach habe ich mich auch schon gerichtet... habe es genauso geschrieben wie es dort steht. Allerdings gibt das nur Fehler... leider... Das Funktioniert auch nicht...


    Was sollen deine Zeilen 15 und 16 machen? Ansonsten habe ich das Script doch in dem Format, oder?


    Grüße!

  • Lässt du jede Email "einfach" melden?

    Nein, ich untersuche jede SMS auf ein Schlüsselwort.

    Schlüsselwort gefunden -> sende SMS -> lösche SMS

    Schlüsselwort nicht gefunden -> lösche SMS


    Und so kann man es auch mit Mails machen.


    Gruss

  • jetzt versuch ich mich mal am Zitat...

    Wenigstens das klappt 8o


    Ohne zu sehen, wie und wo du was im Code geschrieben hattest und die vollständigen Fehlermeldungen dazu, ist es natürlich schwer zu sagen an was es liegt.


    Ja, bis auf die fehlende 'main'-Funktion war die Struktur soweit vorhanden. Hier werden die letzten zwei Zeilen mit Beispielen erklärt.


    Grüße

    Dennis

    🎵🎸Die Nordsee schlägt dir ins Gesicht, trotzdem hast du verloren, du bist nicht weit gekommen, du läufst weiter nach vorn 🎵🎸

  • Moin,


    FSC830 Ahhhh also mit SMS! Auch nicht schlecht :)


    Dennis89 Mh... also der Code steht oben. Dort hatte ich unterschiedliche Zeilen an den entsprechenden Stellen (Steht im 1. Beitrag) hinzugefügt. Bisher hat Python immer das object nicht gekannt. Ich hab aber noch keine Erklärung der Library gefunden, welche mir solche Informationen verständlich erklärt... und wenn ich eine finde, dann ist es meistens nicht für Python :D


    Hier habe ich die Zeilen hinzugefügt... wie ich gedacht habe, dass es passen müsste... Tut aber nicht.


    1.

    Traceback (most recent call last):

    File "/home/pi/Documents/Emailauslesen/EmailEmpfangBetreff.py", line 46, in <module>

    mail_check()

    File "/home/pi/Documents/Emailauslesen/EmailEmpfangBetreff.py", line 28, in mail_check

    message = server.folder_subject(MAILBOX, 'Test')

    AttributeError: 'IMAPClient' object has no attribute 'folder_subject'

    Also findet er folder_subject nicht... hab aber auch nirgends gefunden welches object meine Anforderung erfüllt.


    Leider...


    LG

  • Jrlohni: Wie kommst Du denn darauf, dass es eine `folder_subject()`-Methode geben sollte? Und was sollte die machen? In der Dokumentation von `IMAPClient` sind doch alle Methoden nachzulesen die so ein Objekt hat.


    Falls Du Nachrichten mit "Test" im Betreff haben willst, musst Du die IDs davon suchen (`search()`) und dann die Nachrichten, oder Teile davon, über die IDs abfragen (`fetch()`). Gleich das erste Beispiel ganz am Anfang der Dokumentation zeigt so etwas.

    “If debugging is the process of removing software bugs, then programming must be the process of putting them in.” — Edsger Dijkstra

  • Hallo,


    auch wenn ich gerade gesehen habe, das __blackjack__ und @__deets__ vor mir geantwortet haben und beide so viel mehr von der Programmierung verstehen als ich, poste ich jetzt trotzdem mal mein Codebeispiel. Sonst hätte ich in der letzten halben Stunde auch Kaffee trinken können. 8o


    Jrlohni ich habe gelesen, was du im ersten Beitrag geschrieben hattest, das bringt aber nichts wenn du sagst das es Fehlermeldungen gibt, weil du irgendwas irgendwo hinzugefügt hast. Deswegen habe ich dich um den Code mit den Fehlermeldungen gebeten. Das was du dann gepostet hast wurde ja schon kommentiert.

    Schau mal ob du damit etwas anfangen kannst:

    Findet man alles in der Dokumentation.


    Grüße

    Dennis

    🎵🎸Die Nordsee schlägt dir ins Gesicht, trotzdem hast du verloren, du bist nicht weit gekommen, du läufst weiter nach vorn 🎵🎸

  • Moin,


    Hast du die offizielle Dokumentation bemüht? https://imapclient.readthedocs.io/en/2.2.0/index.html


    Da ist auf der Startseite ein Beispiel, wie man einen Ordner auswählt, darin nach einem Kriterium messages aussuchet, und dann über diese messages iteriert, um ihren Betreff zu bekommen.

    Ja ich hab die Dokumentation bemüht und auch durch gesehen und getestet. Das Beispiel habe ich sogar einmal extra getestet. Gab auch Fehler, welchen weiß ich natürlich nicht mehr... :wallbash:


    Dennis89 Danke für das Script! Sieht erstmal super aus. war natürlich kein Meckern das ich es im 1. Post schon schrieb, nur noch einmal ein Hinweis :)

    Also die Dokumentation habe ich gesehen und auch bereits getestet. Dein Script funktioniert aber auch noch nicht.. leider.. Habe auch bereits geguckt ob ich den Fehler eventuell selber beheben kann. Hab aber leider keine Idee bekommen...


    Fehler:

    5 ungelesene Nachrichten

    0 davon sind von dem gesuchten Absender:

    Traceback (most recent call last):

    File "/home/pi/Documents/Emailauslesen/EmailEmpfangAbsender.py", line 36, in <module>

    main()

    File "/home/pi/Documents/Emailauslesen/EmailEmpfangAbsender.py", line 33, in main

    mail_check()

    File "/home/pi/Documents/Emailauslesen/EmailEmpfangAbsender.py", line 28, in mail_check

    print(email_message.get("From"))

    UnboundLocalError: local variable 'email_message' referenced before assignment


    Dort steht.. egal wie viele Email gelesen oder ungelesen sind... das 5 ungelesene Emails vorhanden sind. Sucht er überhaupt nach ungelesenen Nachrichten? Er sucht nach allen oder?

    Da habe ich jetzt hinzugefügt das er auch nur die ungelesenen Anzeigt.


    Außerdem verstehe ich den Fehler so, das dort eine Referenz fehlt, welche vor der Zuordnung fehlt... aber wenn ich dort teste die zu Referenzierten, gibt es den Fehler immer noch...


    Was macht denn das "b" vor 'EXISTS' eigentlich? Und wofür steht das RFC822?


    Vielen Dank schonmal!


    LG


    P.S.: Ich dachte die Emails wären von der angegebenen Adresse gesendet worden. Waren sie aber gar nicht... Wenn ich nun von der Emailadresse welche ich abfrage eine Email im Posteingang habe, taucht der Fehler nicht auf... Aber er sollte ebenfalls nicht auftauchen wenn keine Email des Empfängers im Eingang ist...

  • Die Fehlermeldung ist doch recht klar: wenn man versucht auf eine Variable zuzugreifen, die noch nicht angelegt ist, kracht es. Genausowenig wie du in ein Auto einsteigen kannst, das noch nicht vor dir steht.


    Im konkreten Fall liegt das daran, dass eben keine Mails gefunden wurden, also wurde auch niemals die for-Schleife betreten. Die print-Anweisung gehoert *IN* die Schleife.


    Das b besagt, dass es sich um ein Bytes-Objekt statt eines Strings handelt. Und RFC822 kann man mal googeln.

  • Ich finde die imaplib zum Kotzen und es passt auch absolut nicht zu Python.

    Wenn ich mir so die ganzen Beispiele im Netz ansehe, wird mir schlecht.


    Wenn ich damit arbeiten müsste, würde ich mir zuerst meinen eigenen Wrapper bauen, um hinterher ein einfaches Interface zu haben.



    Python: Pseudo-Code
    from imap_reader import IMAP_SSL
    
    
    imap = IMAP_SSL("host", 993, "username", "password", "seen_messages.txt")
    for message in imap:
        print(message)
        # do something



    Aber was wäre bloß Python ohne Internet? Schau dir mal imap-tools an. Die API ist viel schöner.

  • Im konkreten Fall liegt das daran, dass eben keine Mails gefunden wurden, also wurde auch niemals die for-Schleife betreten. Die print-Anweisung gehoert *IN* die Schleife.

    Ich bin eigentlich davon ausgegangen, dass das Skript erst mal mit E-mails getestet wird, die auch vorhanden sind. Ich versuche es zumindest immer so zu machen, dass erst die Hauptfunktion funktioniert und ich mich dann um Ausnahmen und Sicherheiten kümmere.
    Mit der 'print'-Anweisung war ich wieder unachtsam, die war in der Schleife (so wie es in der Doku auch drin ist), das habe ich nicht bedacht, als ich die drei 'print' - Anweisungen untereinander schrieb. Sorry. :blush:



    Grüße

    Dennis

    🎵🎸Die Nordsee schlägt dir ins Gesicht, trotzdem hast du verloren, du bist nicht weit gekommen, du läufst weiter nach vorn 🎵🎸

  • Moin,


    @_deets_: Dankeschön :)

    DeaD_EyE Werde ich mir mal angucken :geek: Sieht bisher deutlich übersichtlicher aus!

    Dennis89 Ja ich hab es gestartet, als keine Email vorhanden war :D Trotzdem vielen Dank für die Hilfe bis hierhin! Klappt schon mal deutlich besser :)

    Bei meinem ganzen Email-gesende habe ich bald Angst das der Server meine Mail blockiert :D:D


    So hab das Script nun noch etwas umgeschrieben und geht auch alles soweit ganz super! Allerdings würde ich nun gerne noch implementieren, dass nur Emails welche Ungelesen UND mit bestimmten Betreff vorhanden sind eine Umschaltung auslösen... Bzw. gezählt werden...

    Ich werde vermutlich eine Liste mit ungelesenen Emails schreiben müssen und in dieser Überprüfen ob der Betreff, zur Zeit "Test" vorhanden ist, oder?

    Eine Idee habe ich dazu aber auch nicht...


    Das ist mein etwas umgebauter Code zur Zeit. Mir ist klar das die if-Abfrage so keinen Sinn macht, zumindest für meinen Anwendungsfall...


    LG :)


    Edit: DeaD_EyE leider kann mein Pi die Lib nicht installieren... dort ist immer ein Fehler im Code der Installationsdatei...

    Edited once, last by Jrlohni ().

  • Bei meinem ganzen Email-gesende habe ich bald Angst das der Server meine Mail blockiert :D:D

    Wenn man einen eigenen Mailserver betreibt, kann man sehr schnell auf Spamlisten landen, wenn man nicht alles im Griff hat.
    Das ist aber ein ganz anderes Thema.

    Das ständige Einloggen bei einem E-Mail Provider könnte dazu führen, dass man dann z.B. für X Minuten gesperrt wird.
    Wie lange und wie oft man sich im Zeitraum X neu verbinden kann, ist bei jedem Anbieter anders.


    Ich habe das mit IMAP zwar noch nie gemacht, aber auch dort ist es ziemlich sicher, dass der Server eine Rückmeldung gibt, wieso die Verbindung geschlossen/beendet worden ist. Anhand dieser Meldung kann man dann feststellen, warum es Probleme gab.

    Eigentlich ist das ständige Einloggen, abholen, ausloggen und dann wieder neu verbinden nicht so gut.


    Das IMAP-Protokoll ist für persistente Verbindungen ausgelegt. Es hängt aber auch von der Konfiguration des Providers ab.
    Wenn der keine Grenzen setzt, könnte der Daemon theoretisch so lange eingeloggt bleiben, bis du eine neue IP bekommst, falls du eine dynamische öffentliche IP-Adresse hast. Bei Kabel ändert sich die IPv4 Adresse sehr selten.


    Man kann Nachrichten auch als gelesen markieren. D.h. wenn dein Daemon läuft, kann dieser die "UNSEEN" Mails abholen und diese dann auf "SEEN" setzen. Der E-Mail Provider dient dann als ausgelagerte Datenbank. Sonst müsstest du dir lokal merken, welche Nachrichten bereits gelesen sind.

    Anstatt dich dann wieder auszuloggen, könntest du die Verbindung offen lassen. Wenn der Nachrichteninhalt belanglogs ist, kannst du auch nur die header abholen. Ich habe gesehen, dass das mit der anderen Bibliothek ging und es geht dann bei 125 E-Mails im Postfach auch etwas schneller. (ich lösche selten E-Mails.)

  • Also eingeloggt bleiben klingt gut. Werde ich vermutlich eine neue Funktion schreiben müssen und diese im Anfang einmal aufrufen, richtig?


    Zum ausschließen, dass eine ungelesene Email welche nicht den entsprechenden Betreff hat, einen Alarm auslöst, könnte ich sicher die Mail in einen anderen Ordner verschieben... Habe aber in der IMAPClient Lib keine Funktion dafür gefunden... jemand eine Idee? :)


    LG Johannes

  • […] Allerdings würde ich nun gerne noch implementieren, dass nur Emails welche Ungelesen UND mit bestimmten Betreff vorhanden sind eine Umschaltung auslösen... […]

    Ja dann mach das doch. Man kann da nach mehr als einem Kriterium filtern.

    “If debugging is the process of removing software bugs, then programming must be the process of putting them in.” — Edsger Dijkstra

  • Moin,


    so... mittlerweile kenne ich das Aussehen der Mails. Weitere Versuche nur nach ungelesenen mit entsprechendem Betreff zu suchen, haben leider noch nicht geklappt...


    Er sucht alle Mails mit entsprechendem Betreff raus und schreibt es auch dementsprechend oft. Das ist ja erstmal nicht so schlimm. Das tut er leider aber auch, wenn eine andere Mail ungelesen ist. Also überhaupt eine ungelesen ist... Ich grüble, Google und Teste schon lange wie ich das rausbekommen kann. Allerdings habe ich noch keine Möglichkeit gefunden, welche ich umsetzen kann. Theoretisch muss er die Email, welche ungelesen ist auch auf den Betreff untersuchen. Dafür müsste er der Email eine Nummer zuweisen und diese Nummer erneut mit dem Betreff untersuchen.


    Also hat jemand eine Idee wie ich die Mails nach Betreff UND ungelesen prüfen kann?




    LG Johannes!