Simplifying ADMINS and MANAGERS settings?

I’d like to change the ADMINS and MANAGERS settings to take lists of plain email addresses, rather than tuples of (name, email). I opened ticket #36138, where @sarahboyce requested forum feedback first.

Background

The ADMINS and MANAGERS settings are documented to take lists of (Full name, email address) tuples:

ADMINS = [("John", "john@example.com"), ("Mary", "mary@example.com")]

While investigating some other mail-related code, I noticed they don’t actually work as documented—and maybe never have.
The name part is discarded in mail_admins() and mail_managers(). (And it’s been like that at least as long as Django has been public.)

Users might reasonably expect these settings would take lists of email address strings. Ticket #30604 added an error message to prevent this likely mistake:

# Doesn't currently work:
ADMINS = ["john@example.com", "mary@example.com"]

Possible solutions

It’s a bug that these settings don’t work as documented. Here are some potential solutions. I’ll say up front that I don’t think the first two are good options, but I’m including them for completeness.

  1. Make the code match the docs: Use something like Python’s formataddr() to build an RFC 5822 ‘name-addr’ string from the tuple. (I’d guess some early Django code did exactly this, resulting in the format for these settings.)

    Unfortunately, just calling formataddr() would be a breaking change: it doesn’t handle non-ASCII domains and has some other limitations. The full fix would involve supporting (name, email) pairs in recipient lists all the way down through Django’s email APIs, which gets more complicated.[1]

  2. Make the docs match the code: This is probably the easiest solution, but doesn’t feel great. Something like:

    Each item in the list should be a tuple of (Full name unused, email address). The first item in each tuple is not used, but must be present for historical reasons. Example:

    [("", "john@example.com"), ("", "mary@example.com")]
    
  3. Change to lists of string addresses; deprecate tuples: Update the code and documentation to expect lists of strings. Something like:

    Each item in the list should be an email address str. To include a full name, use the "Name" <email> format. Example:

    [
        "john@example.com",
        '"Ng, Mary" <mary@example.com>',
    ]
    

    This is the same format used for lists of addresses elsewhere in Django: send_mail() recipient_list and EmailMessage to/cc/bcc params.

    Existing settings with lists of (name, email) tuples would go through the usual deprecation process. This would require changes for everyone using these settings, but as @sarahboyce pointed out in #36138, that could be automated in django-update.

  4. Same as (3), but without deprecating tuples: Change the documentation and code as above, but also continue to support lists of (name, email) tuples, without deprecation warnings.

    This avoids the need to change existing settings. But it means Django has to maintain code and tests to cover both cases, indefinitely. (This was my original proposal in #36138.)

Opinions?


  1. There is some support for (name, addr) pairs in django.core.mail’s internal sanitize_address() helper. But as far as I can tell, using (name, addr) pairs has never been documented or tested in the public email APIs. ↩︎

1 Like

Option 3 seems best here. There’s a bit of disruption with the deprecation cycle, but we have those for a reason and this ensures the best long term result.

2 Likes

Option 3 seems good to me. If done, django-upgrade could quite easily gain a fixer for the change.

2 Likes