15. August 2016, ein 14-minütiger Beitrag von Dev Mukherjee

Die meisten Internetdienste müssen E-Mails an ihre Benutzer senden. Das Erstellen der Nachricht ist eine andere Aufgabe als das Versenden der E-Mail. Dieser Beitrag demonstriert den korrekten Aufbau von MIME-Nachrichten (Multipurpose Internet Mail Extensions) in Python.

MIME-Nachrichten haben viele Untertypen, um verschiedene Arten von Inhalten zu kapseln. Die E-Mail-MIME-Bibliothek von Python bietet Wrapper für die Arbeit mit ihnen. Wir werden die folgenden Subtypen untersuchen, um zu demonstrieren, wie man Nachrichten richtig verpackt:

  • mixed wird verwendet, um Inhalte verschiedener Typen inline oder als Anhänge zu versenden
  • alternative wird verwendet, um alternative Versionen desselben Inhalts zu versenden, z.B. um reine Text- und HTML-Versionen eines E-Mail-Bodys zu gruppieren
  • related wird verwendet, um verwandte Ressourcen inline oder als Anhänge einzubinden, z.B. Bilder, die in Ihrem HTML-Inhalt verwendet werden

Die E-Mail-Nachricht, die wir in diesem Beitrag erstellen werden, wird enthalten:

  • HTML- und Klartextversionen des Hauptinhalts
  • Eine angehängte Datei (in diesem Fall eine generierte ICS-Datei)
  • Optional ein Bild im HTML-Inhalt

Beginnen wir mit der Erstellung einer mixed MIME-Multipart-Nachricht, die die verschiedenen Komponenten (Hauptteil der E-Mail, inline angezeigte Bilder und herunterladbare Anhänge) unserer Nachricht enthält:

from email.mime.multipart import MIMEMultipart# By default the type is set to mixedmessage = MIMEMultipart()message = "Hello World"message = "Anomaly Support <[email protected]>"message = "Anomaly Reception <[email protected]>"# If a Reply-To is explicitly provided then the email client will# use this address when the user hit the reply button message = "Anomaly Support <[email protected]>"

HTML und reiner Textkörper

Wir erstellen eine alternativeNachricht mit zwei Anhängen, die zunächst die reine Textversion der E-Mail-Nachricht und dann die HTML-Version enthalten.

HTML- und Textinhalte werden normalerweise mit Hilfe einer Templating-Engine erstellt. Für die Zwecke dieses Beitrags gehe ich davon aus, dass Sie den Inhalt bereits erstellt haben und er als Python-Variable str verfügbar ist.

Die alternative-Nachricht wird durch Instanziierung eines MIMEMultipart-Objekts erstellt, wobei der Konstruktor dieses Mal gebeten wird, den Subtyp alternative zu verwenden.

textual_message = MIMEMultipart('alternative')

Verwenden Sie die MIMEText-Hilfe, um den reinen Text und die HTML-Anhänge zu erstellen.

from email.mime.text import MIMEText# I assume that you have a variable called txt_content# with the textual rendition of the message, this could# have been generated via a templating engineplaintext_part = MIMEText(txt_content, 'plain')textual_message.attach(plaintext_part)# likewise a variable called html_content with the HTMLhtml_part = MIMEText(html_content, 'html')textual_message.attach(html_part)

Hängen Sie die alternativeNachricht an die übergeordnete mixedNachricht an, um den Textkörper der E-Mail-Nachricht zu erstellen.

# Attach this to the mixed type messagemessage.attach(textual_message)

Herunterladbarer Anhang

Text- oder Binärdateien können mit dem MIMEApplicationHelper an Ihre E-Mail angehängt werden. Er wird mit dem Inhalt des Anhangs instanziiert, gefolgt vom MIME-Typ des Anhangs, d.h. für einen application/pdf geben Sie den pdf-Teil an.

Standardmäßig würde der Inhalt inline enthalten sein. Um dies zu einem Anhang zu machen, verwenden Sie die Methode add_header für die Instanz MIMEApplication und deklarieren sie als Anhang. Da der Inhalt des Anhangs nun Teil einer kodierten Nachricht ist, müssen Sie explizit Metainformationen wie einen Dateinamen angeben.

from email.mime.application import MIMEApplicationpdf_file = MIMEApplication(pdf_file_data, "pdf")pdf_file.add_header('Content-Disposition', 'attachment', filename='report.pdf')

Die MIMEApplication-Hilfe kodiert den Inhalt automatisch Base64, wenn er an Nachrichten angehängt wird:

message.attach(pdf_file)

Optionales Bild zur Verwendung im HTML-Textkörper

Denken Sie an ein Bild, das Sie im E-Mail-Textkörper anzeigen, dem Empfänger aber nicht zum Download anbieten wollen. Sie müssten eine related-Nachricht verwenden, um den in der zuvor erstellten alternate-Nachricht enthaltenen E-Mail-Text zu verpacken, und die related-Nachricht an die ursprüngliche mixed-Nachricht anhängen.

Sie müssen auch die Unterklasse MIMEImage verwenden, um sicherzustellen, dass das Bild richtig kodiert wird. Erstellen Sie zunächst eine MIMEMultipart-Nachricht des Untertyps related:

related_message = MIMEMultipart('related')

Erstellen Sie eine Instanz von MIMEImage, die den Bildinhalt enthält:

from email.MIMEImage import MIMEImage# Content of an image that relates to the HTML messageimage = MIMEImage(image_binary_contents)# Lets you reference the image locally in HTMLimage.add_header('Content-ID', '<image1>')

Durch Hinzufügen eines Content-ID-Headers können Sie das Bild im HTML-Inhalt als <img src="cid:image1"> referenzieren. Hängen Sie die ursprünglich erstellte alternate Nachricht an die related Nachricht an, gefolgt von der MIMEImage Instanz:

# Attach the alternative textural message to the # related messagerelated_message.attach(textual_message)# Attach the image to the related messagerelated_message.attach(image)

Hängen Sie schließlich die related Nachricht an die mixed Nachricht an:

# Attach the related message to our parent messagemessage.attach(related_message)

Kodierung und Versand der E-Mail

Nachdem Sie verschiedene MIMETypen und Subtypen gemischt haben, kann Ihre Nachricht durch den Aufruf der Funktion as_string kodiert werden. Diese wiederum fordert jede Teilnachricht und jeden Anhang auf, sich als eine zusammenhängende Nachricht darzustellen. Das Ergebnis ist die Zeichenkette, die Sie über SMTP als E-Mail versenden können.

encoded_email = message.as_string()

smtplib bietet einen SMTP-Client, der diese Nachricht für Sie übermitteln kann. Es ist ziemlich einfach. Je nach Anwendung und Serverkonfiguration können Sie lokale Relays verwenden oder direkt an einen verfügbaren SMTP-Server weiterleiten. Ich überlasse das den spezifischen Anforderungen Ihrer Anwendung.

from smtplib import SMTPsmtp = SMTP("localhost", 25)smtp.sendmail(message, message, encoded_email)smtp.quit()

Anmerkung: Die Reply-To-Direktive ist nicht Teil der SMTP-Nutzlast; sie wird als Teil der MIME-Nachricht behandelt.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.