In diesem Beitrag möchte ich dir ausführlich zeigen, wie du eine E-Mail aus einem Python3 Skript senden kannst. Des Weiteren zeige ich dir auch wie du eine E-Mail inkl. Dateianhänge absenden kannst.
E-Mail-Adresse zum Testen
Für diesen Beitrag verwende ich eine kostenfreie E-Mail von web.de. Du kannst natürlich auch jeden anderen E-Mail Dienst nutzen.
Bei der Verwendung von Gmail.com musst du jedoch noch eine zusätzliche App einrichten, was den Aufwand etwas erhöht.
Die Daten des SMTP Ausgangsservers von web.de sind:
Server | smtp.web.de |
Port | 587 |
Verschlüsselung | STARTTLS, TLS oder Verschlüsselung |
aktivieren von Pop3/IMAP in web.de
Damit jedoch das Absenden einer E-Mail von einem externen Programm mit einem web.de Account möglich ist, muss die Einstellung “POP3 und IMAP erlauben” gesetzt (Haken ist gesetzt) werden.
Senden einer E-Mail mit Text
Zunächst möchte ich dir zeigen wie du einen einfachen Text per E-Mail senden kannst.
Dabei müssen Zeilenumbrüche in dem Text per “\n” ersetzt oder gesetzt werden!
import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText # Serverdaten smtpServer = "smtp.web.de" smtpPort = 587 # Zugangsdaten username = "abc@web.de" password = "xyz#567" # Sender & Empfänger sender = "mytestmail0815@web.de" reciever = "info@draeger-it.blog" # Betreff & Inhalt subject = "Hallo Welt!" body = "Hier steht ein Text. \n Mit einem Zeilenumbruch." # Message Objekt für die E-Mail # später kann an dieses Objekt eine # oder mehrere Dateien angehängt # werden. msg = MIMEMultipart() msg['Subject'] = subject msg['From'] = sender msg['To'] = reciever part = MIMEText(body, 'plain') msg.attach(part) # Erzeugen einer Mail Session smtpObj = smtplib.SMTP(smtpServer, smtpPort) # Debuginformationen auf der Konsole ausgeben smtpObj.set_debuglevel(1) # Wenn der Server eine Authentifizierung benötigt dann... smtpObj.starttls() smtpObj.login(username, password) # absenden der E-Mail smtpObj.sendmail(sender, reciever, msg.as_string())
Wenn das Skript nun ausgeführt wird, dann erscheint beim Empfänger nachfolgende E-Mail.
Absenden von HTML Mails
Im ersten Beispiel habe ich gezeigt wie du eine einfache Mail mit einem “Plaintext” senden kannst. Diese Form des Textes ist recht sicher da so ziemlich jeder Mail Client diesen Text anzeigen lassen kann.
Wenn es etwas schöner sein soll, dann greift man auf HTML Text zurück. Hier hat man deutlich mehr Möglichkeiten seine E-Mail zu gestalten.
body_html = "<html><body>"\ "<h1>Eine Überschrift</h1>"\ "<p style='color:red'>Ein Text in der Schriftfarbe rot</p>"\ "<div style='background-color:green'>Hier ist ein Text mit einer Hintergrundfarbe.</div>"\ "</body></html>" html_part = MIMEText(body_html, 'html') msg.attach(html_part)
Absenden einer E-Mail mit Dateianhängen
Möchte man nun eine Datei per E-Mail versenden, so muss diese als weiteren “part” angehängt werden.
Jedoch muss diese Datei zuvor in BASE64 Codiert werden.
from email.mime.base import MIMEBase from email import encoders ... filename = "test.txt" file_part = MIMEBase('application', "octet-stream") file_part.set_payload(open(filename, "rb").read()) encoders.encode_base64(part) file_part.add_header('Content-Disposition', 'attachment; filename="'+filename+'"') msg.attach(file_part) ...
fertiges Python3 Skript zum senden von E-Mails mit Dateianhänge
import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.base import MIMEBase from email import encoders # Serverdaten smtpServer = "smtp.web.de" smtpPort = 587 # Zugangsdaten username = "abc@web.de" password = "xyz#123" # Sender & Empfänger sender = "mytestmail0815@web.de" reciever = "info@draeger-it.blog" # Betreff subject = "Hallo Welt!" # Inhalt der Mail body = "Hier steht ein Text. \n Mit einem Zeilenumbruch." body_html = "<html><body>"\ "<h1>Eine Überschrift</h1>"\ "<p style='color:red'>Ein Text in der Schriftfarbe rot</p>"\ "<div style='background-color:green'>Hier ist ein Text mit einer Hintergrundfarbe.</div>"\ "</body></html>" # Message Objekt für die E-Mail # später kann an dieses Objekt eine # oder mehrere Dateien angehängt # werden. msg = MIMEMultipart() msg['Subject'] = subject msg['From'] = sender msg['To'] = reciever # Plain Text part = MIMEText(body, 'plain') msg.attach(part) # HTML Text html_part = MIMEText(body_html, 'html') msg.attach(html_part) # Dateianhang filename = "test.txt" file_part = MIMEBase('application', "octet-stream") file_part.set_payload(open(filename, "rb").read()) encoders.encode_base64(file_part) file_part.add_header('Content-Disposition', 'attachment; filename="'+filename+'"') msg.attach(file_part) # Erzeugen einer Mail Session smtpObj = smtplib.SMTP(smtpServer, smtpPort) # Debuginformationen auf der Konsole ausgeben smtpObj.set_debuglevel(1) # Wenn der Server eine Authentifizierung benötigt dann... smtpObj.starttls() smtpObj.login(username, password) # absenden der E-Mail smtpObj.sendmail(sender, reciever, msg.as_string())
Herzlichen Dank für diese gute Schritt-für-Schritt-Anleitung! So kann auch ein Programmier-Anfänger wie ich das Thema gut verstehen 😀 Vielen Dank für den Beitrag und weiter so!
Liebe Grüße
Julius
Zu allererst vielen Dank für die super Anleitung 🙂
Leider bekomme ich stets diese Fehlermeldung: UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 671-673: ordinal not in range(128)
mit einer 4 zeiligen csv datei klappt es manchmal. Mit einer txt Datei leider überhaupt nicht. Bitte um Hilfe !!
Hi,
das klingt nach Zeichen welche nicht decodiert werden können.
Hast einmal ein Beispiel welches du mir per Email senden kannst?
Gruß
Stefan Draeger
Recht herzlichen Dank.
Gut aufbereitet und auch für mich verständlich. 🙂
Gruß, Klaus S.
Moin, danke für das Beispiel. Ich glaube da hat sich ein kleiner Fehlerteufel eingeschlichen.
In Zeile 51 encoders.encode_base64(part) müsste
es wohl encoders.encode_base64(file_part) heißen. Dadurch wird der Body Text verändert.
Noch eine Frage, gibt es eine einfache Möglichkeit zu erkennen, ob das Versenden der Mail funktioniert hat.
MfG Dieter Jürggensen
Hi Dieter,
vielen Dank für den Hinweis.
Ich habe das soeben geändert.
Gruß,
Stefan
Hallo zusammen,
ich bekomme hierbei ein Fehlercode der vermutlich mit der host und port Adresse zusammenhängt.
Bei mir wäre das soweit ich verstanden habe bei Gmail: smtp.gmail.com und 465
Fehlercode:
SMTPServerDisconnected Traceback (most recent call last)
in
25 msg.attach(part)
26 # Erzeugen einer Mail Session
—> 27 smtpObj = smtplib.SMTP(smtpServer, smtpPort)
28 # Debuginformationen auf der Konsole ausgeben
29 smtpObj.set_debuglevel(1)
~\anaconda3\lib\smtplib.py in __init__(self, host, port, local_hostname, timeout, source_address)
251
252 if host:
–> 253 (code, msg) = self.connect(host, port)
254 if code != 220:
255 self.close()
~\anaconda3\lib\smtplib.py in connect(self, host, port, source_address)
337 self.sock = self._get_socket(host, port, self.timeout)
338 self.file = None
–> 339 (code, msg) = self.getreply()
340 if self.debuglevel > 0:
341 self._print_debug(‘connect:’, repr(msg))
~\anaconda3\lib\smtplib.py in getreply(self)
394 if not line:
395 self.close()
–> 396 raise SMTPServerDisconnected(“Connection unexpectedly closed”)
397 if self.debuglevel > 0:
398 self._print_debug(‘reply:’, repr(line))
SMTPServerDisconnected: Connection unexpectedly closed
Für Hilfe wäre ich dankbar 🙂
Gruß Robin
Hallo zusammen,
ich erhalte leider Fehlermeldungen für den Login.
Verwendet habe ich eine Gmail Adresse mit dem Server: smtp.googlemail.com und dem Port 587. Meine Fehlermeldung sieht wie folgt aus: —————————————————————————
SMTPAuthenticationError Traceback (most recent call last)
in
35 # Wenn der Server eine Authentifizierung benötigt dann…
36 smtpObj.starttls()
—> 37 smtpObj.login(username, password)
38 # absenden der E-Mail
39 smtpObj.sendmail(sender, reciever, msg.as_string())
~\anaconda3\lib\smtplib.py in login(self, user, password, initial_response_ok)
730
731 # We could not login successfully. Return result of last attempt.
–> 732 raise last_exception
733
734 def starttls(self, keyfile=None, certfile=None, context=None):
~\anaconda3\lib\smtplib.py in login(self, user, password, initial_response_ok)
719 method_name = ‘auth_’ + authmethod.lower().replace(‘-‘, ‘_’)
720 try:
–> 721 (code, resp) = self.auth(
722 authmethod, getattr(self, method_name),
723 initial_response_ok=initial_response_ok)
~\anaconda3\lib\smtplib.py in auth(self, mechanism, authobject, initial_response_ok)
642 if code in (235, 503):
643 return (code, resp)
–> 644 raise SMTPAuthenticationError(code, resp)
645
646 def auth_cram_md5(self, challenge=None):
SMTPAuthenticationError: (535, b’5.7.8 Username and Password not accepted. Learn more at\n5.7.8
Über Hilfe wäre ich sehr dankbar,
Gruß Robin
Hi,
das Problem bei GMail besteht darin das man ein gesondertes Passwort über die GMail Seite für externe Dienste erstellen muss, damit kann man sich dann erfolgreich anmelden.
Daher verwende ich in meinen Beiträgen immer eine Web.de Adresse hier ist es nur ein einfacher Haken welcher gesetzt werden muss.
Gruß,
Stefan
Hallo Stefan,
danke für die verdammt schnelle Antwort!
Gruß Robin
Hi Robin,
ich habe dir soeben den Beitrag https://draeger-it.blog/gmail-account-app-passwort-erstellen/ erstellt in welchem ich erläutere wie du ein App-Passwort
erstellst und eine einfache E-Mail aus Python3 absendest.
Gruß
Stefan Draeger
Hallo Stefan,
als Erstes: Super Anleitung (auch für Python Dummies) und auch für Deine schnellen Reaktionen.
Ich hab eine kleine Routine erstellt, die im Falle eines “Alarms” eine Sub-Routine aufruft, die eine Mail versendet. Jetzt ist es so, dass hie und da mal der Server nicht erreichbar ist, etc.
Ich habe mir gedacht, dass man in der Mailroutine im Falle des Falles einen Fehler ausgibt, der von der Hauptroutine ausgewertet wird und dann z.B. versucht über eine andere Mailadresse eine Mail versendet.
Beispiel: Primär wird über WEB.DE und im Fehlerfall über GMAIL.COM versendet.
Gruß
Wolfgang
Hi,
ja, das ist eine gute Idee, alternativ könnte man dieses auch speichern und später erneut versuchen.
Gruß
Stefan Draeger
Hi,
ich bezeichne mich ja als Dummy oder wenigstens Newbee.
In diesem Sinne hatte ich gehofft einen Tipp zu bekommen, wie man aus “set_debuglevel(1)” eine Variable raus kriegt, die weiter verarbeitet werden kann. So im Sinne:
If Error = true:
send_Backupmail (x,y,z);
#Else:
do nothing;
Danke
Wolfgang
Vielen Dank für die Anleitung. Ich war vorher schon auf zig Seiten, deren Scripte haben nur Fehler ausgeworfen (scheinbar unlösbare Zertifikatsfehler bei SSL, imports die nicht existieren …). Das hier funktioniert super. Leider erst nach 3 Stunden suchen und probieren gefunden.
Ich wollte übrigens auch an mehrere Adressen versenden. Dazu lass ich das Script einfach mehrfach durchlaufen. Da ich auch den Content über vars abgreife, lässt der sich dann noch für beide unterschiedlich zusammenstellen und formatieren:
body = (“Text\n\n” + var1 + “\nText: ” + var2 + “\nText: ” + var3 + “\n\nText”)
…