diff --git a/docs/usage.rst b/docs/usage.rst index 9779010..5111233 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -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 ============================= diff --git a/src/mailer/admin.py b/src/mailer/admin.py index dc30fdb..db7ed04 100644 --- a/src/mailer/admin.py +++ b/src/mailer/admin.py @@ -6,12 +6,25 @@ def show_to(message): - return ", ".join(message.to_addresses) + if message.email: + return ", ".join(message.to_addresses) + else: + return "" show_to.short_description = "To" # noqa: E305 +def show_subject(message): + if message.email: + return message.subject + else: + return "" + + +show_subject.short_description = "Subject" # noqa: E305 + + class MessageAdminMixin: def plain_text_body(self, instance): email = instance.email @@ -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"] diff --git a/src/mailer/migrations/0007_alter_messagelog_message_data.py b/src/mailer/migrations/0007_alter_messagelog_message_data.py new file mode 100644 index 0000000..489084e --- /dev/null +++ b/src/mailer/migrations/0007_alter_messagelog_message_data.py @@ -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), + ), + ] diff --git a/src/mailer/models.py b/src/mailer/models.py index 3374919..3514483 100644 --- a/src/mailer/models.py +++ b/src/mailer/models.py @@ -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, @@ -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) @@ -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 "" @@ -304,7 +310,7 @@ def to_addresses(self): if email is not None: return email.to else: - return [] + return None @property def subject(self): @@ -312,4 +318,4 @@ def subject(self): if email is not None: return email.subject else: - return "" + return None diff --git a/tests/test_mailer.py b/tests/test_mailer.py index 95e2373..d6763c6 100644 --- a/tests/test_mailer.py +++ b/tests/test_mailer.py @@ -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 @@ -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", "log1@example.com", ["1gol@example.com"]) + + 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"): @@ -664,8 +690,12 @@ def test_message_log_str(self): f'On {log.when_attempted}, "Subject Log δΈ­" to 1gol@example.com', ) + with patch.object(MessageLog, "when_attempted", new_callable=PropertyMock) as log_mock: + log_mock.side_effect = ValueError + self.assertEqual(str(log), "") + log.message_data = None - self.assertEqual(str(log), "") + self.assertEqual(str(log), f'On {log.when_attempted}, "{log.message_id}"') class DbToEmailTest(TestCase):