Skip to content

Support Serializing Emails With Alternatives In Django 5.2 #44

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions mail_panel/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@


class MailToolbarBackendEmail(mail.EmailMultiAlternatives):
def __init__(self, message):
try:
self.id = uuid4().get_hex()
except AttributeError:
self.id = uuid4().hex # python 3
def __init__(self, message, id=None):
if id:
self.id = id
else:
try:
self.id = uuid4().get_hex()
except AttributeError:
self.id = uuid4().hex # python 3
self.date_sent = now()
self.read = False
message.message() # triggers header validation
Expand Down
54 changes: 52 additions & 2 deletions mail_panel/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.core.cache import caches
from django.core.mail import EmailMultiAlternatives

try:
CACHE_SETTINGS = caches.settings
Expand All @@ -20,18 +21,67 @@
cache = caches.create_connection("mail_panel")


def serialize_email(email):
"""
Serialize email to a dictionary (prior to caching).
"""
return {
"subject": email.subject,
"body": email.body,
"from_email": email.from_email,
"to": email.to,
"cc": email.cc,
"bcc": email.bcc,
"headers": email.extra_headers,
"alternatives": email.alternatives,
}


def deserialize_email(message_id, data):
"""
Deserialize a dictionary representing an email (after getting it from the cache).
"""
from .backend import MailToolbarBackendEmail

django_email = EmailMultiAlternatives(
subject=data["subject"],
body=data["body"],
from_email=data["from_email"],
to=data["to"],
cc=data.get("cc", []),
bcc=data.get("bcc", []),
headers=data.get("headers", {}),
)
email = MailToolbarBackendEmail(django_email, id=message_id)
for alt in data.get("alternatives", []):
email.attach_alternative(alt[0], alt[1])
return email


def load_outbox():
"""
Returns a dictionary of cached mail.
"""
return cache.get(MAIL_TOOLBAR_CACHE_KEY, {})
# Since the emails in the cache are serialized, we first deserialize them.
outbox_obj_of_serialized_emails = cache.get(MAIL_TOOLBAR_CACHE_KEY, {})
outbox = {}
for email_id, serialized_email in outbox_obj_of_serialized_emails.items():
email = deserialize_email(email_id, serialized_email)
outbox[email_id] = email
return outbox


def save_outbox(outbox):
"""
Saves the dictionary of cached mail and sets expiry.
"""
cache.set(MAIL_TOOLBAR_CACHE_KEY, outbox, MAIL_TOOLBAR_TTL)
outbox_obj = {}
# Since some emails contain data types that can not be serialized, we first
# serialize emails to a serializable object.
for email_id, email in outbox.items():
outbox_obj[email_id] = serialize_email(email)

cache.set(MAIL_TOOLBAR_CACHE_KEY, outbox_obj, MAIL_TOOLBAR_TTL)


def clear_outbox():
Expand Down