In dem Artikel wollen wir uns einmal ansehen, wie man mit Python automatisiert
E-Mail versenden kann.
Vor kurzem habe ich einen Artikel und ein Video veröffentlicht, wie du ganz einfach Unterschiede in Excel Dateien finden und markieren kannst.
Darauf kam den folgenden Kommentar:
Da bietet es sich doch an, das Problem für den Zuschauer zu lösen, oder?
Die Lösung werden wir in zwei Teile aufteilen.
Hier in dem Artikel geht es rein um das Versenden von E-Mails.
Im Nächsten werden wir dann die Excel Auswertung erweitert und das Ergebnis per E-Mail versenden.
Anmerkung
Der Einfachheit halber werden wir hier keinen Server aufsetzen und einrichten.
Ich gehe davon aus, dass du eine E-Mail-Adresse mit entsprechenden Zugangsdaten zur Verfügung hast.
Voraussetzungen
- Zugang zu einem E-Mail-Server (SMTP)
- smtplib (Python Standard)
- email (Python Standard)
- optional: ssl (Python Standard)
Wie kann ich mit Python E-Mails versenden?
Python liefert im Standard bereits alle notwendigen Pakete mit.
Eine reine Text-E-Mail ist in 3 Zeilen Python Code versendet:
- Verbindung zum E-Mail-Server mit dem Modul smtplib
- Login über die Verbindung mit Benutzername und Passwort
- Versand der E-Mail mit Absender, Empfänger und Nachricht
Wie kann ich mit Python eine E-Mail mit Anhang versenden?
Ein email.mime.application.MIMEApplication Objekt kann für Dateien verwendet werden.
Bei der Erzeugung übergibst du direkt die Daten mit und das Objekt kümmert sich um die korrekte Kodierung.
Anschließend noch den Header setzen und das Objekt mit attach() an die Nachricht hängen.
E-Mail Konfiguration
Wie immer ist es eine gute Idee, die Konfigurationen oben in der Datei in separaten Variablen zu sammeln.
So haben wir später einen guten Überblick und einen einfachen Zugriff, wenn wir Daten anpassen wollen.
Was brauchen wir also alles für eine E-Mail?
SENDER = 'info@ingo-janssen.de'
SMTP_SERVER = 'smtp.ionos.de'
SMTP_PORT = 465
PASSWORD = input('Bitte gib dein E-Mail Passwort ein: ')
RECIPIENT = ['info@ingo-janssen.de']
MESSAGE_TEXT = '''Guten Morgen!
Ich wünsche dir einen wunderschönen Tag!'''
Damit haben wir die nötigsten Konfigurationen zusammen.
Wenn das Skript nur für dich ist, kannst du hier das Passwort natürlich auch direkt einsetzen.
Oder du überlegst dir etwas Ausgefeilteres wie das Passwort in einer eigenen Datei oder einer Umgebungsvariable, oder …
Hier gibt es viele Möglichkeiten.
In meinem Beispiel ist der Login zu meinem E-Mail-Account gleich meiner E-Mail-Adresse.
Deswegen brauche ich keine extra Variable für den Benutzernamen.
Einfache Text E-Mails versenden
Als Erstes wollen wir einfach einfache Text E-Mail versenden.
Sie sind nicht schön, aber es ist die erste und einfachste Möglichkeit überhaupt erstmal etwas zu versenden.
import smtplib
# import ssl
SENDER = 'info@ingo-janssen.de'
SMTP_SERVER = 'smtp.ionos.de'
SMTP_PORT = 465
PASSWORD = input('Bitte gib dein E-Mail Passwort ein: ')
RECIPIENT = ['info@ingo-janssen.de']
MESSAGE_TEXT = '''Guten Morgen!
Ich wünsche dir einen wunderschönen Tag!'''
def send_text_email():
# context = ssl.create_default_context()
# with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT, context=context) as mail_server:
with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) as mail_server:
mail_server.login(SENDER, PASSWORD)
mail_server.sendmail(SENDER, RECIPIENT, MESSAGE_TEXT.encode('utf-8'))
if __name__ == '__main__':
send_text_email()
Zum Versenden von E-Mails brauchen wir die smtplib.
Das ist eine Python Standard Bibliothek, die direkt mit deiner Installation kommt.
Du musst also nichts extra unternehmen.
Mit der smtplib können wir uns einen Zugang zum E-Mail-Server erzeugen.
Dafür übergeben wir der SMTP_SSL Klasse aus der smtplib den Server und den Port und erhalten somit eine konfigurierte Instanz.
Damit wir uns nicht selbst darum kümmern müssen, die Verbindung auch wieder zu schließen, nehmen wir uns Pythons Keyword with zur Hilfe.
Mit with wird eine Verbindung nur so lange offen gehalten, wie wir sie benötigen und im Anschluss automatisch abgeräumt und geschlossen.
In dem Block können wir uns jetzt bei unserem E-Mail-Server anmelden und die E-Mail versenden.
Dafür benutzen wir einmal die Funktion login() an unserer Server Verbindung und melden uns durch die Übergabe von Benutzername und Passwort beim Server an.
Im Anschluss können wir mit der Funktion sendmail() die E-Mail versenden.
Dafür bekommt die Funktion zuerst den Absender, dann einen oder mehrere Empfänger und abschließend den Text der E-Mail übergeben.
Ich habe hier RECIPIENT direkt als Liste angegeben, um dir zu zeigen, dass du auch mehrere Empfänger angeben kannst, an die dann verschickt wird.
Wenn du nur einen Empfänger hast, kannst du den aber auch einfach als regulären String angeben.
Die Funktion kümmert sich dann selbst darum, eine Liste mit einem Eintrag zu erstellen.
Der Text muss einmal mit der Funktion encode(‘utf-8’) enkodiert werden, da in meinem Text deutsche Umlaute vorkommen.
Wird der Text nicht kodiert, führt das zu einer Fehlermeldung.
Die sendmail() Funktion erwartet ASCII kompatible Zeichen.
Eine Anmerkung noch:
Ich habe hier den SSL Kontext auskommentiert.
Möchtest du korrekte SSL E-Mails versenden, musst du das auch mit einem SSL Kontext machen.
Das erfordert allerdings auch, dass du bei dir Zertifikate ordentlich installiert hast.
Das habe ich bei mir lokal gerade nicht und war ehrlich gesagt einfach zu faul sie jetzt zu installieren.
Damit du aber trotzdem den vollständigen Code hast, habe ich dir die entsprechenden Zeilen einfach als Kommentar im Code gelassen.
Perfekt! Du hast gerade deine erste E-Mail versendet!
Aber reine Text E-Mails sehen nicht besonders ansprechend aus und werden von manchen E-Mail-Programmen überhaupt nicht dargestellt.
Außerdem fehlen auch noch so Dinge, wie zum Beispiel ein Betreff.
Eine reine Text-E-Mail kann damit nicht umgehen.
Also machen wir uns an den nächsten Schritt und sehen uns an, wie wir HTML E-Mails versenden können.
HTML E-Mails versenden
Für eine HTML-E-Mail brauchen wir erstmal einen HTML-Text, den wir versenden können.
Dafür legen wir eine neue Variable MESSAGE_HTML an und fügen dort etwas HTML ein.
Zusätzlich kann eine HTML-E-Mail auch mit einem Betreff umgehen, also legen wir auch dafür gleich die Variable SUBJECT an.
import smtplib
SENDER = 'info@ingo-janssen.de'
SMTP_SERVER = 'smtp.ionos.de'
SMTP_PORT = 465
PASSWORD = input('Bitte gib dein E-Mail Passwort ein: ')
RECIPIENT = ['info@ingo-janssen.de']
SUBJECT = 'Ein netter Gruß.'
MESSAGE_TEXT = '''Guten Morgen!
Ich wünsche dir einen wunderschönen Tag!'''
MESSAGE_HTML = '''
<html>
<body>
<p>Guten Morgen!</p>
<p>Ich wünsche dir einen wunderschönen Tag!</p>
<p>Schau doch mal auf meiner <a href="https://ingo-janssen.de">Webseite</a> vorbei</p>
</body>
</html>
'''
def send_html_email():
# context = ssl.create_default_context()
# with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT, context=context) as mail_server:
with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) as mail_server:
mail_server.login(SENDER, PASSWORD)
mail_server.sendmail(SENDER, RECIPIENT, MESSAGE_TEXT.encode('utf-8'))
if __name__ == '__main__':
send_html_email()
Jetzt kommen ein paar Veränderungen.
Zuerst müssen wir uns eine HTML-Message erzeugen.
Dafür benutzen wir das Python-Standard-Modul email und erzeugen ein MIMEMultipart() Objekt.
An dem Objekt können Betreff, Absender und Empfänger gesetzt werden.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
SENDER = 'info@ingo-janssen.de'
SMTP_SERVER = 'smtp.ionos.de'
SMTP_PORT = 465
PASSWORD = input('Bitte gib dein E-Mail Passwort ein: ')
RECIPIENT = ['info@ingo-janssen.de']
SUBJECT = 'Ein netter Gruß.'
MESSAGE_TEXT = '''Guten Morgen!
Ich wünsche dir einen wunderschönen Tag!'''
MESSAGE_HTML = '''
<html>
<body>
<p>Guten Morgen!</p>
<p>Ich wünsche dir einen wunderschönen Tag!</p>
<p>Schau doch mal auf meiner <a href="https://ingo-janssen.de">Webseite</a> vorbei</p>
</body>
</html>
'''
def send_html_email():
message = MIMEMultipart()
message['Subject'] = SUBJECT
message['From'] = SENDER
message['To'] = ','.join(RECIPIENT)
message_content_plain = MIMEText(MESSAGE_TEXT, 'plain')
message_content_html = MIMEText(MESSAGE_HTML, 'html')
message.attach(message_content_plain)
message.attach(message_content_html)
with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) as mail_server:
mail_server.login(SENDER, PASSWORD)
mail_server.sendmail(SENDER, RECIPIENT, message.as_string())
if __name__ == '__main__':
send_html_email()
Wie gesagt, wird mit MIMEMultipart erstmal eine Nachricht erzeugt.
Die Nachricht kannst du dir wie ein Dictionary vorstellen, an dem du jetzt die verschiedenen Werte setzen kannst.
Hier setzen wir Subject, From und To für Betreff, Absender, Empfänger.
Beim Empfänger, also dem message[‘To’], handelt es sich nicht um die wirklichen Empfänger der Nachricht, sondern lediglich um die, die dann im jeweiligen E-Mail-Programm oben angezeigt werden.
Hier können statt E-Mail-Adressen auch Namen angezeigt werden.
Deshalb wird intern auch hier der Inhalt kodiert.
Da du eine Liste nicht kodieren kannst, sondern nur deren Inhalt, würde es zu einem Fehler führen, wenn wir hier eine Liste übergeben.
Das heißt, wir müssen aus unserer Liste für die Darstellung einen String erzeugen.
Am schnellsten lässt sich das mit der Funktion join() an Listen durchführen.
Hierfür wird jedes Element der Liste einfach mit dem Join-Text (in dem Fall ein Komma) aneinander gereiht.
Mit der Klasse MIMEText kannst du jetzt die verschiedenen Inhaltsarten für deine E-Mail erstellen.
Das ist einmal ‘plain’ für den reinen Textinhalt und einmal ‘html’ für den neuen HTML Inhalt.
Anschließend werden die Inhalte nur noch mit der Funktion attach an die Nachricht gehängt.
Um die Nachricht schlussendlich auch zu versenden, übergibst du die message und rufst dabei die Funktion as_string() auf.
Damit wird die Nachricht in Text umgewandelt und kann versendet werden.
Herzlichen Glückwunsch!
Schon hast du auch eine HTML E-Mail versendet.
Dann fehlt eigentlich nur noch die Möglichkeit, E-Mails mit Anhang versenden zu können, oder?
Lass uns das doch direkt als Nächstes angehen.
E-Mails mit Anhängen versenden
Anhänge sind auch ein weiterer Teil der Nachricht, die wir bereits erzeugt haben.
Für einfachen Text und auch für HTML Text haben wir die Klasse MIMEText benutzt.
Für Dateiinhalte stellt uns Python die Klasse MIMEApplication zur Verfügung.
Wir können angeben, was für ein Typ es sein soll und können Daten in die Klasse einlesen.
Als Beispiel nehme ich einfach die README.md Datei aus dem Projekt und versende sie mit meiner E-Mail.
import smtplib
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
SENDER = 'info@ingo-janssen.de'
SMTP_SERVER = 'smtp.ionos.de'
SMTP_PORT = 465
PASSWORD = input('Bitte gib dein E-Mail Passwort ein: ')
RECIPIENT = ['info@ingo-janssen.de']
SUBJECT = 'Ein netter Gruß.'
MESSAGE_TEXT = '''Guten Morgen!
Ich wünsche dir einen wunderschönen Tag!'''
MESSAGE_HTML = '''
<html>
<body>
<p>Guten Morgen!</p>
<p>Ich wünsche dir einen wunderschönen Tag!</p>
<p>Schau doch mal auf meiner <a href="https://ingo-janssen.de">Webseite</a> vorbei</p>
</body>
</html>
'''
ATTACHMENT = 'README.md'
def send_html_email_with_attachment():
message = MIMEMultipart()
message['Subject'] = SUBJECT
message['From'] = SENDER
message['To'] = RECIPIENT
message_content_plain = MIMEText(MESSAGE_TEXT, 'plain')
message_content_html = MIMEText(MESSAGE_HTML, 'html')
message.attach(message_content_plain)
message.attach(message_content_html)
with open(ATTACHMENT, 'rb') as attachment:
message_attachment = MIMEApplication(attachment.read())
message_attachment.add_header(
'Content-Disposition',
f'attachment; filename={ATTACHMENT}',
)
message.attach(message_attachment)
with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) as mail_server:
mail_server.login(SENDER, PASSWORD)
mail_server.sendmail(SENDER, RECIPIENT, message.as_string())
if __name__ == '__main__':
send_html_email_with_attachment()
Als Erstes schnappen wir uns also den Pfad unserer Datei und legen auch dafür wieder eine Variable an.
Nicht vergessen, wir wollen alle Konfigurationen einfach erreichbar oben in der Datei.
Kein langes Suchen.
Um unsere Anhang-Datei einzulesen, nehmen wir uns wieder das Keyword with zur Hilfe.
Mit open() in Verbindung mit rb als Modus können wir die Datei mit read() als bytes einlesen.
Mit den eingelesenen Daten können wir jetzt eine Instanz der schon angesprochenen Klasse MIMEApplication erzeugen und direkt den Datenstrom übergeben.
Die Klasse kümmert sich dann intern um die korrekte Kodierung und Bereitstellung der Daten.
Was jetzt noch fehlt, sind die Header.
Header werden benötigt, damit das E-Mail-Programm (oder auch ein Browser) weiß, wie die Datei dargestellt werden soll.
Hier sagen wir, dass es sich um ein attachment handelt und mit welchem Dateinamen es angezeigt werden soll.
Als letzten Schritt müssen wir den Anhang jetzt nur noch an die E-Mail-Nachricht anhängen.
Dafür benutzen wir, wie auch schon bei den Text- und HTML Inhalten, die attach Funktion von message.
Am Versand ändert sich wieder nichts.
Das war’s.
Wenn du jetzt die E-Mail versendest, hat sie einen einfachen Textinhalt, einen HTML Inhalt und auch einen Anhang.
Zusammenfassung
E-Mails versenden mit Python ist keine schwere Sache.
Im Standard werden bereits alle notwendigen Pakete mitgeliefert.
Willst du lediglich reine Text-Mails versenden, ist das in 3 Zeilen Python Code erledigt.
- Schritt 1: Verbindung zum E-Mail-Server mit der Klasse *SMTP_SSL(SERVER, PORT)
- Schritt 2: Login am E-Mail-Server über login(BENUTZER, PASSWORT)
- Schritt 3: Versand der E-Mail über sendmail(ABSENDER, EMPFÄNGER, NACHRICHT)
Mehr ist nicht nötig.
Kurse
Code Challenges und YouTube Videos führen nicht immer zum gewünschten Erfolg.
Manchmal ist es besser, gezielt und strukturiert durch ein Thema zu arbeiten.
Schau dich einfach mal bei meinen Kursen um.
Ohne lästiges Blah Blah steigen wir direkt in das Thema ein und behandeln alles, was du brauchst.
Ingo Janssen ist ein Softwareentwickler mit über 10 Jahren Erfahrung in der Leitung seines eigenen Unternehmens.
Er studierte Wirtschaftsinformatik an der TH Deggendorf und hat Softwareentwicklung an der FOM Hochschule in München unterrichtet.
Ingo hat mit einer Vielzahl von Unternehmen zusammengearbeitet, von kleinen und mittelständischen Unternehmen bis hin zu MDAX- und DAX-gelisteten Unternehmen.
Ingo ist leidenschaftlich daran interessiert, sein Wissen und seine Expertise mit anderen zu teilen. Aus diesem Grund betreibt er einen YouTube-Kanal mit Programmier-Tutorials und eine Discord-Community, in der Entwickler miteinander in Kontakt treten und voneinander lernen können.
Sie können Ingo auch auf LinkedIn, Xing und Gulp finden, wo er Updates über seine Arbeit teilt und Einblicke in die Tech-Branche gibt.
YouTube | Discord | LinkedIn | Xing | Gulp Profile