In the changelog under Django 5.2 release notes | Django documentation | Django it says the following:
- Tuple items of EmailMessage.attachments and EmailMultiAlternatives.attachments are now named tuples, as opposed to regular tuples.
- EmailMultiAlternatives.alternatives is now a list of named tuples, as opposed to regular tuples.
This is mentioned in the section “Minor features”, but it’s actually a breaking change, as emails can now no longer be pickled. This breaks GitHub - pinax/django-mailer: mail queuing and management for the Django web framework, which pickles the email to store it in the database, queued to be sent later, and probably other similar packages as well.
I am wondering what the benefit of moving from a regular tuple to a named tuple was, if this should maybe be undone, or how it can be done in a way that still allows the pickling of emails. I don’t see an easy way for django-mailer to support Django 5.2. It basically has to create its own internal representation of EmailMessage
and EmailMultiAlternatives
, pickle that instead, while still also supporting already-stored emails that were pickled with Django 5.1 and earlier. Is this breaking change to third party packages really worth the change to named tuples?
Example code that works fine in Django 5.1:
import base64
import pickle
from django.core.mail import EmailMultiAlternatives
base64_encode = base64.encodebytes if hasattr(base64, "encodebytes") else base64.encodestring
email = EmailMultiAlternatives(
subject="Test",
body="Test",
to=["john@example.com"],
)
email.attach("test.txt", "Hello", "plain/text")
print(email.attachments)
db_value = base64_encode(pickle.dumps(email)).decode("ascii")
print(db_value)
(This uses the pickle logic from django-mailer.)
In Django 5.2 the pickling fails:
db_value = base64_encode(pickle.dumps(email)).decode("ascii")
~~~~~~~~~~~~^^^^^^^
_pickle.PicklingError: Can't pickle <class 'django.core.mail.message.Attachment'>: attribute lookup Attachment on django.core.mail.message failed
Pickle can’t load django.core.mail.message.Attachment
because that doesn’t exist. This is the definition:
EmailAttachment = namedtuple("Attachment", ["filename", "content", "mimetype"])
Hello @kevinrenskers! This has been reported in #36309 (EmailAlternative is not serializable) – Django and will be fixed soon and released, if all goes well, in two weeks in 5.2.1.
That’s great news! I am a bit surprised that it takes multiple weeks to release 5.2.1 when it already contains multiple fixes for regressions in 5.2.0 (seems best to release those fixes asap and then follow up with 5.2.2?) but still, good news that it’s coming 
I’m sure you meant well, but please note that Django is maintained by volunteers and 1.5 paid Fellows who juggle a significant workload and must prioritize across many tasks. The project also follows a well-defined and consistent release schedule: in particular, patch releases are issued monthly, typically within the first 10 days of the month. Comments that overlook this context are not constructive and do not help support the community maintaining Django.
4 Likes
I did indeed mean well, but I see what you mean. Sorry!
1 Like