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
.
.