﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
36163	Change mail APIs to (mostly) keyword-only parameters	Mike Edmunds	Mike Edmunds	"Several of Django's email APIs have extremely long parameter lists. This complicates adding—and documenting—new parameters where they would logically fit, as the existing positional order must be maintained for compatibility.

This ticket proposes changing the public django.core.mail APIs to require keyword-only arguments, starting at the first boolean or ""uncommon"" parameter. That's `fail_silently` for the functional APIs, and `bcc` for the class constructors (specifics below).

Forum discussion: https://forum.djangoproject.com/t/change-send-mail-and-emailmessage-to-kwargs-only/38239

~~Consensus in the forum was that this change should be made '''without a deprecation period.''' Existing code that uses positional arguments for the affected params would raise a TypeError after the change.~~ __During a standard deprecation period, the affected parameters would be accepted as either positional or keyword arguments, but using posargs would raise a deprecation warning. After the deprecation period, continuing to use posargs for those params would result in Python's usual TypeError.__ [Edit: further forum discussion clarified need to follow the deprecation process.]

A quick (and by no means exhaustive) GitHub code search suggests a lot of existing code already uses keyword arguments for these params, but that positional arguments are common for the earlier ones. One potential exception is custom EmailMultiAlternatives subclasses. (More details in the forum.)

(This originally came up in the context of #35514, which must add a new `provider` parameter to several existing APIs—including the ""[https://github.com/django/django/blob/8eca4077f60fa0705ecfd9437c9ceaeef7a3808b/django/core/mail/__init__.py#L78-L79 frozen]"" send_mail() and send_mass_mail() functions, and the EmailMessage class with its [https://docs.djangoproject.com/en/5.1/topics/email/#emailmessage-objects:~:text=in%20the%20given%20order%2C%20if%20positional%20arguments%20are%20used documented parameter ordering].)

=== Proposed changes ===

This change would add `*,`s where indicated below. All parameters after the `*,` would become keyword only.

{{{#!python
# django/core/mail/__init__.py
def get_connection(
    backend=None, 
    *, 
    fail_silently=False, **kwds):

def send_mail(
    subject, message, from_email, recipient_list,
    *,
    fail_silently=False, auth_user=None, auth_password=None,
    connection=None, html_message=None):

def send_mass_mail(
    datatuple, 
    *,
    fail_silently=False, auth_user=None, auth_password=None,
    connection=None):

def mail_admins(
    subject, message, 
    *,
    fail_silently=False, connection=None, html_message=None):

def mail_managers(
    subject, message,
    *,
    fail_silently=False, connection=None, html_message=None):
}}}

{{{#!python
# django/core/mail/message.py
class EmailMessage:
    def __init__(
        self,
        subject="""", body="""", from_email=None, to=None,
        *,
        bcc=None, connection=None,
        attachments=None, headers=None,
        cc=None, reply_to=None):


class EmailMultiAlternatives(EmailMessage):
    def __init__(
        self,
        subject="""", body="""", from_email=None, to=None,
        *,
        bcc=None, connection=None,
        attachments=None, headers=None,
        alternatives=None,
        cc=None, reply_to=None):

}}}
"	Cleanup/optimization	closed	Core (Mail)	dev	Normal	fixed			Ready for checkin	1	0	0	0	0	0
