15 aug 2016, een stuk van 14 minuten door Dev Mukherjee

De meeste internetdiensten moeten emails versturen naar hun gebruikers. Het samenstellen van het bericht is een aparte taak ten opzichte van het verzenden van de e-mail. Deze post demonstreert de juiste constructie van Multipurpose Internet Mail Extensions (MIME) berichten in Python.

MIME berichten hebben vele subtypes om verschillende soorten inhoud in te kapselen. Python’s e-mail MIME bibliotheek biedt wrappers om hiermee te werken. We zullen de volgende subtypes onderzoeken om te laten zien hoe je berichten op de juiste manier verpakt:

  • mixed gebruikt om inhoud van verschillende typen te verzenden, inline of als bijlagen
  • alternative gebruikt om alternatieve versies van dezelfde inhoud te verzenden, bijv. groep platte tekst en HTML-versies van een e-mail body
  • related gebruikt om gerelateerde bronnen inline of als bijlagen te verzenden, bijv. afbeeldingen die in uw HTML-inhoud worden gebruikt

Het e-mailbericht dat we in dit bericht zullen maken, zal bevatten:

  • HTML- en platte tekstversies van de body-inhoud
  • Een bijgevoegd bestand (dat in dit geval een gegenereerd ICS-bestand is)
  • Optioneel een afbeelding in de HTML-inhoud

Laten we beginnen met het maken van een mixed MIME-multideelbericht dat de verschillende componenten (e-mailbody, inline weergegeven afbeeldingen en downloadbare bijlagen) van ons bericht zal huisvesten:

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 en platte tekst inhoud

We maken een alternative bericht dat twee bijlagen bevat, eerst met de platte tekst versie van het e-mailbericht, gevolgd door de HTML-versie.

De inhoud in HTML en tekst wordt gewoonlijk geproduceerd met behulp van een templating-engine. In dit bericht ga ik ervan uit dat u de inhoud al hebt gegenereerd en dat deze beschikbaar is als een Python str-variabele.

Het alternative-bericht wordt gemaakt door een MIMEMultipart-object te instantiëren, waarbij de constructor wordt gevraagd het subtype alternative te gebruiken.

textual_message = MIMEMultipart('alternative')

Gebruik de MIMEText-helper om de platte tekst- en HTML-bijlagen te maken.

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)

Stel het alternative-bericht vast aan het bovenliggende mixed-bericht om de tekstuele inhoud van het e-mailbericht te maken.

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

Downloadbare bijlage

Tekstuele of binaire bestanden kunnen als bijlage bij uw e-mailbericht worden gevoegd met behulp van de MIMEApplication-helper. Het wordt aangemaakt met de inhoud van de bijlage gevolgd door het MIME type van de bijlage, d.w.z. voor een application/pdf geeft u het pdf gedeelte op.

Standaard zou de inhoud inline zijn. Om hier een bijlage van te maken, gebruikt u de add_header methode op de MIMEApplication instantie en verklaart u deze tot bijlage. Aangezien de inhoud van de bijlage nu deel uitmaakt van een gecodeerd bericht, moet u expliciet meta-informatie zoals een bestandsnaam opgeven.

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

De MIMEApplication helper codeert automatisch Base64 de inhoud wanneer deze aan berichten wordt gehecht:

message.attach(pdf_file)

Optionele afbeelding voor gebruik in de HTML-body

Bedenk een afbeelding die u in de e-mailbody wilt weergeven, maar die u niet als download aan de ontvanger wilt aanbieden. U zou een related bericht moeten gebruiken om de e-mail body in te pakken in het alternate bericht dat we eerder hebben gemaakt en het related bericht aan het oorspronkelijke mixed bericht te hechten.

U zult ook het gebruik van de MIMEImage subklasse nodig hebben om ervoor te zorgen dat de afbeelding correct wordt gecodeerd. Maak eerst een MIMEMultipart-bericht van subtype related:

related_message = MIMEMultipart('related')

Maak een instantie van MIMEImage die de inhoud van de afbeelding zal bevatten:

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>')

Door een Content-ID-header toe te voegen, kunt u naar de afbeelding in de HTML-inhoud verwijzen als <img src="cid:image1">. Koppel het oorspronkelijk gecreëerde alternate-bericht aan het related-bericht, gevolgd door de MIMEImage-instantie:

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

Maak ten slotte het related-bericht vast aan het mixed-bericht:

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

Encoding and sending the email

Nadat u verschillende MIME types en subtypes hebt gemengd en gematched, kan uw bericht worden gecodeerd door de as_string functie aan te roepen. Deze vraagt op zijn beurt elk subbericht en elke bijlage om zichzelf te renderen als één samenhangend bericht. Het resultaat is de string die u via SMTP als uw e-mail kunt verzenden.

encoded_email = message.as_string()

smtplib biedt een SMTP-client die dit bericht voor u kan afleveren. Het is vrij eenvoudig. Afhankelijk van uw toepassing en serverconfiguratie kunt u ervoor kiezen om lokale relais te gebruiken of direct naar een beschikbare SMTP-server te relayen. Ik laat dat over aan de specifieke behoeften van uw toepassingen.

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

Note: De Reply-To directive maakt geen deel uit van de SMTP payload; die wordt behandeld als onderdeel van het MIME bericht.

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.