Migrera e-post till mailersLink to this heading

Django 6.1 introducerade inställningen MAILERS, som ersätter EMAIL_BACKEND och flera andra inställningar av typen EMAIL_*. Det introducerade också mail.mailers för att hämta konfigurerade instanser av e-postbackend, som ersättning för mail.get_connection(). Ett nytt argument, using, ersätter det tidigare connection i Django-funktioner som skickar e-post.

Den här guiden ger information om hur befintliga projekt migreras till den nya mailers-funktionaliteten.

Alla Django-projekt som skickar e-post bör:

  • Om du använder tredjepartspaket som skickar e-post ska du verifiera deras kompatibilitet med MAILERS innan du gör andra ändringar.

  • Uppdatera e-postrelaterade inställningar.

  • Kör med utfasningsvarningar aktiverade (se howto/upgrade-version:Hantera utfasningsvarningar) för att identifiera annan kod som behöver uppdateras.

Andra uppdateringar behövs bara för projekt eller återanvändbara Django-bibliotek som använder dessa specifika funktioner:

Migrera inställningarLink to this heading

Ofta är den enda ändring som behövs för att migrera till mailers att uppdatera e-postrelaterade inställningar. I projektets inställningar definierar du en MAILERS-ordbok med en post "default" som motsvarar de tidigare inställningarna EMAIL_*:

Code
MAILERS = {
    "default": {
        "BACKEND": ...,  # value of EMAIL_BACKEND setting
        "OPTIONS": {
            # values from other deprecated EMAIL_* settings
            ...,
        },
    },
}

För att till exempel uppdatera dessa inställningar:

Code
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "mail.example.net"
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = "user@example.net"
EMAIL_HOST_PASSWORD = "password"

använder du:

Code
MAILERS = {
    "default": {
        "BACKEND": "django.core.mail.backends.smtp.EmailBackend",
        "OPTIONS": {
            "host": "mail.example.net",
            "use_tls": True,
            # port is not needed: it defaults to 587 with use_tls True.
            "username": "user@example.net",
            "password": "password",
        },
    },
}

Den fullständiga listan över utfasade inställningar EMAIL_* och vart de ska flyttas i en MAILERS-konfiguration är:

  • EMAIL_BACKEND blir "BACKEND". Om inställningarna inte definierade EMAIL_BACKEND var standardvärdet "django.core.mail.backends.smtp.EmailBackend" (vilket också är standard om en MAILERS-konfiguration inte anger "BACKEND").

  • EMAIL_FILE_PATH blir "file_path" i "OPTIONS" (med "BACKEND" inställt på "django.core.mail.backends.filebased.EmailBackend").

  • EMAIL_HOST blir "host" i "OPTIONS". En "host" krävs för SMTP-e-postbackend. Om inställningarna inte definierade EMAIL_HOST anger du "host" som "localhost" (standardvärdet för den utfasade inställningen).

  • EMAIL_HOST_PASSWORD blir "password" i "OPTIONS".

  • EMAIL_HOST_USER blir "username" i "OPTIONS". (Observera att "username" inte helt följer namnkonventionen för de andra utfasade inställningarna.)

  • EMAIL_PORT blir "port" i "OPTIONS". Det kan utelämnas om anslutningen använder standardporten för sin säkerhet (465 för SSL, 587 för TLS eller 25 för en oskyddad SMTP-anslutning).

  • EMAIL_SSL_CERTFILE blir "ssl_certfile" i "OPTIONS".

  • EMAIL_SSL_KEYFILE blir "ssl_keyfile" i "OPTIONS".

  • EMAIL_TIMEOUT blir "timeout" i "OPTIONS".

  • EMAIL_USE_SSL blir "use_ssl" i "OPTIONS".

  • EMAIL_USE_TLS blir "use_tls" i "OPTIONS".

För tredjeparts- eller anpassade e-postbackendar beror tillgängliga "OPTIONS" på backend. Se dokumentationen från tredje part, eller för anpassade backendar Migrera anpassade e-postbackendar nedan.

Avsnittet Konfigurera e-post innehåller mer information om inställningen MAILERS och ytterligare konfigurationsexempel.

Förbereda återanvändbara bibliotekLink to this heading

I de flesta fall fortsätter tredjepartspaket som skickar e-post via Django att fungera med projekt vars inställningar har uppgraderats för att använda MAILERS. (Om de använder utfasade e-postfunktioner kommer dessa förstås att ge utfasningsvarningar.)

Det finns två utfasade funktioner som inte stöds när MAILERS har definierats i ett projekts inställningar:

  • Att försöka komma åt någon av de utfasade inställningarna EMAIL_* i django.conf.settings (till exempel att kontrollera settings.EMAIL_BACKEND eller använda settings.EMAIL_HOST_USER).

  • Att anropa mail.get_connection("path.to.EmailBackend") med en specifik backend-sökväg. (Andra argument till get_connection() stöds fortfarande och ger bara utfasningsvarningar när MAILERS är definierat.)

Om ett tredjepartspaket gör något av detta kommer projekt som använder det inte att kunna byta till inställningen MAILERS förrän paketet har uppdaterats.

Åtgärda fel av typen ”not available when MAILERS is defined”Link to this heading

Om något av dessa fel uppstår i ett tredjepartspaket betyder det att paketet inte är kompatibelt med inställningen MAILERS:

  • AttributeError: "The name setting is not available when MAILERS is defined" där name är EMAIL_BACKEND, EMAIL_HOST eller någon annan av de utfasade inställningarna.

  • RuntimeError: get_connection(backend, ...) is not supported with MAILERS.

Om du ser dessa fel, kontrollera om det finns en nyare version av beroendet. Om det inte finns det (och det inte finns något alternativ till paketet) behöver du ta bort MAILERS från inställningarna och ersätta den med motsvarande utfasade e-postinställningar tills paketet har uppdaterats.

Om felen kommer från din egen kod kan du läsa de andra avsnitten i denna migreringsguide för rekommenderade uppdateringar.

Ersätta get_connection() och argumenten connectionLink to this heading

Ersättningarna för den utfasade funktionen mail.get_connection() och argumenten connection till andra e-postfunktioner beror på hur och varför anslutningarna skapas:

  • get_connection() anropas utan argument

    Ersätt med mailers.default. Uppdatera till exempel denna kod:

    Code
    connection = mail.get_connection()
    connection.send_messages([email1, email2])
    

    till:

    Code
    connection = mail.mailers.default
    connection.send_messages([email1, email2])
    

    Observera att mailers.default är standard för Djangos funktioner som skickar e-post. Kod som denna:

    Code
    mail.send_mail(..., connection=mail.get_connection())
    

    kan uppdateras till:

    Code
    mail.send_mail(...)  # No connection arg needed.
    
  • get_connection(fail_silently=True)

    Se Ersätta fail_silently.

  • get_connection(...) anropas med andra argument

    Definiera en anpassad MAILERS-konfiguration med önskad backend och önskade alternativ. Hänvisa sedan till den med argumentet using när e-post skickas, eller hämta en instans av e-postbackend från mail.mailers med konfigurationsnamnet.

    För att till exempel uppgradera denna kod:

    Code
    connection = mail.get_connection(
        "path.to.custom.EmailBackend", option1=True, option2="value"
    )
    mail.send_mail(..., connection=connection)
    connection.send_messages([email1, email2])
    

    Definiera en anpassad MAILERS-konfiguration i inställningarna:

    Code
    MAILERS = {
        "default": {...},
        "custom": {
            "BACKEND": "path.to.custom.EmailBackend",
            "OPTIONS": {
                "option1": True,
                "option2": "value",
            },
        },
    }
    

    Och använd den sedan så här:

    Code
    mail.send_mail(..., using="custom")
    mail.mailers["custom"].send_messages([email1, email2])
    

Ersätta fail_silentlyLink to this heading

De utfasade argumenten fail_silently till send_mail(), send_mass_mail(), mail_admins(), mail_managers() och EmailMessage.send() kan ersättas på flera sätt. Befintlig användning verkar ha flera olika förväntningar på beteendet, varav många inte stämmer med den faktiska implementationen (som beror på e-postbackend). Överväg att ta bort fail_silently helt om det inte finns ett särskilt behov av det.

Anrop med fail_silently=True bör uppdateras med något av dessa alternativ, beroende på anroparens avsikt:

  • För att skicka ett meddelande om e-post har konfigurerats men undvika att utlösa ett fel om den inte har det (till exempel i ett återanvändbart bibliotek) omger du sändanropet med try: / except mail.MailerDoesNotExist: pass.

  • För att ignorera alla undantag (till exempel för att undvika kedjefel i en felhanterare som skickar e-post) omger du sändanropet med try: / except Exception: pass.

  • För att ignorera enbart SMTP-relaterade fel omger du sändanropet med try / except OSError: pass. Observera att detta ignorerar både tillfälliga nätverksstörningar och SMTP-konfigurationsproblem (precis som den befintliga implementationen av SMTP-e-postbackendens fail_silently).

  • För att ignorera slutanvändares skrivfel i to-adresser och andra leveransproblem tar du bort argumentet fail_silently. Mottagarfel upptäcks i allmänhet inte vid sändningstillfället, så att använda fail_silently för detta ändamål åstadkommer inget och kan maskera andra problem, som konfigurationsfel.

    (I konfigurationer för lokal leverans kan SMTP-servrar rapportera vissa mottagarfel vid sändning. Om du använder fail_silently särskilt för att ignorera dessa fel bör du i stället överväga att fånga SMTPRecipientsRefused och/eller SMTPResponseExceptions med särskilda smtp_code-värden som ett mer precist filter.)

  • För att skapa en e-postkonfiguration som ignorerar vissa backendberoende fel och återanvända den för flera sändningar skapar du en anpassad MAILERS-konfiguration med "fail_silently": True i "OPTIONS" och hänvisar sedan till konfigurationen med using i sändanropet.

Anrop med fail_silently=False bör uppdateras genom att ta bort argumentet fail_silently, eftersom detta är standard.

If you use AdminEmailHandler or BrokenLinkEmailsMiddleware and rely on their previous fail-silent behavior, see Ignoring transient failures in error reporting.

Migrera anpassade e-postbackendarLink to this heading

Anpassade implementationer av EmailBackend kan behöva uppdateras för kompatibilitet med mailers.

  • I backendens metod __init__() ska explicita nyckelordsargument accepteras för alla konfigurationsalternativ som kan komma från "OPTIONS". Backendar som använder anpassade inställningar för konfiguration kan fortsätta att göra det (eller låta bli, enligt eget val), men nyckelordsargument bör ha företräde framför inställningar.

  • Acceptera variabla **kwargs och skicka dem till superklassens init. (Detta inkluderar ett nytt argument alias som måste skickas till superklassen.) Säkerställ att **kwargs som används av backend inte skickas till superklassens init, eftersom det skulle generera ett InvalidMailer-fel för okända OPTIONS.

  • Backendar måste nu själva hantera fail_silently om de vill stödja det. Det finns inget krav på att stödja fail_silently, och backendar som inte erbjuder det bör ta bort det nyckelordsargumentet. (Skicka inte ett explicit argument fail_silently till superklassens init.)

  • Acceptera inte variabla positionsargument *args och skicka dem inte till superklassens init.

Superklassen BaseEmailBackend initierar nu attributet alias. Det är användbart för felmeddelanden (till exempel raise InvalidMailer(f"Bad host {host}", alias=self.alias)), men bör inte användas för att komma åt settings.MAILERS direkt. Alla OPTIONS för en mailer-konfiguration skickas till backendens init som nyckelordsargument.

För återanvändbara bibliotek som vill stödja kompatibilitet med utfasade e-postfunktioner och inställningar, eller som stöder äldre Django-versioner:

  • En backend kan upptäcka att den initieras utan MAILERS genom att kontrollera om self.alias is None. (Djangos inbyggda backendar kontrollerar detta för att avgöra om utfasade inställningar ska användas.) Bibliotek som stöder äldre Django-versioner behöver använda getattr(self, "alias", None).

  • Backendar som använder Djangos SMTP-e-postinställningar, som EMAIL_HOST, får inte försöka komma åt dem när MAILERS används (self.alias is not None), eftersom detta orsakar ett AttributeError med texten ”not available when MAILERS is defined”.

  • Bibliotek som stöder flera Django-versioner kan identifiera stöd för mailers med antingen hasattr(django.core.mail, "mailers") eller django.VERSION >= (6, 1).

Ersätta auth_user och auth_passwordLink to this heading

De utfasade argumenten auth_user och auth_password till send_mail() och send_mass_mail() kan ersättas genom att definiera en anpassad MAILERS-konfiguration med "username" och "password" i "OPTIONS" och hänvisa till den konfigurationen med argumentet using när e-post skickas.

För att till exempel uppgradera:

Code
mail.send_mail(..., auth_user="admin", auth_password="admin-password")

Lägg till en anpassad MAILERS-konfiguration i inställningarna:

Code
MAILERS = {
    # Existing default configuration.
    "default": {
        "OPTIONS": {
            "host": "smtp.example.com",
            "username": "default-user",
            "password": "default-password",
        },
    },
    # Duplicate the default configuration, changing the auth.
    "admin-config": {
        "OPTIONS": {
            "host": "smtp.example.com",
            "username": "admin",
            "password": "admin-password",
        },
    },
}

Och hänvisa sedan till den vid sändning:

Code
mail.send_mail(..., using="admin-config")

Uppdatera email_backend för AdminEmailHandlerLink to this heading

Det utfasade argumentet email_backend till loggningsklassen AdminEmailHandler kan ersättas med en anpassad MAILERS-konfiguration, som hänvisas till med argumentet using.

Om inställningarna till exempel innehåller:

Code
LOGGING = {
    # ...
    "handlers": {
        "mail_admins": {
            "class": "django.utils.log.AdminEmailHandler",
            "email_backend": "third.party.EmailBackend",
        },
    },
    # ...
}

Ersätt detta med:

Code
LOGGING = {
    # ...
    "handlers": {
        "mail_admins": {
            "class": "django.utils.log.AdminEmailHandler",
            "using": "admin-logging",  # defined in MAILERS
        },
    },
    # ...
}

MAILERS = {
    "default": {...},
    "admin-logging": {
        "BACKEND": "third.party.EmailBackend",
    },
}

Ignoring transient failures in error reportingLink to this heading

Django includes two features that report errors via email: AdminEmailHandler and BrokenLinkEmailsMiddleware. In earlier releases, those features used the deprecated fail_silently argument. Starting in Django 2028 – or immediately once the MAILERS setting is defined – those features no longer use fail_silently so no longer ignore certain backend-specific errors.

This may affect projects that use those features with an unreliable SMTP connection and rely on silently ignoring temporary network failures (and certain SMTP configuration errors). If you want to continue dropping error notification emails that cannot be sent, define a MAILERS configuration with the "fail_silently" option enabled for use by those error handlers:

Code
MAILERS = {
    "default": {...},
    "admin-logging": {
        "BACKEND": "django.core.mail.backends.smtp.EmailBackend",
        "OPTIONS": {
            # ... other SMTP options ...
            "fail_silently": True,
        },
    },
}

To use this for AdminEmailHandler, set the "using" option in the LOGGING config as shown in the previous section.

To use this for BrokenLinkEmailsMiddleware, create a subclass that defines using, and then specify the path to that subclass in your MIDDLEWARE setting:

Code
from django.middleware.common import BrokenLinkEmailsMiddleware


class CustomBrokenLinkEmailsMiddleware(BrokenLinkEmailsMiddleware):
    using = "admin-logging"