Skicka e-post¶
Django tillhandahåller omslag för Pythons moduler email och smtplib för att förenkla att skapa och skicka e-post. Djangos e-postramverk stöder också att byta mellan olika leveransmekanismer: under utveckling kan du skicka e-post till konsolen eller en fil, och i produktion till en SMTP-server eller e-postleverantör.
Koden finns i modulen django.core.mail.
Snabba exempel¶
Använd send_mail() för att skicka e-post på ett enkelt sätt. Till exempel, för att skicka ett vanligt textmeddelande:
from django.core.mail import send_mail
send_mail(
"Subject here",
"Here is the message.",
"from@example.com",
["to@example.com"],
)
När du behöver ytterligare funktioner för att skicka e-post använder du klassen EmailMessage eller EmailMultiAlternatives. För att till exempel skicka ett fler-delat e-postmeddelande med både HTML- och klartextversioner, en viss mall och anpassade meddelandehuvuden kan du använda följande tillvägagångssätt:
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
# First, render the plain text content.
text_content = render_to_string(
"templates/emails/my_email.txt",
context={"my_variable": 42},
)
# Secondly, render the HTML content.
html_content = render_to_string(
"templates/emails/my_email.html",
context={"my_variable": 42},
)
# Then, create a multipart email instance.
msg = EmailMultiAlternatives(
subject="Subject here",
body=text_content,
from_email="from@example.com",
to=["to@example.com"],
headers={"List-Unsubscribe": "<mailto:unsub@example.com>"},
)
# Lastly, attach the HTML content to the email instance and send.
msg.attach_alternative(html_content, "text/html")
msg.send()
Konfigurera e-post¶
Nya Django-projekt är inte konfigurerade för att skicka e-post som standard. I stället skrivs e-post ut i konsolen som ett utvecklingshjälpmedel (för projekt skapade med startproject) eller leder till felet MailerDoesNotExist (när inställningen MAILERS inte har definierats).
Använd inställningen MAILERS för att tala om för Django hur e-post ska skickas. Till exempel, för att skicka via en SMTP-server som körs på den lokala datorn:
MAILERS = {
"default": {
"BACKEND": "django.core.mail.backends.smtp.EmailBackend",
"OPTIONS": {
"host": "localhost",
},
},
}
Django abstraherar e-postsändningsprocessen i en klass för ”e-postbackend”. Backend för e-post listar de e-postbackendar som följer med Django.
Exemplet ovan använder Djangos SMTP-e-postbackend, som skickar med standardprotokollet SMTP. Denna backend är användbar för många produktionskonfigurationer, bland annat SMTP-servrar i din egen infrastruktur och de flesta kommersiella e-posttjänstleverantörer (ESP). Det finns även e-postbackendar från tredje part som integreras direkt med ESP-API:er eller lägger till andra sändningsfunktioner.
Under utveckling eller testning vill du ofta inte skicka e-post alls. Djangos testkörningsverktyg åsidosätter automatiskt konfigurationen MAILERS och ersätter den med Djangos e-postbackend i minnet. Det förhindrar att testfall skickar verklig e-post och ger dem tillgång till de meddelanden som skulle ha skickats. topics/email:Konfigurera e-post för utveckling beskriver några andra metoder.
I tidigare utgåvor använde Django som standard en SMTP-server på localhost för att skicka e-post, med den nu utfasade inställningen EMAIL_BACKEND och relaterade inställningar.
Ersatt sedan version 6.1: Fram till Django 2028 gäller fortfarande det tidigare beteendet om inställningen MAILERS inte är definierad: Django använder då som standard en SMTP-server på localhost (men visar utfasningsvarningar). Från och med Django 2028 ger försök att skicka e-post utan definierad MAILERS felet MailerDoesNotExist.
Befintliga projekt kan välja det nya beteendet i förväg genom att lägga till MAILERS i settings.py. Se Migrera e-post till mailers.
Flera e-postkonfigurationer¶
Ibland behöver olika typer av e-post skickas på olika sätt: till exempel intern respektive extern e-post, olika SMTP-servrar för användare i olika regioner, olika tjänster för transaktionsaviseringar och massutskick för marknadsföring, med mera.
Inställningen MAILERS kan definiera flera e-postkonfigurationer. Till exempel:
import os
MAILERS = {
"default": {
"BACKEND": "django.core.mail.backends.smtp.EmailBackend",
"OPTIONS": {
"host": "smtp.example.net",
"use_tls": True,
"username": os.environ["EMAIL_ACCOUNT_ID"],
"password": os.environ["EMAIL_API_KEY"],
},
},
"notifications": {
"BACKEND": "example.third.party.EmailBackend",
"OPTIONS": {
"api_key": os.environ["THIRD_PARTY_API_KEY"],
"region": "eu",
},
},
"admin": {
"BACKEND": "django.core.mail.backends.smtp.EmailBackend",
"OPTIONS": {
"host": "localhost",
},
},
}
Detta definierar tre e-postkonfigurationer:
"default"skickar via en SMTP-server påsmtp.example.netmed en TLS-skyddad anslutning. Den läser ett konto-id och en API-nyckel från miljövariabler och använder dem som användarnamn och lösenord för SMTP-autentisering. (Många SMTP-tjänster använder någon variant av detta autentiseringsschema.)"notifications"skickar via en hypotetisk kommersiell e-posttjänst, med en EmailBackend från tredje part som ansluter direkt till dess API. (Se Tredjepartsbackendar för vägledning om var du hittar verkliga community-underhållna paket för e-postbackendar.)"admin"skickar via en SMTP-server pålocalhost, utan att några andra alternativ krävs.
Med den här konfigurationen kan du ange argumentet using till Djangos funktioner för att skicka e-post för att välja en viss e-postkonfiguration:
from django.core.mail import send_mail
send_mail(
"Account activated",
"Congratulations, you're all ready to use our Django app!",
"from@example.com",
["user@example.com"],
using="notifications",
)
Om using inte anges använder Django e-postkonfigurationen som definieras för konfigurationen "default".
För återanvändbara appar eller Django-funktioner som skickar e-post åt dig kan det finnas ett alternativ för att använda en viss e-postkonfiguration. Djangos loggningsklass AdminEmailHandler låter dig till exempel ange e-postkonfigurationen i alternativet using.
Skicka meddelanden¶
django.core.mail innehåller funktioner för att smidigt skicka e-post samt klasser för att bygga och skicka mer komplexa e-postmeddelanden med bilagor och flera innehållstyper.
Observera
Teckenuppsättningen för e-post som skickas med django.core.mail kommer att ställas in till värdet för din DEFAULT_CHARSET-inställning.
send_mail()¶
- send_mail(subject, message, from_email, recipient_list, *, fail_silently=False, auth_user=None, auth_password=None, connection=None, html_message=None)[source]¶
django.core.mail.send_mail() skickar ett enskilt e-postmeddelande.
Parametrarna subject, message, from_email och recipient_list är obligatoriska.
subject: En sträng.meddelande: En sträng.from_email: En sträng. OmNone, kommer Django att använda värdet av inställningenDEFAULT_FROM_EMAIL.mottagare_lista: En lista med strängar, var och en en e-postadress. Varje medlem irecipient_listkommer att se de andra mottagarna i fältet ”To:” i e-postmeddelandet.
Följande parametrar är valfria och måste anges som nyckelordsargument om de används.
fail_silently: Ett booleskt värde med standardvärdetFalse. Om det sätts tillTrueundertryckersend_mail()vissa fel under sändningen. (Exakt vilka undantag som ignoreras beror på den e-postbackend som används.)auth_user: Det valfria användarnamnet som ska användas för att autentisera sig mot SMTP-servern. Om detta inte anges kommer Django att använda värdet för inställningenEMAIL_HOST_USER.auth_password: Det valfria lösenordet som ska användas för att autentisera sig mot SMTP-servern. Om detta inte anges kommer Django att använda värdet för inställningenEMAIL_HOST_PASSWORD.anslutning: Den valfria e-postbackend som ska användas för att skicka e-post. Om inget anges kommer en instans av standardbackend att användas. Se dokumentationen på Email backends för mer information.html_message: Omhtml_messageanges kommer det resulterande e-postmeddelandet att vara ett e-postmeddelande av typen multipart/alternative medmessagesom innehållstyp av typen text/plain ochhtml_messagesom innehållstyp av typen text/html.using: Ett valfritt alias förMAILERSsom används för att skicka e-post. Om det inte anges används standardkonfigurationen för e-post.
fail_silently, auth_user, auth_password och connection är inte tillåtna tillsammans med argumentet using.
Returvärdet är antalet framgångsrikt levererade meddelanden (som kan vara 0 eller 1 eftersom det bara kan skicka ett meddelande).
Ersatt sedan version 6.0: Att skicka fail_silently och senare parametrar som positionsargument är utfasat.
Ersatt sedan version 6.1: Argumenten fail_silently, auth_user, auth_password och connection är föråldrade. I de flesta fall kan de ersättas med using och en lämplig MAILERS-konfiguration. Se Ersätta fail_silently, Ersätta auth_user och auth_password och Ersätta get_connection() och argumenten connection.
Argumentet using lades till.
Äldre versioner ignorerade fail_silently=True, auth_user och auth_password när connection också angavs. Detta genererar nu TypeError.
sänd_mass_mail()¶
- send_mass_mail(datatuple, *, fail_silently=False, auth_user=None, auth_password=None, connection=None, using=None)[source]¶
django.core.mail.send_mass_mail() är avsedd att hantera massutskick av e-post.
datatuple är en tupel där varje element är i detta format:
(subject, message, from_email, recipient_list)
fail_silently, auth_user, auth_password och connection har samma funktioner som i send_mail(). De måste anges som nyckelordsargument om de används och är inte tillåtna tillsammans med argumentet using.
Nyckelordsargumentet using är ett valfritt alias för MAILERS som används för att skicka e-post. Om det inte anges används standardkonfigurationen för e-post.
Varje separat element i datatuple resulterar i ett separat e-postmeddelande. Liksom i send_mail() ser mottagare i samma recipient_list alla andra adresser i fältet ”To:” i e-postmeddelandena.
Exempelvis skulle följande kod skicka två olika meddelanden till två olika uppsättningar mottagare, men endast en anslutning till e-postservern skulle öppnas:
message1 = (
"Subject here",
"Here is the message",
"from@example.com",
["first@example.com", "other@example.com"],
)
message2 = (
"Another Subject",
"Here is another message",
"from@example.com",
["second@test.com"],
)
send_mass_mail((message1, message2))
Returvärdet är antalet framgångsrikt levererade meddelanden.
Ersatt sedan version 6.0: Att skicka fail_silently och senare parametrar som positionsargument är utfasat.
Ersatt sedan version 6.1: Argumenten fail_silently, auth_user, auth_password och connection är föråldrade. I de flesta fall kan de ersättas med using och en lämplig MAILERS-konfiguration. Se Ersätta fail_silently, Ersätta auth_user och auth_password och Ersätta get_connection() och argumenten connection.
Argumentet using lades till.
Äldre versioner ignorerade fail_silently=True, auth_user och auth_password när connection också angavs. Detta genererar nu TypeError.
send_mass_mail() vs. send_mail()¶
Huvudskillnaden mellan send_mass_mail() och att upprepade gånger anropa send_mail() är att send_mail() öppnar en anslutning till e-postservern varje gång den körs, medan send_mass_mail() använder en enda anslutning för alla meddelanden. Det gör send_mass_mail() något effektivare.
send_mail() med flera to-adresser skickar ett enda e-postmeddelande där både john@example.com och jane@example.com visas i fältet ”To:”:
send_mail(
"Subject",
"Message.",
"from@example.com",
["john@example.com", "jane@example.com"],
)
send_mass_mail() skickar ett separat meddelande per datatuple-element, så att john@example.com och jane@example.com var och en får sitt eget e-postmeddelande:
datatuple = (
("Subject", "Message.", "from@example.com", ["john@example.com"]),
("Subject", "Message.", "from@example.com", ["jane@example.com"]),
)
send_mass_mail(datatuple)
mail_admins()¶
- mail_admins(subject, message, *, fail_silently=False, connection=None, html_message=None, using=None)[source]¶
django.core.mail.mail_admins() är en genväg för att skicka ett e-postmeddelande till webbplatsadministratörerna, enligt definitionen i inställningen ADMINS.
mail_admins() prefixar ämnet med värdet på inställningen EMAIL_SUBJECT_PREFIX, som är "[Django]" som standard.
”From:”-rubriken i e-postmeddelandet kommer att vara värdet för inställningen SERVER_EMAIL.
Denna metod finns för enkelhetens och läsbarhetens skull.
Om html_message anges kommer det resulterande e-postmeddelandet att vara ett multipart/alternative e-postmeddelande med message som innehållstyp text/plain och html_message som innehållstyp text/html.
Nyckelordsargumentet using är ett valfritt alias för MAILERS som används för att skicka e-post. Om det inte anges används standardkonfigurationen för e-post.
Ersatt sedan version 6.0: Att skicka fail_silently och senare parametrar som positionsargument är utfasat.
Ersatt sedan version 6.1: Argumenten fail_silently och connection är utfasade. I de flesta fall kan de ersättas av using med en lämplig MAILERS-konfiguration. Se Ersätta fail_silently och Ersätta get_connection() och argumenten connection.
Argumentet using lades till.
Äldre versioner ignorerade fail_silently=True när även connection angavs. Detta ger nu ett TypeError.
mail_managers()¶
- mail_managers(subject, message, *, fail_silently=False, connection=None, html_message=None, using=None)[source]¶
django.core.mail.mail_managers() är precis som mail_admins(), förutom att den skickar ett e-postmeddelande till webbplatsansvariga, enligt definitionen i inställningen MANAGERS.
Nyckelordsargumentet using är ett valfritt alias för MAILERS som används för att skicka e-post. Om det inte anges används standardkonfigurationen för e-post.
Ersatt sedan version 6.0: Att skicka fail_silently och senare parametrar som positionsargument är utfasat.
Ersatt sedan version 6.1: Argumenten fail_silently och connection är utfasade. I de flesta fall kan de ersättas av using med en lämplig MAILERS-konfiguration. Se Ersätta fail_silently och Ersätta get_connection() och argumenten connection.
Argumentet using lades till.
Äldre versioner ignorerade fail_silently=True när även connection angavs. Detta ger nu ett TypeError.
Klassen ”E-postmeddelande¶
Djangos funktioner send_mail() och send_mass_mail() är egentligen tunna omslag som använder klassen EmailMessage.
Alla funktioner i klassen EmailMessage är inte tillgängliga via send_mail() och relaterade omslagsfunktioner. Om du vill använda avancerade funktioner, såsom BCC-mottagare, filbilagor eller e-post i flera delar, behöver du skapa EmailMessage-instanser direkt.
Observera
Detta är en designfunktion. send_mail() och relaterade funktioner var ursprungligen det enda gränssnitt som Django tillhandahöll. Listan med parametrar som de accepterade växte dock långsamt över tid. Det var rimligt att gå över till en mer objektorienterad design för e-postmeddelanden och bara behålla de ursprungliga funktionerna för bakåtkompatibilitet.
EmailMessage ansvarar för att skapa själva e-postmeddelandet. e-postbackend ansvarar sedan för att skicka e-postmeddelandet.
För enkelhetens skull tillhandahåller EmailMessage metoden send() för att skicka ett enskilt e-postmeddelande. Om du behöver skicka flera meddelanden erbjuder e-postbackendens API ett alternativ.
- class EmailMessage[source]¶
Klassen
EmailMessageinitieras med följande parametrar. Alla parametrar är valfria och kan anges när som helst före anropet av metodensend().De fyra första parametrarna kan skickas som positions- eller nyckelordsargument, men måste ha den angivna ordningen om positionsargument används:
subject: Ämnesraden för e-postmeddelandet.kropp: Texten i brödtexten. Detta bör vara ett vanligt textmeddelande.from_email: Avsändarens adress. Både formernafred@example.comoch"Fred" <fred@example.com>stöds (se Formatera e-postadresser). Om den utelämnas används inställningenDEFAULT_FROM_EMAIL.till: En lista eller tupel av mottagaradresser.
Följande parametrar måste anges som nyckelordsargument om de används:
cc: En lista eller tupel av mottagaradresser som används i ”Cc”-rubriken när e-postmeddelandet skickas.bcc: En lista eller tupel med adresser som används för hemlig kopia när e-postmeddelandet skickas.reply_to: En lista eller tupel av mottagaradresser som används i ”Reply-To”-rubriken när e-postmeddelandet skickas.attachments: En lista med bilagor som ska läggas till i meddelandet. Varje bilaga kan vara en instans avMIMEPartellerEmailAttachment, eller en tupel med attributen(filename, content, mimetype).Changed in Django 6.0:Stöd för
MIMEPart-objekt i listanattachmentslades till.headers: En ordbok med extra rubriker som ska läggas till meddelandet. Nycklarna är rubriknamnet, värdena är rubrikvärdena. Det är upp till den som anropar att se till att rubriknamn och värden är i rätt format för ett e-postmeddelande. Motsvarande attribut ärextra_headers.connection: En instans av en e-postbackend. Denna parameter ignoreras när send_messages() används.Ersatt sedan version 6.1: Argumentet
connectionär utfasat. Definiera i stället enMAILERS-konfiguration med önskade anslutningsalternativ och anropa sedanEmailMessage.send(using="...")med den konfigurationens alias. Se Migrera e-post till mailers.
Ersatt sedan version 6.0: Att skicka alla parametrar utom de fyra första som positionsargument är utfasat.
Till exempel:
from django.core.mail import EmailMessage email = EmailMessage( subject="Hello", body="Body goes here", from_email="from@example.com", to=["to1@example.com", "to2@example.com"], bcc=["bcc@example.com"], reply_to=["another@example.com"], headers={"Message-ID": "foo"}, )
Klassen har följande metoder:
- send(fail_silently=False, *, using=None)[source]¶
Skickar meddelandet. Returnerar
1om meddelandet skickades, annars0. (En tom mottagarlista returnerar0– inget undantag utlöses.)Det valfria nyckelordsargumentet
usinganger ett alias förMAILERSsom används för att skicka e-post. Om det inte anges används standardkonfigurationen för e-post.Om en utfasad anslutning angavs när e-postmeddelandet konstruerades används den anslutningen. Att ange både en anslutning och
usingger ett fel.Om det utfasade nyckelordsargumentet
fail_silentlyärTrueignoreras vissa backendberoende undantag när meddelandet skickas. Att ange bådefail_silentlyochusingger ett fel.Changed in Django 6.1:Argumentet
usinglades till.Äldre versioner ignorerade
fail_silently=Truenär ävenconnectionangavs. Detta ger nu ettTypeError.Ersatt sedan version 6.1: Argumentet
fail_silentlyär utfasat. Se Ersätta fail_silently för alternativ.
- message(*, policy=email.policy.default)[source]¶
Konstruerar och returnerar ett Python-objekt av typen
email.message.EmailMessagesom representerar meddelandet som ska skickas.Nyckelordsargumentet
policygör det möjligt att ange reglerna för att uppdatera och serialisera meddelandets representation. Det måste vara ettemail.policy.Policy-objekt. Standardvärdet äremail.policy.default. I vissa fall kan du vilja användaSMTP,SMTPUTF8eller en anpassad policy. SMTP-e-postbackend använder till exempel policynSMTPför att säkerställa `` ``-radslut enligt SMTP-protokollets krav.Om du behöver utöka Djangos klass
EmailMessagevill du sannolikt åsidosätta den här metoden för att lägga önskat innehåll i Python-objektet EmailMessage.Changed in Django 6.0:Nyckelordsargumentet
policylades till och returtypen uppdaterades till en instans avEmailMessage.
- recipients()[source]¶
Returnerar en lista över alla mottagare av meddelandet, oavsett om de finns i attributen
to,ccellerbcc. Detta är en annan metod som du kan behöva åsidosätta vid underklassning, eftersom SMTP-servern måste få hela mottagarlistan när meddelandet skickas. Om du lägger till ett annat sätt att ange mottagare i klassen måste de också returneras från denna metod.
- attach(filename, content, mimetype)[source]¶
- attach(mimepart)
Skapar en ny bilaga och lägger till den i meddelandet. Det finns två sätt att anropa
attach():Du kan skicka tre argument:
filename,contentochmimetype.filenameär filbilagans namn så som det visas i e-postmeddelandet,contentär data som finns i bilagan ochmimetypeär bilagans valfria MIME-typ. Om du utelämnarmimetypegissas MIME-innehållstypen utifrån bilagans filnamn.Till exempel:
message.attach("design.png", img_data, "image/png")
Om du anger en
mimetypeav typen message/rfc822 kancontentvara ettdjango.core.mail.EmailMessageeller Pythonsemail.message.EmailMessageelleremail.message.Message.För en
mimetypesom börjar med text/ förväntas innehållet vara en sträng. Binära data kommer att avkodas med UTF-8, och om det misslyckas kommer MIME-typen att ändras till application/octet-stream och data kommer att bifogas oförändrat.För bilagor som kräver ytterligare rubriker eller parametrar kan du också skicka ett enskilt Python-objekt av typen
MIMEParttillattach(). Det bifogas direkt till det resulterande meddelandet. Till exempel, för att bifoga en intern bild med Content-ID:import email.utils from email.message import MIMEPart from django.core.mail import EmailMultiAlternatives message = EmailMultiAlternatives(...) image_data_bytes = ... # Load image as bytes # Create a random Content-ID, including angle brackets cid = email.utils.make_msgid() inline_image = email.message.MIMEPart() inline_image.set_content( image_data_bytes, maintype="image", subtype="png", # or "jpeg", etc. depending on the image type disposition="inline", cid=cid, ) message.attach(inline_image) # Refer to Content-ID in HTML without angle brackets message.attach_alternative(f'… <img src="cid:{cid[1:-1]}"> …', "text/html")
Pythons dokumentation för
email.contentmanager.set_content()beskriver de argument som stöds förMIMEPart.set_content().Changed in Django 6.0:Stöd för
MIMEPart-bilagor lades till.Ersatt sedan version 6.0: Stöd för
email.mime.base.MIMEBase-bilagor är utfasat. Använd i ställetMIMEPart.
- attach_file(path, mimetype=None)[source]¶
Skapar en ny bilaga med en fil från filsystemet. Anropa den med sökvägen till filen som ska bifogas och, valfritt, den MIME-typ som ska användas för bilagan. Om MIME-typen utelämnas gissas den utifrån filnamnet. Du kan använda den så här:
message.attach_file("/images/weather_map.png")
För MIME-typer som börjar med text/ hanteras binära data som i
attach().
- class EmailAttachment¶
En namngiven tupel för att lagra bilagor till ett e-postmeddelande.
Den namngivna tupeln har följande index:
filnamninnehållmimetype
Skicka alternativa innehållstyper¶
Skicka flera versioner av innehållet¶
Det kan vara användbart att inkludera flera versioner av innehållet i ett e-postmeddelande; det klassiska exemplet är att skicka både text- och HTML-versioner av ett meddelande. Med Djangos e-postbibliotek kan du göra detta med klassen EmailMultiAlternatives.
- class EmailMultiAlternatives[source]¶
En underklass till
EmailMessagesom tillåter ytterligare versioner av meddelandetexten i e-postmeddelandet via metodenattach_alternative(). Denna ärver direkt alla metoder (inklusive klassinitialiseringen) frånEmailMessage.- alternatives¶
En lista med namngivna tupler av typen
EmailAlternative. Detta är särskilt användbart i tester:self.assertEqual(len(msg.alternatives), 1) self.assertEqual(msg.alternatives[0].content, html_content) self.assertEqual(msg.alternatives[0].mimetype, "text/html")
Alternativ bör endast läggas till med hjälp av metoden
attach_alternative()eller skickas till konstruktören.
- attach_alternative(content, mimetype)[source]¶
Bifoga en alternativ representation av meddelandetexten i e-postmeddelandet.
Om du t.ex. vill skicka en kombination av text och HTML kan du skriva:
from django.core.mail import EmailMultiAlternatives subject = "hello" from_email = "from@example.com" to = "to@example.com" text_content = "This is an important message." html_content = "<p>This is an <strong>important</strong> message.</p>" msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg.attach_alternative(html_content, "text/html") msg.send()
- body_contains(text)[source]¶
Returnerar ett booleskt värde som anger om den angivna
textenfinns med i e-postmeddelandetsbodyoch i alla bifogade alternativ av MIME-typentext/*.Detta kan vara användbart när du testar e-postmeddelanden. Till exempel:
def test_contains_email_content(self): subject = "Hello World" from_email = "from@example.com" to = "to@example.com" msg = EmailMultiAlternatives(subject, "I am content.", from_email, [to]) msg.attach_alternative("<p>I am content.</p>", "text/html") self.assertIs(msg.body_contains("I am content"), True) self.assertIs(msg.body_contains("<p>I am content.</p>"), False)
- class EmailAlternative¶
En namngiven tupel för att lagra alternativa versioner av e-postinnehåll.
Den namngivna tupeln har följande index:
innehållmimetype
Uppdatering av standardinnehållstypen¶
Som standard är MIME-typen för parametern body i en EmailMessage "text/plain". Det är god praxis att låta detta vara, eftersom det garanterar att alla mottagare kan läsa e-postmeddelandet, oavsett e-postklient. Om du däremot är säker på att mottagarna kan hantera en alternativ innehållstyp kan du använda attributet content_subtype i klassen EmailMessage för att ändra huvudinnehållstypen. Huvudtypen är alltid "text", men du kan ändra undertypen. Till exempel:
msg = EmailMessage(subject, html_content, from_email, [to])
msg.content_subtype = "html" # Main content is now text/html
msg.send()
Säker e-postsändning¶
Varje offentlig webbplats som kan skicka e-post kommer förr eller senare att utsättas för försök att missbruka den för spam, nätfiske eller annat skadligt innehåll. En fullständig genomgång av sårbarheter vid e-postsändning ligger utanför Djangos dokumentation, men det finns många referenser på webben. Två bra utgångspunkter är:
Princeton Universitys vägledning om att förhindra e-postmissbruk i webbformulär. Även om detta är en intern referens för användare av Princeton’s Drupal Site Builder gäller nästan alla råd i lika hög grad för webbplatser byggda med Django (eller något annat webbramverk).
OWASP:s faktablad om e-postvalidering och verifiering i identitetssystem. Det handlar främst om användning av e-post i autentiseringssammanhang. Många av rekommendationerna hanteras av
django.contrib.authoch andra Django-funktioner, men frågor som hastighetsbegränsning och säkra flöden för att ändra e-postadress är utvecklarens ansvar.
Att fundera på hur e-post kan missbrukas (och vidta åtgärder för att begränsa det) är särskilt viktigt om webbplatsen kan skicka till overifierade adresser. Funktioner som anmälan till nyhetsbrev, kontaktformulär som skickar en kopia eller ett automatiskt svar till avsändaren samt ”dela den här sidan” kan vara attraktiva mål.
Formatera e-postadresser¶
E-postadresser kan innehålla ett ”vänligt” visningsnamn tillsammans med adressen user@domain. Du kan till exempel inkludera företagets namn i inställningen DEFAULT_FROM_EMAIL:
DEFAULT_FROM_EMAIL = '"Example, Inc." <contact@example.com>'
De dubbla citattecknen runt "Example, Inc." behövs för att kommat inte ska läsas som en avgränsning mellan två olika adresser. En fast adress, som skrivs ut för hand enligt exemplet ovan, är säker, men en adress som sätts samman av variabla delar (särskilt opålitliga indata) kräver mer försiktighet.
Varning
Använd aldrig strängformatering för att bygga en e-postadress av variabla delar. Till exempel är f'"{name}" <{email}>' osäkert.
E-postadresshuvuden har komplexa syntaxregler (ungefär som HTML eller SQL), så att skapa dem genom att kombinera strängar skapar en injektionssårbarhet. Även om du har validerat formatet för email kan en angripare utnyttja delen name för att injicera ytterligare adresser.
Undvik detta genom att alltid använda ett vältestat bibliotek som är särskilt avsett för att formatera e-postadresser, till exempel Pythons klass email.headerregistry.Address (ersättningen för den äldre funktionen formataddr(), som inte stöder internationaliserade domännamn).
För att till exempel inkludera en användares fullständiga namn när du skickar e-post till personen (där user är en instans av standardmodellen User):
from django.core.mail import send_mail
from email.headerregistry import Address
def send_mail_to_user(user, subject, body, from_email=None):
# Safely create an email address with the user's name.
# (addr_spec is the technical term for the user@domain address.)
address = Address(
display_name=user.get_full_name(),
addr_spec=user.email,
)
send_mail(subject, body, from_email, [address])
Djangos inbyggda e-postbackendar stöder att använda objekt av typen Address direkt i alla adressfält, som visas här. Det gör även många anpassade backendar och tredjepartsbackendar. Men om det orsakar ett TypeError eller annat problem med en viss backend ska du använda str(address) för att omvandla objektet till en säker, korrekt formaterad sträng.
Förhindra injektion av rubrik¶
E-posthuvudinjektion är ett säkerhetsangrepp där en angripare manipulerar e-postrubriker för att ändra avsedd avsändare eller mottagare, ämnesrad eller möjligen till och med hela den synliga meddelandetexten.
En typ av rubrikinjektion utnyttjar syntaxen för adressrubriker. Du ansvarar för att förhindra detta när du bygger e-postadresser från användartillhandahållen indata, enligt beskrivningen i Formatera e-postadresser ovan.
En annan attack, som kanske är mer välkänd, är CRLF-injektion. Den använder tecknen radretur och radmatning för att infoga ytterligare rubriker i e-postmeddelandet. Django förhindrar detta genom att utlösa ValueError om dessa tecken förekommer i något rubrikfält när meddelandet ska skickas.
Äldre versioner utlöste django.core.mail.BadHeaderError för vissa ogiltiga rubriker. Det har ersatts med ValueError.
Djangos CRLF-skydd bygger på att Pythons moderna EmailPolicy används i Djangos EmailMessage.message(). Anpassade e-postbackendar som inte anropar den funktionen, eller som anropar den med den äldre policyn compat32, ansvarar för att själva förhindra CRLF-injektion.
Skicka många meddelanden effektivt¶
Att upprätta och stänga en SMTP-anslutning (eller någon annan nätverksanslutning för den delen) är en dyr process. Om du har många e-postmeddelanden att skicka är det klokt att återanvända en SMTP-anslutning i stället för att skapa och förstöra en anslutning varje gång du vill skicka ett e-postmeddelande.
Det finns två sätt att instruera en e-postbackend att återanvända en anslutning. Båda innebär att hämta en e-postbackendinstans från mail.mailers och använda backendens API.
Det första sättet är att använda backendens metod send_messages(). Den tar en lista med instanser av EmailMessage (eller en underklass) och skickar dem alla med samma anslutning.
Om du till exempel har en funktion som heter get_notification_emails() och returnerar en lista med EmailMessage-objekt som representerar något periodiskt e-postutskick du vill skicka, kan du skicka dessa meddelanden med ett enda anrop till send_messages():
from django.core import mail
email_list = get_notification_emails()
# Use the default mailer. You could substitute
# mail.mailers["alias"] for a specific mailer.
backend = mail.mailers.default
backend.send_messages(email_list)
I detta exempel öppnar anropet till send_messages() en anslutning i backenden, skickar listan med meddelanden och stänger sedan anslutningen igen. (Så implementeras send_mass_mail().)
Det andra sättet är att använda metoderna open() och close() i e-postbackenden för att styra anslutningen manuellt. send_messages() öppnar eller stänger inte anslutningen om den redan är öppen, så om du öppnar anslutningen manuellt kan du styra när den stängs. Till exempel:
from django.core import mail
# Use the "notifications" mailer configuration.
backend = mail.mailers["notifications"]
# Manually open the connection.
backend.open()
# Construct an email message. (Passing None as the third argument
# uses settings.DEFAULT_FROM_EMAIL as the "From:" address.)
email1 = mail.EmailMessage("Hi", "Message", None, ["to1@example.com"])
# Send the email. The connection was already open, so send_messages()
# leaves it open after sending.
backend.send_messages([email1])
# Construct and send two more messages. The connection is still open.
email2 = mail.EmailMessage("Hi", "Message", None, ["to2@example.com"])
email3 = mail.EmailMessage("Hi", "Message", None, ["to3@example.com"])
backend.send_messages([email2, email3])
# Because we opened it, we need to manually close the connection.
backend.close()
När du öppnar en backends anslutning manuellt ansvarar du för att den stängs. Exemplet ovan har faktiskt ett fel: om ett undantag inträffar medan meddelandena skickas stängs inte anslutningen. Det kan åtgärdas med en try-finally-sats, men det är bättre att använda backendinstansen som en kontexthanterare, eftersom den då automatiskt anropar open() och close() vid behov.
Detta motsvarar föregående exempel, men använder backenden som en kontexthanterare för att undvika att lämna anslutningen öppen vid fel:
from django.core import mail
# Use mail.mailers[...] as a context manager.
with mail.mailers["notifications"] as backend:
# The backend connection is automatically opened inside the context.
email1 = mail.EmailMessage("Hi", "Message", None, ["to1@example.com"])
backend.send_messages([email1])
# The connection is still open, and is reused for the second send.
email2 = mail.EmailMessage("Hi", "Message", None, ["to2@example.com"])
email3 = mail.EmailMessage("Hi", "Message", None, ["to3@example.com"])
backend.send_messages([email2, email3])
# After exiting the context (either normally or because of an error),
# the backend connection is automatically closed.
Backend för e-post¶
Själva sändningen av ett e-postmeddelande hanteras av e-postbackend.
Django innehåller flera e-postbackendar. Med undantag för SMTP-backenden är de främst användbara under testning och utveckling. Om de inbyggda backendarna inte uppfyller dina behov finns tredjepartspaket tillgängliga. Du kan även skapa en underklass av någon av de inbyggda backendarna för att ändra dess beteende, eller till och med skriva en egen e-postbackend.
SMTP-backend¶
SMTP-e-postbackenden ansluter till en SMTP-server för att skicka e-post. Använd den genom att ange BACKEND till "django.core.mail.backends.smtp.EmailBackend".
SMTP-backenden stöder följande OPTIONS:
"host"(obligatorisk): SMTP-serverns värdnamn eller IP-adress."port": portnumret att ansluta till på SMTP-värden. Om det utelämnas används standardporten för anslutningsprotokollet beroende på alternativen"use_tls"och"use_ssl":587för TLS,465för SSL eller25för en oskyddad anslutning."username"och"password": ange dessa om servern kräver SMTP-autentisering (inloggningsuppgifter för ”SMTP AUTH”, ibland kallat SMTP-inloggning).Även om användarnamnet ofta är en e-postadress får det inte förväxlas med standardadresserna för ”From:”. Dessa definieras av inställningarna
DEFAULT_FROM_EMAILochSERVER_EMAIL."use_tls"eller"use_ssl": sätt ett av dessa alternativ tillTrueför att ansluta till SMTP-servern med ett säkert protokoll –"use_tls"för explicit TLS eller"use_ssl"för SSL (implicit TLS)."ssl_certfile"och"ssl_keyfile": om SMTP-serverns SSL/TLS-anslutning kräver klientcertifikatautentisering använder du dessa alternativ för att ange sökvägarna till en PEM-formaterad certifikatkedjefil och en privat nyckelfil. (Nyckelfilen kan utelämnas om certifikatfilen innehåller den privata nyckeln.)Dessa alternativ är inte avsedda för användning med en privat certifikatutfärdare eller ett självsignerat SMTP-servercertifikat. Se Privata och självsignerade SMTP-servercertifikat nedan.
Observera att dessa alternativ inte medför någon kontroll av certifikatets giltighet. De skickas vidare till den underliggande SSL-anslutningen. Se dokumentationen för Pythons metod
ssl.SSLContext.wrap_socket()för information om hur filen med certifikatkedjan och filen med privat nyckel hanteras."timeout": tidsgränsen (i sekunder) för anslutning till SMTP-servern och andra blockerande åtgärder. Om den inte anges hämtas värdet frånsocket.getdefaulttimeout(), vars standardvärde är ingen tidsgräns (None), vilket innebär att SMTP-åtgärder kan blockera obegränsat länge."fail_silently": sätt tillTrueför att ignorera vissa fel när ett meddelande skickas. AllaOSErrors ignoreras när SMTP-anslutningen öppnas, ochsmtplib.SMTPException-fel ignoreras under kommunikationen med servern. Detta undertrycker både tillfälliga nätverksstörningar och allvarliga konfigurationsproblem. Det ignorerar dock inte alla fel, och problem med att serialisera meddelandet ignoreras inte tyst. (Alternativet finns för bakåtkompatibilitet men rekommenderas inte för normal användning.)
Exempel:
MAILERS = {
"default": {
"BACKEND": "django.core.mail.backends.smtp.EmailBackend",
"OPTIONS": {
"host": "smtp.example.net",
"use_tls": True,
"username": "my-app",
"password": os.environ["MY_APP_SMTP_PASSWORD"],
"timeout": 10,
},
},
}
Ersatt sedan version 6.1: När inställningen MAILERS inte är definierad använder Django SMTP-backenden som standardutskickare (standardinställningen EMAIL_BACKEND) och ansluter till localhost på port 25. Detta beteende tas bort i Django 7.0, som inte kommer att ha någon standardkonfiguration för e-postutskickare.
När SMTP-backenden används utan att MAILERS är definierad hämtas alternativen ovan från de föråldrade inställningarna EMAIL_HOST, EMAIL_PORT, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD, EMAIL_USE_TLS, EMAIL_USE_SSL, EMAIL_SSL_KEYFILE, EMAIL_SSL_CERTFILE och EMAIL_TIMEOUT. (Det finns ingen inställning som motsvarar alternativet "fail_silently".)
- class backends.smtp.EmailBackend¶
Det rekommenderas inte att instansiera en
EmailBackend-klass direkt. Användmailersför att hämta en backendinstans.När SMTP-klassen
EmailBackendkonstrueras direkt (utan att gå viamailers) accepterar den alternativen ovan som nyckelordsargument. Standardvärdena kommer från motsvarande, utfasadeEMAIL_*-inställningar.hostär inte obligatorisk och har standardvärdet"localhost", ochporthar standardvärdet25även omuse_tlselleruse_sslär True.När inställningen
MAILERSär definierad orsakar ett försök att skapa en SMTP-EmailBackenddirekt ettAttributeError.Ersatt sedan version 6.1: Att direkt skapa en instans av en klass
EmailBackendkommer inte att stödjas i Django 2028. Odokumenterad användning ger en annan hantering av standardargument än i tidigare utgåvor.
Privata och självsignerade SMTP-servercertifikat¶
Om SMTP-servern använder ett SSL-certifikat från en privat certifikatutfärdare (CA) ska CA:ns rotcertifikat läggas till i klientens systemomfattande CA-samling (där Django körs). På motsvarande sätt ska ett självsignerat certifikat läggas till i klientens systemomfattande CA-samling så att det kan betraktas som betrott. SMTP-backendens alternativ "ssl_certfile" kan inte användas för CA-rötter eller självsignerade certifikat.
Följ plattformsspecifika instruktioner för att lägga till certifikatet i systemets CA-katalog. Om det inte är möjligt eller önskvärt att ändra systemkatalogen är ett alternativ att använda OpenSSL:s miljövariabler SSL_CERT_FILE eller SSL_CERT_DIR för att ange en egen certifikatkatalog.
För mer komplexa scenarier kan SMTP-backenden underklassas för att lägga till rotcertifikat i dess ssl_context med ssl.SSLContext.load_verify_locations().
Backend för konsol¶
I stället för att skicka verkliga e-postmeddelanden skriver konsolbackenden de meddelanden som skulle ha skickats till standardutdata. Använd den genom att ange BACKEND till "django.core.mail.backends.console.EmailBackend".
Konsolbackenden stöder följande OPTIONS:
"stream": ett strömliknande objekt att skriva till. Standardvärdet ärstdout."fail_silently": angeTrueför att ignorera alla fel när meddelandet skrivs till strömmen, inklusive fel vid serialisering av meddelandet. (Alternativet finns för bakåtkompatibilitet men rekommenderas inte.)
Denna backend är inte avsedd att användas i produktion - den tillhandahålls som en bekvämlighet som kan användas under utveckling.
Inställningsfilen som skapas av startproject definierar nu MAILERS med konsolbackenden som standardkonfiguration.
Backend för filer¶
Filbackenden skriver e-postmeddelanden till en fil. En ny fil skapas för varje ny session som öppnas i denna backend. Använd den genom att ange BACKEND till "django.core.mail.backends.filebased.EmailBackend".
Filbackenden stöder följande OPTIONS:
"file_path"(obligatorisk): katalogen som filerna skrivs till. Kan vara en sträng eller ettpathlib.Path-objekt. Om katalogen inte finns försöker filbackenden skapa den."fail_silently": angeTrueför att ignorera alla fel när meddelandet skrivs till filen – inklusive fel vid serialisering av meddelandet – men inte fel som rör säkerställandet att filsökvägens katalog finns. (Alternativet finns för bakåtkompatibilitet men rekommenderas inte.)
Denna backend är inte avsedd att användas i produktion - den tillhandahålls som en bekvämlighet som kan användas under utveckling.
Ersatt sedan version 6.1: När filbackenden används utan att inställningen MAILERS är definierad hämtar den alternativet file_path från inställningen EMAIL_FILE_PATH.
Backend i minnet¶
Backenden 'locmem' lagrar meddelanden i ett särskilt attribut i modulen django.core.mail. Attributet outbox skapas när det första meddelandet skickas. Det är en lista med en EmailMessage-instans för varje meddelande som skulle ha skickats. Meddelanden i utkorgen förses med attributet sent_using, som identifierar det MAILERS-alias som användes för att skicka meddelandet.
Använd minnesbackenden genom att ange BACKEND till "django.core.mail.backends.locmem.EmailBackend". Den stöder inga OPTIONS.
Djangos testkörning växlar automatiskt till denna backend för testning.
Denna backend är inte avsedd att användas i produktion - den tillhandahålls som en bekvämlighet som kan användas under utveckling och testning.
Attributet sent_using lades till i meddelanden i utkorgen.
Dummy backend¶
Som namnet antyder gör dummy-backenden ingenting med dina meddelanden. Använd den genom att ange BACKEND till "django.core.mail.backends.dummy.EmailBackend". Den stöder inga OPTIONS.
Denna backend är inte avsedd att användas i produktion - den tillhandahålls som en bekvämlighet som kan användas under utveckling.
Tredjepartsbackendar¶
Det finns lösningar som underhålls av communityn!
Django har ett levande ekosystem. Det finns e-postbackendar som lyfts fram på sidan Community Ecosystem. Djangos Email grid på Django Packages erbjuder ännu fler alternativ!
Det finns tredjepartsbackendar för e-post som:
Integrerar direkt med kommersiella e-postleverantörers API:er (som ofta har extrafunktioner som inte är tillgängliga via SMTP).
Lägger ut e-postsändning på asynkrona uppgiftsköer.
Lägger till funktioner i andra e-postbackendar, till exempel upprätthållande av listor över mottagare som inte får kontaktas eller loggning av skickade meddelanden.
Tillhandahåller verktyg för utveckling och felsökning, till exempel sandbox-fångst och förhandsvisningar av e-post i webbläsaren.
Definiera en anpassad backend för e-post¶
Om du behöver ändra hur e-post skickas kan du skriva en egen e-postbackend. Använd en anpassad backend genom att ange BACKEND till Pythons importsökväg för din backendklass och OPTIONS till de nyckelordsargument för __init__() som backenden stöder.
Anpassade e-postbackendar bör vara underklasser till BaseEmailBackend, som finns i modulen django.core.mail.backends.base. En anpassad e-postbackend måste implementera metoden send_messages(email_messages). Metoden tar emot en lista med EmailMessage-instanser och returnerar antalet meddelanden som har levererats korrekt. Om backenden har ett begrepp om en beständig session eller anslutning bör du även implementera metoderna open() och close(). Se smtp.EmailBackend som referensimplementation.
Hämta en instans av en e-postbackend¶
Fabriken mailers i django.core.mail returnerar instanser av e-postbackendar.
- mailers¶
- New in Django 6.1.
Du kan komma åt de e-postutskickare som konfigurerats i inställningen
MAILERSvia ett dict-liknande objekt:django.core.mail.mailers:>>> from django.core.mail import mailers >>> mailers["notifications"]
Om den angivna nyckeln inte är definierad utlöses felet
MailerDoesNotExist. Andra konfigurationsproblem utlöser feletInvalidMailer.
- mailers.default¶
- New in Django 6.1.
Som en genväg kan standardutskickaren nås via
django.core.mail.mailers.default:>>> from django.core.mail import mailers >>> mailers.default
Detta motsvarar
mailers["default"]. Om ingen standardutskickare har konfigurerats utlöses feletMailerDoesNotExist.Ersatt sedan version 6.1: Om inställningen
MAILERSinte är definierad skaparmailers.defaulten e-postbackendinstans från den utfasadeEMAIL_BACKENDoch relaterade inställningar. Detta stöder bakåtkompatibilitet med Django 6.0 och tidigare.Detta beteende (och dessa inställningar) kommer att tas bort i Django 2028.
- get_connection(backend=None, *, fail_silently=False, **kwargs)[source]¶
Den utfasade funktionen
django.core.mail.get_connection()skapar och returnerar en instans av en e-postbackend. Dess beteende beror på inställningenMAILERSoch hur funktionen anropas.Om inställningen
MAILERSär definierad:get_connection()utan argument returnerarmailers.default.get_connection(...)som anropas med enbartfail_silentlyeller andra nyckelordsargument skapar en instans avMAILERS["default"]med nyckelorden tillagda till standardutskickarensOPTIONS.get_connection(backend, ...)med en importsökväg för en backend utlöser ett fel.
Om inställningen
MAILERSinte är definierad:get_connection()utan argument returnerar en instans av den e-postbackend som anges iEMAIL_BACKEND.Om du anger argumentet
backendinstansieras den backenden.Om nyckelordsargumentet
fail_silentlyär True ignoreras vissa backendberoende undantag under e-postsändningen utan felmeddelande.Alla andra nyckelordsargument skickas direkt till konstruktören för e-postbackend.
Ersatt sedan version 6.0: Att ange
fail_silentlysom positionsargument är utfasat.Ersatt sedan version 6.1:
get_connection()är utfasad och tas bort i Django 7.0. Byt tillmailers[alias]. Se Ersätta get_connection() och argumenten connection för förslag på migrering.
API för e-postbackendar¶
Instanser av en e-postbackendklass har följande metoder:
open()instansierar en långlivad anslutning för e-postsändning.close()stänger den aktuella anslutningen för e-postsändning.send_messages(email_messages)skickar en lista medEmailMessage-objekt. Om anslutningen inte är öppen öppnar anropet implicit anslutningen och stänger den därefter. Om anslutningen redan är öppen lämnas den öppen efter att e-post har skickats.
En backendinstans kan också användas som kontexthanterare, vilket automatiskt anropar open() och close() vid behov. Ett exempel finns i Skicka många meddelanden effektivt.
Konfigurera e-post för utveckling¶
Det finns tillfällen då man inte vill att Django ska skicka e-post överhuvudtaget. Till exempel när du utvecklar en webbplats vill du förmodligen inte skicka ut tusentals e-postmeddelanden - men du kanske vill validera att e-postmeddelanden kommer att skickas till rätt personer under rätt förhållanden och att dessa e-postmeddelanden innehåller rätt innehåll.
Det enklaste sättet att konfigurera e-post för lokal utveckling är att använda e-postbackend console. Denna backend omdirigerar all e-post till stdout, så att du kan inspektera innehållet i e-postmeddelanden.
E-postbackend file kan också vara användbar under utvecklingsarbetet - den här backend-enheten dumpar innehållet i varje SMTP-anslutning till en fil som kan inspekteras när du vill.
Ett annat sätt är att använda en mockad SMTP-server som tar emot e-postmeddelanden lokalt och visar dem i terminalen, men inte faktiskt skickar något. Paketet aiosmtpd erbjuder ett sätt att göra detta:
python -m pip install "aiosmtpd >= 1.4.5"
python -m aiosmtpd -n -l localhost:8025
Detta kommando startar en minimal SMTP-server som lyssnar på port 8025 på localhost. Servern skriver ut alla e-posthuvuden och e-postmeddelandets brödtext till standardutdata. Du behöver sedan bara ange SMTP-backendens OPTIONS "host" och "port" därefter. En mer detaljerad diskussion om SMTP-serveralternativ finns i dokumentationen för modulen aiosmtpd.
Information om hur du enhetstestar e-postmeddelanden i din applikation finns i avsnittet E-posttjänster i testdokumentationen.