diff --git a/mail_panel/backend.py b/mail_panel/backend.py index e9dbde4..901b4b2 100644 --- a/mail_panel/backend.py +++ b/mail_panel/backend.py @@ -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 diff --git a/mail_panel/utils.py b/mail_panel/utils.py index d944a9c..259e957 100644 --- a/mail_panel/utils.py +++ b/mail_panel/utils.py @@ -1,4 +1,5 @@ from django.core.cache import caches +from django.core.mail import EmailMultiAlternatives try: CACHE_SETTINGS = caches.settings @@ -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():