15 augusti 2016, ett 14-minuters inslag av Dev Mukherjee
De flesta internettjänster behöver skicka e-post till sina användare. Att konstruera meddelandet är en separat uppgift jämfört med att skicka e-postmeddelandet. Det här inlägget visar korrekt konstruktion av MIME-meddelanden (Multipurpose Internet Mail Extensions) i Python.
MIME-meddelanden har många undertyper för att kapsla in olika typer av innehåll. Pythons MIME-bibliotek för e-post tillhandahåller wrappers för att arbeta med dem. Vi kommer att utforska följande undertyper för att visa hur man paketerar meddelanden på rätt sätt:
-
mixed
används för att skicka innehåll av olika typer, inline eller som bilagor -
alternative
används för att skicka alternativa versioner av samma innehåll, t.ex. gruppera ren text- och HTML-versioner av en e-postkropp -
related
används för att inkludera relaterade resurser inline eller som bilagor, t.ex. bilder som används i ditt HTML-innehåll
Det e-postmeddelande som vi kommer att skapa i det här inlägget kommer att innehålla:
- HTML- och ren textversioner av huvudinnehållet
- En bifogad fil (som i det här fallet är en genererad
ICS
-fil) - Optionellt har vi en bild i HTML-innehållet
Låt oss börja med att skapa ett mixed
MIME multipart-meddelande som kommer att hysa de olika komponenterna (e-posthuvudet, bilder som visas inline och nedladdningsbara bilagor) i vårt meddelande:
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- och textinnehåll
Vi kommer att skapa ett alternative
-meddelande med två bilagor, där den första innehåller en ren textversion av e-postmeddelandet följt av HTML-versionen.
HTML- och textinnehåll skulle vanligtvis produceras med hjälp av en mallmotor. I det här inlägget antar jag att du redan har genererat innehållet och att det finns tillgängligt som en Python str
-variabel.
Det alternative
-meddelandet skapas genom att instansiera ett MIMEMultipart
-objekt, den här gången genom att be konstruktören att använda alternative
-subtypen.
textual_message = MIMEMultipart('alternative')
Använd MIMEText
-hjälpen för att skapa bilagorna med klartext och HTML.
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)
Foga alternative
-meddelandet till det överordnade mixed
-meddelandet för att skapa e-postmeddelandets textkropp.
# Attach this to the mixed type messagemessage.attach(textual_message)
Bifogade filer som kan laddas ner
Textuella eller binära filer kan bifogas till e-postmeddelandet genom att använda hjälparen MIMEApplication
. Den instansieras med innehållet i bilagan följt av bilagaens MIME-typ, dvs. för en application/pdf
anger du pdf
-delen.
Som standard skulle innehållet vara inline. För att göra detta till en bilaga använder du add_header
-metoden på MIMEApplication
-instansen och deklarerar att det är en bilaga. Eftersom innehållet i bilagan nu är en del av ett kodat meddelande måste du uttryckligen tillhandahålla metainformation som ett filnamn.
from email.mime.application import MIMEApplicationpdf_file = MIMEApplication(pdf_file_data, "pdf")pdf_file.add_header('Content-Disposition', 'attachment', filename='report.pdf')
Hjälparen MIMEApplication
kodar automatiskt Base64
innehållet när de bifogas meddelanden:
message.attach(pdf_file)
Optionell bild för användning i HTML-kroppen
Tänk på en bild som du vill visa i e-postkroppen, men som du inte vill erbjuda mottagaren för nedladdning. Du skulle behöva använda ett related
-meddelande för att slå in den e-postkropp som finns i alternate
-meddelandet som vi skapade tidigare och bifoga related
-meddelandet till det ursprungliga mixed
-meddelandet.
Du kommer också att behöva använda MIMEImage
-underklassen för att se till att bilden är kodad på rätt sätt. Först skapar du ett MIMEMultipart
meddelande av subtyp related
:
related_message = MIMEMultipart('related')
Skapa en instans av MIMEImage
som kommer att innehålla bildinnehållet:
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>')
Genom att lägga till en Content-ID
rubrik kan du referera till bilden i HTML-innehållet som <img src="cid:image1">
. Bifoga det ursprungligen skapade alternate
meddelandet till related
meddelandet följt av MIMEImage
instansen:
# Attach the alternative textural message to the # related messagerelated_message.attach(textual_message)# Attach the image to the related messagerelated_message.attach(image)
För att slutligen bifoga related
meddelandet till mixed
meddelandet:
# Attach the related message to our parent messagemessage.attach(related_message)
Kodning och sändning av e-postmeddelandet
När du har blandat och matchat olika MIME
typer och undertyper kan ditt meddelande kodas genom att anropa as_string
-funktionen. Denna ber i sin tur varje undermeddelande och bilaga att återge sig själva som ett sammanhängande meddelande. Resultatet är den sträng som du kan skicka över SMTP
som ditt e-postmeddelande.
encoded_email = message.as_string()
smtplib
tillhandahåller en SMTP
-klient som kan leverera detta meddelande åt dig. Det är ganska enkelt. Beroende på ditt program och din serveruppsättning kan du välja att använda lokala reläer eller reläa direkt till en tillgänglig SMTP-server. Jag lämnar det till dina applikationers specifika behov.
from smtplib import SMTPsmtp = SMTP("localhost", 25)smtp.sendmail(message, message, encoded_email)smtp.quit()
Notera: Reply-To
-direktivet är inte en del av SMTP-nyttolasten; det hanteras som en del av MIME
-meddelandet.