Skicka e-postLink to this heading
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 exempelLink to this heading
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-postLink to this heading
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.
Flera e-postkonfigurationerLink to this heading
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 meddelandenLink to this heading
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.
send_mail()Link to this heading
- send_mail(subject, message, from_email, recipient_list, *, fail_silently=False, auth_user=None, auth_password=None, connection=None, html_message=None)Link to this definition
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).
sänd_mass_mail()Link to this heading
- send_mass_mail(datatuple, *, fail_silently=False, auth_user=None, auth_password=None, connection=None, using=None)Link to this definition
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.
send_mass_mail() vs. send_mail()Link to this heading
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()Link to this heading
- mail_admins(subject, message, *, fail_silently=False, connection=None, html_message=None, using=None)Link to this definition
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.
mail_managers()Link to this heading
- mail_managers(subject, message, *, fail_silently=False, connection=None, html_message=None, using=None)Link to this definition
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.
Klassen ”E-postmeddelandeLink to this heading
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.
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 EmailMessageLink to this definition
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).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.
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)Link to this definition
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.
- message(*, policy=email.policy.default)Link to this definition
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.
- recipients()Link to this definition
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)Link to this definition
- 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().
- attach_file(path, mimetype=None)Link to this definition
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 EmailAttachmentLink to this definition
En namngiven tupel för att lagra bilagor till ett e-postmeddelande.
Den namngivna tupeln har följande index:
filnamninnehållmimetype
Skicka alternativa innehållstyperLink to this heading
Skicka flera versioner av innehålletLink to this heading
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 EmailMultiAlternativesLink to this definition
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.- alternativesLink to this definition
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)Link to this definition
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)Link to this definition
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 EmailAlternativeLink to this definition
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ållstypenLink to this heading
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ändningLink to this heading
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-postadresserLink to this heading
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.
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 rubrikLink to this heading
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.
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 effektivtLink to this heading
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-postLink to this heading
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-backendLink to this heading
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,
},
},
}
- class backends.smtp.EmailBackendLink to this definition
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.
Privata och självsignerade SMTP-servercertifikatLink to this heading
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 konsolLink to this heading
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.
Backend för filerLink to this heading
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.
Backend i minnetLink to this heading
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.
Dummy backendLink to this heading
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.
TredjepartsbackendarLink to this heading
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-postLink to this heading
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-postbackendLink to this heading
Fabriken mailers i django.core.mail returnerar instanser av e-postbackendar.
- mailersLink to this definition
-
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.defaultLink to this definition
-
Som en genväg kan standardutskickaren nås via
django.core.mail.mailers.default:>>> from django.core.mail import mailers >>> mailers.defaultDetta motsvarar
mailers["default"]. Om ingen standardutskickare har konfigurerats utlöses feletMailerDoesNotExist.
- get_connection(backend=None, *, fail_silently=False, **kwargs)Link to this definition
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.
API för e-postbackendarLink to this heading
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 utvecklingLink to this heading
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.