Skip to content

Commit

Permalink
Merge pull request #176 from eht16/support_message_log_without_data
Browse files Browse the repository at this point in the history
Support message log without message data
  • Loading branch information
spookylukey authored Apr 30, 2024
2 parents 03538ff + 7991223 commit 4520089
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 11 deletions.
7 changes: 7 additions & 0 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,13 @@ that the message will be retried indefinitely. If you set this to a value of ``0
the message will not be retried at all, any number greater than ``0`` will be the
maximum number of retries (excluding the initial attempt).

To not log the email contents after sending it, you can set ``MAILER_EMAIL_LOG_MESSAGE_DATA``
to `False`. The default is ``True``, which means that the message will be stored with the full
email content. If you set this to the value ``False``, only the message meta data and result
status will be stored in the ``MessageLog`` table.
Disabling storing the email content can be useful for privacy or performance reasons,
it also helps to not increase the database size.

Using the DontSendEntry table
=============================

Expand Down
17 changes: 15 additions & 2 deletions src/mailer/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,25 @@


def show_to(message):
return ", ".join(message.to_addresses)
if message.email:
return ", ".join(message.to_addresses)
else:
return "<Message data unavailable>"


show_to.short_description = "To" # noqa: E305


def show_subject(message):
if message.email:
return message.subject
else:
return "<Message data unavailable>"


show_subject.short_description = "Subject" # noqa: E305


class MessageAdminMixin:
def plain_text_body(self, instance):
email = instance.email
Expand Down Expand Up @@ -40,7 +53,7 @@ class DontSendEntryAdmin(admin.ModelAdmin):

class MessageLogAdmin(MessageAdminMixin, admin.ModelAdmin):

list_display = ["id", show_to, "subject", "message_id", "when_attempted", "result"]
list_display = ["id", show_to, show_subject, "message_id", "when_attempted", "result"]
list_filter = ["result"]
date_hierarchy = "when_attempted"
readonly_fields = ["plain_text_body", "message_id"]
Expand Down
18 changes: 18 additions & 0 deletions src/mailer/migrations/0007_alter_messagelog_message_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.0.4 on 2024-04-13 09:37

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("mailer", "0006_message_retry_count"),
]

operations = [
migrations.AlterField(
model_name="messagelog",
name="message_data",
field=models.TextField(null=True),
),
]
16 changes: 11 additions & 5 deletions src/mailer/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,11 @@ def log(self, message, result_code, log_message=""):
create a log entry for an attempt to send the given message and
record the given result and (optionally) a log message
"""
log_message_data = getattr(settings, "MAILER_EMAIL_LOG_MESSAGE_DATA", True)
message_data = message.message_data if log_message_data else None

return self.create(
message_data=message.message_data,
message_data=message_data,
message_id=get_message_id(message.email),
when_added=message.when_added,
priority=message.priority,
Expand All @@ -271,7 +274,7 @@ class MessageLog(BigAutoModel):
"""

# fields from Message
message_data = models.TextField()
message_data = models.TextField(null=True)
message_id = models.TextField(editable=False, null=True)
when_added = models.DateTimeField(db_index=True)
priority = models.PositiveSmallIntegerField(choices=PRIORITIES, db_index=True)
Expand All @@ -290,7 +293,10 @@ class Meta:
def __str__(self):
try:
email = self.email
return f"On {self.when_attempted}, \"{email.subject}\" to {', '.join(email.to)}"
if email:
return f"On {self.when_attempted}, \"{email.subject}\" to {', '.join(email.to)}"
else:
return f'On {self.when_attempted}, "{self.message_id}"'
except Exception:
return "<MessageLog repr unavailable>"

Expand All @@ -304,12 +310,12 @@ def to_addresses(self):
if email is not None:
return email.to
else:
return []
return None

@property
def subject(self):
email = self.email
if email is not None:
return email.subject
else:
return ""
return None
38 changes: 34 additions & 4 deletions tests/test_mailer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import datetime
import pickle
import time
from unittest.mock import Mock, patch
from unittest.mock import Mock, PropertyMock, patch

import django
import lockfile
Expand Down Expand Up @@ -634,8 +634,34 @@ def test_message_log(self):
# Fake a log entry without email
log.message_data = ""

self.assertEqual(log.to_addresses, [])
self.assertEqual(log.subject, "")
self.assertEqual(log.to_addresses, None)
self.assertEqual(log.subject, None)

def test_message_log_without_log_message_data(self):
with self.settings(
MAILER_EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend",
MAILER_EMAIL_LOG_MESSAGE_DATA=False,
): # noqa
mailer.send_mail("Subject Log", "Body", "[email protected]", ["[email protected]"])

self.assertEqual(Message.objects.count(), 1)
self.assertEqual(Message.objects.deferred().count(), 0)
self.assertEqual(MessageLog.objects.count(), 0)
when_added = Message.objects.first().when_added

engine.send_all()

self.assertEqual(Message.objects.count(), 0)
self.assertEqual(Message.objects.deferred().count(), 0)
self.assertEqual(MessageLog.objects.count(), 1)

log = MessageLog.objects.all()[0]

self.assertEqual(log.email, None)
self.assertEqual(log.message_data, None)
self.assertEqual(log.to_addresses, None)
self.assertEqual(log.subject, None)
self.assertEqual(log.when_added, when_added)

def test_message_str(self):
with self.settings(MAILER_EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend"):
Expand Down Expand Up @@ -664,8 +690,12 @@ def test_message_log_str(self):
f'On {log.when_attempted}, "Subject Log 中" to [email protected]',
)

with patch.object(MessageLog, "when_attempted", new_callable=PropertyMock) as log_mock:
log_mock.side_effect = ValueError
self.assertEqual(str(log), "<MessageLog repr unavailable>")

log.message_data = None
self.assertEqual(str(log), "<MessageLog repr unavailable>")
self.assertEqual(str(log), f'On {log.when_attempted}, "{log.message_id}"')


class DbToEmailTest(TestCase):
Expand Down

0 comments on commit 4520089

Please sign in to comment.