15 Aug 2016, 14-minutowy fragment Dev Mukherjee

Większość serwisów internetowych musi wysyłać e-maile do swoich użytkowników. Konstruowanie wiadomości jest oddzielnym zadaniem do wysłania e-maila. Ten post demonstruje prawidłową konstrukcję wiadomości Multipurpose Internet Mail Extensions (MIME) w Pythonie.

Wiadomości MIME mają wiele podtypów, które enkapsulują różne rodzaje zawartości. Biblioteka email MIME Pythona dostarcza wrapperów do pracy z nimi. Zapoznamy się z następującymi podtypami, aby zademonstrować, jak prawidłowo pakować wiadomości:

  • mixed używane do wysyłania treści różnych typów, inline lub jako załączniki
  • alternative używane do wysyłania alternatywnych wersji tej samej treści, np. grupowanie wersji zwykłego tekstu i HTML treści wiadomości e-mail
  • related używane do dołączania powiązanych zasobów inline lub jako załączniki, np. obrazy używane w treści HTML

Wiadomość e-mail, którą stworzymy w tym poście, będzie zawierać:

  • WersjeHTML i zwykłego tekstu treści body
  • Załączony plik (który w tym przypadku jest wygenerowanym plikiem ICS)
  • Opcjonalnie posiadać obraz w treści HTML

Zacznijmy od utworzenia wieloczęściowej wiadomości mixed MIME, która pomieści różne komponenty (treść emaila, obrazy wyświetlane inline i załączniki do pobrania) naszej wiadomości:

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 i zawartość ciała w postaci zwykłego tekstu

Utworzymy wiadomość alternative, która ma dwa załączniki, pierwszy zawierający wersję zwykłego tekstu wiadomości e-mail, a następnie wersję HTML.

Treść HTML i tekstowa byłaby typowo produkowana z pomocą silnika szablonującego. Na potrzeby tego postu zakładam, że już wygenerowałeś treść i jest ona dostępna jako zmienna Pythona str.

Wiadomość alternative jest tworzona przez instancję obiektu MIMEMultipart, tym razem prosząc konstruktor o użycie podtypu alternative.

textual_message = MIMEMultipart('alternative')

Użyj helpera MIMEText, aby utworzyć załączniki zwykłego tekstu i 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)

Dołącz wiadomość alternative do wiadomości nadrzędnej mixed, aby utworzyć tekstowe ciało wiadomości e-mail.

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

Załącznik do pobrania

Pliki tekstowe lub binarne można dołączyć do wiadomości e-mail za pomocą helpera MIMEApplication. Jest on tworzony z zawartością załącznika, po której następuje typ MIME załącznika, np. dla application/pdf dostarczasz mu część pdf.

Domyślnie zawartość byłaby zawarta w linii. Aby zrobić z tego załącznik, użyj metody add_header na instancji MIMEApplication i zadeklaruj, że jest to załącznik. Ponieważ zawartość załącznika jest teraz częścią zakodowanej wiadomości, musisz jawnie dostarczyć meta informacje, takie jak nazwa pliku.

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

Pomocnik MIMEApplication automatycznie Base64 koduje zawartość, gdy jest ona dołączana do wiadomości:

message.attach(pdf_file)

Opcjonalny obraz do użycia w treści HTML

Pomyśl o obrazie, który chcesz wyświetlić w treści wiadomości e-mail, ale nie chcesz oferować odbiorcy do pobrania. Musiałbyś użyć wiadomości related, aby zawinąć treść wiadomości e-mail zawartej w wiadomości alternate, którą stworzyliśmy wcześniej, i dołączyć wiadomość related do oryginalnej wiadomości mixed.

Będziesz także potrzebował użycia podklasy MIMEImage, aby zapewnić, że obraz jest zakodowany prawidłowo. Po pierwsze, utwórz wiadomość MIMEMultipart o podtypie related:

related_message = MIMEMultipart('related')

Utwórz instancję klasy MIMEImage, która będzie zawierać zawartość obrazu:

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

Dodanie nagłówka Content-ID pozwoli Ci odwołać się do obrazu w treści HTML jako <img src="cid:image1">. Dołącz pierwotnie utworzoną wiadomość alternate do wiadomości related, a następnie do instancji MIMEImage:

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

Na koniec dołącz wiadomość related do wiadomości mixed:

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

Kodowanie i wysyłanie wiadomości e-mail

Po wymieszaniu i dopasowaniu różnych MIME typów i podtypów, wiadomość może zostać zakodowana przez wywołanie funkcji as_string. Ta z kolei prosi każdą wiadomość i załącznik, aby renderowały się jako jedna spójna wiadomość. Wynikiem jest ciąg znaków, który można wysłać przez SMTP jako wiadomość e-mail.

encoded_email = message.as_string()

smtplib zapewnia klienta SMTP, który może dostarczyć tę wiadomość dla Ciebie. Jest to całkiem proste. W zależności od Twojej aplikacji i konfiguracji serwera możesz zdecydować się na użycie lokalnych przekaźników lub przekaźników bezpośrednio do dostępnego serwera SMTP. Pozostawię to konkretnym potrzebom Twoich aplikacji.

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

Uwaga: Dyrektywa Reply-To nie jest częścią zawartości SMTP; jest ona obsługiwana jako część wiadomości MIME.

.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.