[Django] #36163: Change mail APIs to (mostly) keyword-only parameters

23 views
Skip to first unread message

Django

unread,
Jan 31, 2025, 4:08:21 PMJan 31
to django-...@googlegroups.com
#36163: Change mail APIs to (mostly) keyword-only parameters
-------------------------------------+-------------------------------------
Reporter: Mike Edmunds | Type:
| Cleanup/optimization
Status: new | Component: Core
| (Mail)
Version: 5.1 | Severity: Normal
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
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.

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):

}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/36163>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jan 31, 2025, 8:15:43 PMJan 31
to django-...@googlegroups.com
#36163: Change mail APIs to (mostly) keyword-only parameters
-------------------------------------+-------------------------------------
Reporter: Mike Edmunds | Owner: Chaitanya
Type: | Rahalkar
Cleanup/optimization | Status: assigned
Component: Core (Mail) | Version: 5.1
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Chaitanya Rahalkar):

* owner: (none) => Chaitanya Rahalkar
* status: new => assigned

--
Ticket URL: <https://code.djangoproject.com/ticket/36163#comment:1>

Django

unread,
Feb 1, 2025, 9:16:35 AMFeb 1
to django-...@googlegroups.com
#36163: Change mail APIs to (mostly) keyword-only parameters
-------------------------------------+-------------------------------------
Reporter: Mike Edmunds | Owner: Chaitanya
Type: | Rahalkar
Cleanup/optimization | Status: assigned
Component: Core (Mail) | Version: dev
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Claude Paroz):

* stage: Unreviewed => Accepted
* version: 5.1 => dev

Comment:

+1, I think this is good practice, helps code readability and avoid
possible ambiguity when passing positional parameters.
--
Ticket URL: <https://code.djangoproject.com/ticket/36163#comment:2>

Django

unread,
Feb 7, 2025, 2:15:21 PMFeb 7
to django-...@googlegroups.com
#36163: Change mail APIs to (mostly) keyword-only parameters
-------------------------------------+-------------------------------------
Reporter: Mike Edmunds | Owner: Chaitanya
Type: | Rahalkar
Cleanup/optimization | Status: assigned
Component: Core (Mail) | Version: dev
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Old description:
New description:

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.]
Comment (by Mike Edmunds):

Updated description to require a deprecation period based on additional
forum feedback (and per the original proposal in the forum).

Opened https://github.com/django/django/pull/19145 with an implementation
of an `@deprecate_posargs` decorator to simplify the deprecation process.
--
Ticket URL: <https://code.djangoproject.com/ticket/36163#comment:3>

Django

unread,
Feb 8, 2025, 3:40:21 PMFeb 8
to django-...@googlegroups.com
#36163: Change mail APIs to (mostly) keyword-only parameters
-------------------------------------+-------------------------------------
Reporter: Mike Edmunds | Owner: Chaitanya
Type: | Rahalkar
Cleanup/optimization | Status: assigned
Component: Core (Mail) | Version: dev
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mike Edmunds):

* has_patch: 0 => 1

Comment:

@chaitanyarahalkar are you still working on this?

I'm marking it "has patch" to get a review for the `@deprecate_posargs`
decorator, but it will still need a separate PR (including deprecation
docs) for the original issue.
--
Ticket URL: <https://code.djangoproject.com/ticket/36163#comment:4>

Django

unread,
Feb 17, 2025, 10:03:32 PMFeb 17
to django-...@googlegroups.com
#36163: Change mail APIs to (mostly) keyword-only parameters
-------------------------------------+-------------------------------------
Reporter: Mike Edmunds | Owner: Mike
Type: | Edmunds
Cleanup/optimization | Status: assigned
Component: Core (Mail) | Version: dev
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mike Edmunds):

* owner: Chaitanya Rahalkar => Mike Edmunds

--
Ticket URL: <https://code.djangoproject.com/ticket/36163#comment:5>

Django

unread,
Jul 16, 2025, 7:49:15 AMJul 16
to django-...@googlegroups.com
#36163: Change mail APIs to (mostly) keyword-only parameters
-------------------------------------+-------------------------------------
Reporter: Mike Edmunds | Owner: Mike
Type: | Edmunds
Cleanup/optimization | Status: assigned
Component: Core (Mail) | Version: dev
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by GitHub <noreply@…>):

In [changeset:"f42b89f1bf49a5b89ed852b60f79342320a81c5e" f42b89f]:
{{{#!CommitTicketReference repository=""
revision="f42b89f1bf49a5b89ed852b60f79342320a81c5e"
Fixed #36477, Refs #36163 -- Added @deprecate_posargs decorator to
simplify deprecation of positional arguments.

This helper allows marking positional-or-keyword parameters as keyword-
only with a deprecation period, in a consistent and correct manner.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/36163#comment:6>

Django

unread,
Jul 16, 2025, 5:14:29 PMJul 16
to django-...@googlegroups.com
#36163: Change mail APIs to (mostly) keyword-only parameters
-------------------------------------+-------------------------------------
Reporter: Mike Edmunds | Owner: Mike
Type: | Edmunds
Cleanup/optimization | Status: assigned
Component: Core (Mail) | Version: dev
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 1
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Natalia Bidart):

* needs_better_patch: 0 => 1

Comment:

Setting as patch needs improvement until Mike fixes conflicts and updates
PR based on latest merges.
--
Ticket URL: <https://code.djangoproject.com/ticket/36163#comment:7>

Django

unread,
Jul 16, 2025, 6:57:55 PMJul 16
to django-...@googlegroups.com
#36163: Change mail APIs to (mostly) keyword-only parameters
-------------------------------------+-------------------------------------
Reporter: Mike Edmunds | Owner: Mike
Type: | Edmunds
Cleanup/optimization | Status: assigned
Component: Core (Mail) | Version: dev
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mike Edmunds):

* needs_better_patch: 1 => 0

--
Ticket URL: <https://code.djangoproject.com/ticket/36163#comment:8>

Django

unread,
Jul 17, 2025, 11:48:20 AMJul 17
to django-...@googlegroups.com
#36163: Change mail APIs to (mostly) keyword-only parameters
-------------------------------------+-------------------------------------
Reporter: Mike Edmunds | Owner: Mike
Type: | Edmunds
Cleanup/optimization | Status: assigned
Component: Core (Mail) | Version: dev
Severity: Normal | Resolution:
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Natalia Bidart):

* stage: Accepted => Ready for checkin

--
Ticket URL: <https://code.djangoproject.com/ticket/36163#comment:9>

Django

unread,
Jul 17, 2025, 1:01:29 PMJul 17
to django-...@googlegroups.com
#36163: Change mail APIs to (mostly) keyword-only parameters
-------------------------------------+-------------------------------------
Reporter: Mike Edmunds | Owner: Mike
Type: | Edmunds
Cleanup/optimization | Status: closed
Component: Core (Mail) | Version: dev
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by nessita <124304+nessita@…>):

In [changeset:"6320915053bbd22bee2240b80df08ed4e25235f8" 6320915]:
{{{#!CommitTicketReference repository=""
revision="6320915053bbd22bee2240b80df08ed4e25235f8"
Refs #36163 -- Reordered EmailMessage options in docs/topics/email.txt.

Reordered the keyword-only EmailMessage parameters in the documentation
to group similar options together and move rarely used options later.

Used keywords for *all* parameters in EmailMessage examples to improve
clarity.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/36163#comment:11>

Django

unread,
Jul 17, 2025, 1:01:29 PMJul 17
to django-...@googlegroups.com
#36163: Change mail APIs to (mostly) keyword-only parameters
-------------------------------------+-------------------------------------
Reporter: Mike Edmunds | Owner: Mike
Type: | Edmunds
Cleanup/optimization | Status: closed
Component: Core (Mail) | Version: dev
Severity: Normal | Resolution: fixed
Keywords: | Triage Stage: Ready for
| checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by nessita <124304+nessita@…>):

* resolution: => fixed
* status: assigned => closed

Comment:

In [changeset:"fc793fc303a3d516ab51bb21aa317031caabe7b4" fc793fc3]:
{{{#!CommitTicketReference repository=""
revision="fc793fc303a3d516ab51bb21aa317031caabe7b4"
Fixed #36163 -- Deprecated most positional arguments in django.core.mail.

In public mail APIs, changed less frequently used parameters from
keyword-or-positional to keyword-only, emitting a warning during the
required deprecation period.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/36163#comment:10>
Reply all
Reply to author
Forward
0 new messages