How can I log all outgoing email in Django?
I wrote a custom email backend which logs the stuff to a model.
Here's my backend:
from django.core.mail.backends.smtp import *from django.db import transactionfrom modules.common.models import *class LoggingEmailBackend(EmailBackend): """ A wrapper around the SMTP backend that logs all emails to the DB. """ def send_messages(self, email_messages): """ A helper method that does the actual logging """ with transaction.commit_on_success(): for email_message in email_messages: email_record = Email.objects.create( to='; '.join(email_message.recipients()), subject=email_message.subject, body=email_message.body, ) try: return super(LoggingEmailBackend, self)._send( email_message ) except: email_record.ok = False return False finally: email_record.ok = True return True
Here's the model:
class Email(models.Model): """ Model to store all the outgoing emails. """ when = models.DateTimeField( null=False, auto_now_add=True ) to = models.EmailField( null=False, blank=False, ) subject = models.CharField( null=False, max_length=128, ) body = models.TextField( null=False, max_length=1024, ) ok = models.BooleanField( null=False, default=True, )
Here's my model:
from django.contrib import adminfrom modules.common.models import *class EmailAdmin(admin.ModelAdmin): """ Admin part for managing the the Email model """ list_display = ['to', 'subject', 'ok',] list_filter = ['ok'] readonly_fields = ['when', 'to', 'subject', 'body', 'ok'] search_fields = ['subject', 'body', 'to'] def has_delete_permission(self, request, obj=None): return False def has_add_permission(self, request): return Falseadmin.site.register(Email, EmailAdmin)
Since the OP asked about logging and not about saving to DB, here's a middleware that does that:
import django.core.mail.backends.smtpimport logginglogger = logging.getLogger(__name__) # or you could enter a specific logger nameclass LoggingBackend(django.core.mail.backends.smtp.EmailBackend): def send_messages(self, email_messages): try: for msg in email_messages: logger.info(u"Sending message '%s' to recipients: %s", msg.subject, msg.to) except: logger.exception("Problem logging recipients, ignoring") return super(LoggingBackend, self).send_messages(email_messages)
and then in your settings.py:
EMAIL_BACKEND = 'whereiputit.LoggingBackend'
I do not know if there exists a module that works this way, but writing a custom one is a piece of cake. Just create a separate model and every time you send an email, create a new instance ( use a custom method for email sending ). Then, link this model with the admin and bingo..