From 33c9c32e7e31bd672537f35850d15fe44c7bb170 Mon Sep 17 00:00:00 2001 From: Felix Boehme Date: Mon, 8 Dec 2014 14:54:03 -0800 Subject: [PATCH] Related object, mass mail utils Added generic fkey on message in order to allow associating messages with other objects Added mass mail utilities that store outgoing messages (including link to other object) --- django_mailbox/mail.py | 49 +++++++++++++ django_mailbox/models.py | 17 ++++- ..._content_type__add_field_message_relate.py | 72 +++++++++++++++++++ 3 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 django_mailbox/mail.py create mode 100644 django_mailbox/south_migrations/0017_auto__add_field_message_related_content_type__add_field_message_relate.py diff --git a/django_mailbox/mail.py b/django_mailbox/mail.py new file mode 100644 index 0000000..20c2d64 --- /dev/null +++ b/django_mailbox/mail.py @@ -0,0 +1,49 @@ +from django.core.mail import get_connection, EmailMultiAlternatives, EmailMessage + + +def record_messages(mailbox, messages, related_object=None): + """ + Used in functions below. Records sent messages in Django Mailbox. + """ + for message in messages: + mailbox.record_outgoing_message(message.message(), related_object) + + +def send_mass_mail_recorded(datatuple, mailbox, related_object=None, bcc=None, + fail_silently=False, auth_user=None, auth_password=None, connection=None): + """ + Shadows Django's send mass mail, but records each outgoing message to the + specified mailbox. + + Also added optional bcc argument. + """ + connection = connection or get_connection( + username=auth_user, password=auth_password, fail_silently=fail_silently + ) + + messages = [EmailMessage(subject, message, sender, recipient, bcc) + for subject, message, sender, recipient in datatuple] + + record_messages(mailbox, messages, related_object) + + return connection.send_messages(messages) + + +def send_mass_html_mail_recorded(datatuple, mailbox, related_object=None, bcc=None, + fail_silently=False, user=None, password=None, connection=None): + """ + Like above, but lets you send HTML emails. + """ + connection = connection or get_connection( + username=user, password=password, fail_silently=fail_silently + ) + + messages = [] + for subject, text, html, from_email, recipient in datatuple: + message = EmailMultiAlternatives(subject, text, from_email, recipient, bcc) + message.attach_alternative(html, 'text/html') + messages.append(message) + + record_messages(mailbox, messages) + + return connection.send_messages(messages) \ No newline at end of file diff --git a/django_mailbox/models.py b/django_mailbox/models.py index 981883d..5e5fe64 100644 --- a/django_mailbox/models.py +++ b/django_mailbox/models.py @@ -16,6 +16,8 @@ import mimetypes import os.path import sys import uuid +from django.contrib.contenttypes import generic +from django.contrib.contenttypes.models import ContentType import six from six.moves.urllib.parse import parse_qs, unquote, urlparse @@ -233,9 +235,11 @@ class Mailbox(models.Model): return msg - def record_outgoing_message(self, message): + def record_outgoing_message(self, message, related_object=None): msg = self._process_message(message) msg.outgoing = True + if related_object: + msg.related_object = related_object msg.save() return msg @@ -413,6 +417,17 @@ class Message(models.Model): verbose_name=_(u'In reply to'), ) + related_content_type = models.ForeignKey( + ContentType, + blank=True, + null=True + ) + related_object_id = models.PositiveIntegerField( + blank=True, + null=True + ) + related_object = generic.GenericForeignKey('related_content_type', 'related_object_id') + from_header = models.CharField( _('From header'), max_length=255, diff --git a/django_mailbox/south_migrations/0017_auto__add_field_message_related_content_type__add_field_message_relate.py b/django_mailbox/south_migrations/0017_auto__add_field_message_related_content_type__add_field_message_relate.py new file mode 100644 index 0000000..3a99751 --- /dev/null +++ b/django_mailbox/south_migrations/0017_auto__add_field_message_related_content_type__add_field_message_relate.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'Message.related_content_type' + db.add_column('django_mailbox_message', 'related_content_type', + self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'], null=True, blank=True), + keep_default=False) + + # Adding field 'Message.related_object_id' + db.add_column('django_mailbox_message', 'related_object_id', + self.gf('django.db.models.fields.PositiveIntegerField')(null=True, blank=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Message.related_content_type' + db.delete_column('django_mailbox_message', 'related_content_type_id') + + # Deleting field 'Message.related_object_id' + db.delete_column('django_mailbox_message', 'related_object_id') + + + models = { + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'django_mailbox.mailbox': { + 'Meta': {'object_name': 'Mailbox'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'from_email': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'uri': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}) + }, + 'django_mailbox.message': { + 'Meta': {'object_name': 'Message'}, + 'body': ('django.db.models.fields.TextField', [], {}), + 'encoded': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'from_header': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'in_reply_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'replies'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}), + 'mailbox': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'messages'", 'to': "orm['django_mailbox.Mailbox']"}), + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'outgoing': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'processed': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'read': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}), + 'related_content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}), + 'related_object_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}), + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'to_header': ('django.db.models.fields.TextField', [], {}) + }, + 'django_mailbox.messageattachment': { + 'Meta': {'object_name': 'MessageAttachment'}, + 'document': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), + 'headers': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attachments'", 'null': 'True', 'to': "orm['django_mailbox.Message']"}) + } + } + + complete_apps = ['django_mailbox'] \ No newline at end of file