I left this comment on the changeset. Leaving it here too as this is a better spot for the conversation:
I believe that this fixes the scenario you're describing. Catching the MaxRetriesException without reraising was causing it to retry indefinitely before this fix. The way task.retry() works is that it wiill raise the MaxRetriesException (or whatever e is with the exc kwarg) after the max, and the task needs to get that exception in order to stop. As far as I can tell this is the documented way of handling retries. Please correct me if I'm wrong though.
You're quite right! I was basing my claim on observations from our production servers, the logs of which have since been laid to rest. Experimenting locally, I can't reproduce the indefinite retry problem.
I am confused as to why we were seeing so many retries but happy to know it's not a problem with django-celery-email.