Opened 2 hours ago
#36894 new Bug
Email fail_silently, auth_user, auth_password are ignored when connection param provided
| Reported by: | Mike Edmunds | Owned by: | |
|---|---|---|---|
| Component: | Core (Mail) | Version: | 6.0 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
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=Falsetofail_silently=Noneto 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_userandauth_password(which already default to None) - Updating tests to cover the new behavior