Opened 3 weeks ago

Last modified 7 days ago

#36894 assigned Cleanup/optimization

Email fail_silently, auth_user, auth_password are ignored when connection param provided

Reported by: Mike Edmunds Owned by: Praful Gulani
Component: Core (Mail) Version: 6.0
Severity: Normal Keywords: email fail_silently
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description (last modified by Mike Edmunds)

Most django.core.mail APIs take a fail_silently parameter which is intended to suppress errors during sending, as well as a connection parameter to provide a specific EmailBackend instance for sending. When connection is specified, fail_silently is ignored.

To reproduce, configure your email settings to cause an error (e.g., EMAIL_HOST="not.a.real.host") and:

from django.core.mail import get_connection, send_mail

send_mail("subject", "body", None, ["to@example.com"])
# Correct behavior: raises socket.gaierror: [Errno 8] nodename nor servname provided, or not known

send_mail("subject", "body", None, ["to@example.com"], fail_silently=True)
# Correct behavior: returns 0 messages sent, doesn't raise an error

send_mail("subject", "body", None, ["to@example.com"], fail_silently=True, connection=get_connection())
# Bug: despite fail_silently=True, raises socket.gaierror

A similar problem exists with the auth_user and auth_password params to send_mail() and send_mass_mail(), which are also silently ignored when a connection is provided.

There is no safe way to set any of these options on a connection (EmailBackend instance) once it has been constructed. The correct way to achieve the desired behavior is move fail_silently and the other params into get_connection():

send_mail("subject", "body", None, ["to@example.com"],
    connection=get_connection(fail_silently=True, username="auth_user", password="auth_password"))

Suggested fix

Django's email APIs should handle fail_silently, auth_user and auth_password params as an error when connection is also provided. This will involve:

  • Changing the default from fail_silently=False to fail_silently=None to be able to distinguish the cases. (Don't forget EmailMessage.send().)
  • Raising a TypeError when connection is not None and fail_silently is not None. Something like "fail_silently cannot be used with a connection. (Pass fail_silently to get_connection() instead.)"
  • Converting fail_silently==None to False where the high level APIs call get_connection()
  • Issuing similar error messages for auth_user and auth_password (which already default to None)
  • Updating tests to cover the new behavior
  • Updating docs to note the changed behavior (params that had been silently ignored with connection will now raise an error)

Change History (13)

comment:1 by Kundan Yadav, 3 weeks ago

Owner: set to Kundan Yadav
Status: newassigned

comment:2 by Natalia Bidart, 3 weeks ago

Keywords: email fail_silently added
Triage Stage: UnreviewedAccepted
Type: BugCleanup/optimization

Thank you Mike for this ticket! I agree with your rationale, but personally I see this as a cleanup rather than a bug. I believe the was a lacking of being explicit in the docs that if a connection is given, the other connection-related params are ignored.

I would also include in your "Suggested fix" list to improve the docs.

comment:3 by Mike Edmunds, 3 weeks ago

Description: modified (diff)
Easy pickings: set

(Edited "suggested fix" to include adding versionchanged notes in relevant docs.)

comment:4 by Kundan Yadav, 3 weeks ago

Owner: Kundan Yadav removed
Status: assignednew

comment:5 by Kundan Yadav, 3 weeks ago

Owner: set to Kundan Yadav
Status: newassigned

comment:6 by Mike Edmunds, 2 weeks ago

Note that django.utils.log.AdminEmailHandler provides fail_silently=True to both get_connection() and mail_admins(). The latter is redundant and will result in an error once this change is implemented (so will need to be removed).

comment:7 by Praful Gulani, 13 days ago

Owner: changed from Kundan Yadav to Praful Gulani

comment:8 by Praful Gulani, 10 days ago

Has patch: set

comment:9 by Mike Edmunds, 10 days ago

Patch needs improvement: set

comment:10 by Praful Gulani, 9 days ago

Patch needs improvement: unset

comment:11 by Mike Edmunds, 8 days ago

Patch needs improvement: set

comment:12 by Praful Gulani, 8 days ago

Patch needs improvement: unset

comment:13 by Mike Edmunds, 7 days ago

Triage Stage: AcceptedReady for checkin
Note: See TracTickets for help on using tickets.
Back to Top