Deprecating or changing how django.core.mail handles fail_silently

I’m not sure that the parallel with contrib.messages holds, for two reasons:

  1. IMHO the concerns are different: messages.fail_silently guards against the messages middleware not being installed/available, which could be seen as a deployment/configuration condition. Email’s fail_silently suppresses runtime errors (SMTP down, connection refused, etc) and these are not the same kind of problem, so I’m thinking that the API analogy doesn’t transfer cleanly.

  2. Perhaps more fundamentally, I think fail_silently was designed for a single-backend world, where “degrade gracefully if mesages/email isn’t set up” made sense. But Django is moving away from that pattern into using a dictionary of named backends configs (DATABASES, CACHES, STORAGES, TASKS, and soon email with EMAIL_PROVIDERS). In this format, each backend is intentionally configured; its absence is a hard error. The ambiguity that fail_silently was presumably designed to handle over no longer exists.

Given this, I’m inclined to vote for option 2 (deprecate entirely) as my first choice, but if that one is considered too aggressive, I’d go with option 3 as a compromise.

IMHO the classical use case for keeping fail_silently is mail_admins() in an error handler, but I think that is better served by an explicit try/except at the call site, where the caller actually knows the context and intent. At this point, fail_silently=True is just a bundled try/except with worse readability and hidden behavior.

2 Likes