15. august 2016, en 14-minutters artikel af Dev Mukherjee

De fleste internettjenester har brug for at sende e-mails til deres brugere. At konstruere meddelelsen er en separat opgave i forhold til at sende e-mailen. Dette indlæg demonstrerer korrekt konstruktion af MIME-meddelelser (Multipurpose Internet Mail Extensions) i Python.

MIME-meddelelser har mange undertyper til indkapsling af forskellige former for indhold. Pythons e-mail-MIME-bibliotek indeholder wrappere til at arbejde med dem. Vi vil undersøge følgende undertyper for at demonstrere, hvordan man pakker meddelelser korrekt:

  • mixed bruges til at sende indhold af forskellige typer, inline eller som vedhæftede filer
  • alternative bruges til at sende alternative versioner af det samme indhold, f.eks. gruppere ren tekst og HTML-versioner af en e-mailtekst
  • related bruges til at inkludere relaterede ressourcer inline eller som vedhæftede filer, f.eks. billeder, der bruges i dit HTML-indhold

Den e-mail-besked, som vi vil oprette i dette indlæg, vil indeholde:

  • HTML- og almindelig tekstversioner af indholdet i kroppen
  • En vedhæftet fil (som i dette tilfælde er en genereret ICS-fil)
  • Optionelt har vi et billede i HTML-indholdet

Lad os begynde med at oprette en mixed MIME multipart-meddelelse, som skal rumme de forskellige komponenter (e-mail-krop, billeder, der vises inline, og vedhæftede filer, der kan downloades) i vores meddelelse:

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- og almindelig tekstindhold

Vi vil oprette en alternative-meddelelse, der har to vedhæftede filer, hvoraf den første indeholder almindelig tekstversionen af e-mail-meddelelsen efterfulgt af HTML-versionen.

HTML- og tekstindhold vil typisk blive produceret med hjælp fra en templating-motor. I dette indlæg antager jeg, at du allerede har genereret indholdet, og at det er tilgængeligt som en Python str-variabel.

alternative-meddelelsen oprettes ved at instantiere et MIMEMultipart-objekt og denne gang bede konstruktøren om at bruge alternative-subtypen.

textual_message = MIMEMultipart('alternative')

Brug MIMEText-hjælperen til at oprette de vedhæftede filer i ren tekst og HTML-bilag.

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)

Føj alternative-meddelelsen til den overordnede mixed-meddelelse for at oprette e-mail-meddelelsens teksttekst.

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

Downloadbar vedhæftet fil

Tekstuelle eller binære filer kan vedhæftes til din e-mail ved hjælp af MIMEApplication-hjælperen. Den instantieres med indholdet af den vedhæftede fil efterfulgt af MIME-typen for den vedhæftede fil, dvs. for en application/pdf skal du angive pdf-delen.

Som standard vil indholdet være indeholdt inline. Hvis du vil gøre dette til en vedhæftet fil, skal du bruge add_header-metoden på MIMEApplication-instansen og erklære den for at være en vedhæftet fil. Da indholdet af den vedhæftede fil nu er en del af en kodet meddelelse, skal du udtrykkeligt angive metainformationer som f.eks. et filnavn.

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

MIMEApplicationhjælperen MIMEApplicationkoder automatisk Base64 indholdet, når det vedhæftes meddelelser:

message.attach(pdf_file)

Optionelt billede til brug i HTML-teksten

Tænk på et billede, som du ønsker at vise i e-mail-teksten, men som du ikke ønsker at tilbyde modtageren til download. Du skal bruge en related-meddelelse til at indpakke den e-mail-tekst, der er indeholdt i den alternate-meddelelse, som vi oprettede tidligere, og vedhæfte related-meddelelsen til den oprindelige mixed-meddelelse.

Du skal også bruge MIMEImage-underklassen for at sikre, at billedet er kodet korrekt. Først skal du oprette en MIMEMultipart-meddelelse af undertype related:

related_message = MIMEMultipart('related')

Opret en instans af MIMEImage, der skal indeholde billedets indhold:

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

Gennem tilføjelse af en Content-ID-overskrift kan du henvise til billedet i HTML-indholdet som <img src="cid:image1">. Vedhæft den oprindeligt oprettede alternate-meddelelse til related-meddelelsen efterfulgt af 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)

Slutteligt vedhæftes related-meddelelsen til mixed-meddelelsen:

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

Kodning og afsendelse af e-mailen

Når du har blandet og matchet forskellige MIME typer og undertyper, kan din meddelelse kodes ved at kalde as_string-funktionen. Denne beder til gengæld alle undermeddelelser og vedhæftede filer om at gengive sig selv som én sammenhængende meddelelse. Resultatet er den streng, som du kan sende over SMTP som din e-mail.

encoded_email = message.as_string()

smtplib leverer en SMTP-klient, der kan levere denne besked for dig. Det er ret ligetil. Afhængigt af dit program og din serveropsætning kan du vælge at bruge lokale relæer eller videresende direkte til en tilgængelig SMTP-server. Jeg vil overlade det til dine applikationers specifikke behov.

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

Bemærk: Reply-To-direktivet er ikke en del af SMTP-payload; det håndteres som en del af MIME-meddelelsen.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.