E-Mailversand aus TKinter

  • Hallo liebe Community,

    ich habe mir von mitp das Buch "Raspberry Pi programmieren mit Python" gekauft.
    Hier ist auch eine Anleitung drin um Anhänge per Mail zu versenden über smtplib. Was gut funktioniert ist die Standardausführung über das Shell. D. h. ich geb die Mailadresse per Input weiter ins Shell.

    Jetzt möchte ich das ganze aber etwas hübscher über ein TKinter-Window lösen.
    Anbei mal mein Ansatz:


    Leider denkt Python dass der Name MailEntry nicht definiert ist, obwohl ich das ja gemacht habe im TKinter. Oder bin ich da absolut auf dem Holzweg? Ich vermute mal TKinter-Objekte (Labels, Entrys,...) sind in Input nicht kompatibel, oder?

    Hier die Fehlermeldung: File "/home/pi/Desktop/Test/Hollywood/hier 3.py", line 48, in Mail
    m['To'] = input(MailEntry).get
    NameError: name 'MailEntry' is not defined

    Wäre cool wenn mir da jemand helfen könnte.

  • Ok, ich habs selber rausgefunden :)
    Für alle interessierten:
    Ihr müsst den MailEntry als Global setzen damit es von TKinter in SMTPlib übernommen werden kann.
    Dann könnt ihr es Easy importieren und per -get-String durchführen.

    Das ganze sieht dann so aus:

    def Mailintro():
    global MailEntry

    ...

    def Mail():
    global MailEntry
    MailEntry = MailEntry
    f = open('tmp.jpg', 'rb')
    image = MIMEImage(f.read())
    f.close()
    m = MIMEMultipart()
    m['To'] = MailEntry.get()
    m['From'] = 'Sendermailadresse'
    m['Subject'] = 'Test'
    m.attach(image)

    s = smtplib.SMTP('smtp.web.de')
    s.starttls()
    s.login('Benutzername', 'Passwort')
    s.send_message(m)
    s.quit()
    os.system ("gm display Bestätigungsbild")
    quit()

  • Hallo,

    Zitat

    Ihr müsst den MailEntry als Global setzen


    Wenn du `global` in einem Python Programm nutzt kannst du zu 99,9% sicher sein, dass du nicht sauber programmiert hast. Vergiß' am besten, dass es `global` gibt. `global` macht Programme und übersichtlich und es ist u.U. extrem schwierig, den Zustand des Programms nachzuvollziehen.

    Was du in deinem Fall möchtest ist, der Funktion `Mail` ein Parameter beim Aufruf mitzugeben.

    Namen von Funktionen schreibt man in Python übrigens klein_mit_unterstrich.

    Gruß, noisefloor

  • from tkinter import *

    Das sollte man ebenfalls nicht machen.

    Allgemein ist der Code etwas Chaotisch, mal nutzt du ein Leerzeichen zwischen "Wert" und "=", mal nicht, ebenso mit den Kommas mal lässt du danach ein Leerzeichen mal nicht... Zwischen Funktionsaufruf und "(" setzt man auch kein Leerzeichen. "datetime" verwendest du nirgends.
    Die Funktion "dest()" machst so keine Sinn, ebenso MailReady(). Das alles macht es schwer deinen Code zu lesen und vor allem zu verstehen.
    Mailintro() wird ebenfalls nirgends aufgerufen also wie soll das Programm überhaupt funktionieren?

    Dein Lösungsweg beinhaltet auch etwas unsinniges: "MailEntry = MailEntry" das ist absolut unnötig.

    Es mag auf deine Weise funktionieren, aber da du dir ja extra ein Buch über Python gekauft hast solltest du es auch so lernen wie es richtig wäre :fies: Wenn das derart falsch in deinem Buch beschrieben wird ist das Buch für die Tonne.


    Um das eigentliche Problem/Anliegen zu lösen gibt es 2 Möglichkeiten:

    1) Das gesamte Konstrukt als Klasse schreiben und "self" verwenden, denn dadurch sind alle über "self." definierten Variablen innerhalb der Klasse in jeder Funktion (bzw innerhalb einer Klasse sind es Methoden) abrufbar.
    2) Beim festlegen des Button zum ausführen der "Mail()" Funktion als Argument/Parameter das "Entry()" Objekt übergeben sodass man dann innerhalb der "Mail()" Funktion darauf zugreifen kann.

    Zu 1): => http://codepad.org/lCfYvv6U
    [code=php]
    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
    import os
    import smtplib
    import tkinter
    from RPi import GPIO
    from PIL import Image
    from email.mime.image import MIMEImage
    from email.mime.multipart import MIMEMultipart


    class mailSender(object):
    def __init__(self, mailHost, mailUser, mailPass, mailFrom):
    self.mailHost = mailHost
    self.mailUser = mailUser
    self.mailPass = mailPass
    self.mailFrom = mailFrom
    self.widget()

    def widget(self):
    self.window = tkinter.Tk()
    self.window.protocol("WM_DELETE_WINDOW", self.quit)
    self.window.title("E-Mailversand?")
    self.window.attributes('-fullscreen', tkinter.TRUE)
    self.image = tkinter.PhotoImage(file='das entsprechende Bild')
    self.label = tkinter.Label(master=self.window, image=self.image)
    self.label.pack()
    #self.label = tkinter.Label(master=self.window, width=20, font=("Arial", 16))
    self.MailEntry = tkinter.Entry(master=self.window, width=20)
    self.MailEntry.focus()
    self.MailEntry.pack()
    self.send_button = tkinter.Button(master=self.window, text="Bild versenden", width=20, font=("Arial", 16), command=self.sendMail)
    self.send_button.pack(side=tkinter.LEFT, padx=2, pady=2)
    self.exit_button = tkinter.Button(master=self.window, bg="#229", fg="white", text="X", command=self.quit)
    self.exit_button.pack()
    self.window.mainloop()

    def sendMail(self):
    m = MIMEMultipart()
    m['To'] = self.MailEntry.get()
    m['From'] = self.mailFrom
    m['Subject'] = 'Test'
    with open('tmp.jpg', 'rb') as f:
    image = MIMEImage(f.read())
    m.attach(image)
    s = smtplib.SMTP(self.mailHost)
    s.starttls()
    s.login(self.mailUser, self.mailPass)
    s.send_message(m)
    self.quit()
    os.system("gm display Abschlussbild")

    def quit(self):
    self.window.destroy()
    print("Quit")


    if __name__ == '__main__':
    mailSender('smtp.web.de', 'Login', 'Password', 'absender@web.de')
    [/php]


    Zu 2):
    [code=php]
    SendMail = Button(master=window, text="Bild versenden", width=20, font=("Arial", 16), command = lambda:Mail(MailEntry) )

    def Mail(mailTo):
    m['To'] = mailTo.get()
    [/php]

  • Erstmal danke für eure Antworten.
    Erstmal ist es schön dass mehrere Wege nach Rom führen ;) Den Code muss ich bereinigen. Das ist richtig. Ich importiere Dinge, die ich nicht brauche (datetime). Das liegt daran dass ich nicht meinen kompletten Code gepostet habe. Nur eben den notwendigen Teil. Leider habe da wohl das datetime übersehen rauszulöschen.

    Ich werde mich wohl für die 2. Funktion von dir, Meigrafd, entscheiden! Danke!

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!