From e3cd913fe7e69d1a97f027098006044a2ed6b661 Mon Sep 17 00:00:00 2001 From: Patrick Craston Date: Tue, 15 Jan 2013 12:05:04 +0000 Subject: [PATCH 1/7] Add attachment handling --- django_mailbox/models.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/django_mailbox/models.py b/django_mailbox/models.py index 6c54192..5f0edaa 100755 --- a/django_mailbox/models.py +++ b/django_mailbox/models.py @@ -3,9 +3,12 @@ from email.utils import formatdate import rfc822 import urllib import urlparse +import os from django.conf import settings from django.core.mail.message import make_msgid +from django.core.files import File +from django.core.files.temp import NamedTemporaryFile from django.db import models from django_mailbox.transports import Pop3Transport, ImapTransport,\ MaildirTransport, MboxTransport, BabylTransport, MHTransport, \ @@ -160,6 +163,23 @@ class Mailbox(models.Model): except IndexError: pass msg.save() + if message.is_multipart(): + for part in message.walk(): + if part.get_content_maintype() == 'multipart': + continue + if part.get('Content-Disposition') is None: + continue + filename = part.get_filename() + data = part.get_payload(decode=True) + if not data: + continue + temp_file = NamedTemporaryFile(delete=True) + temp_file.write(data) + temp_file.flush() + attachment = MessageAttachment() + attachment.document.save(filename, File(temp_file)) + attachment.save() + msg.attachments.add(attachment) return msg def get_new_mail(self): @@ -226,6 +246,8 @@ class Message(models.Model): null=True, ) + attachments = models.ManyToManyField(MessageAttachment) + objects = models.Manager() unread_messages = UnreadMessageManager() incoming_messages = IncomingMessageManager() @@ -290,3 +312,6 @@ class Message(models.Model): def __unicode__(self): return self.subject + +class MessageAttachment(models.Model): + document = models.FileField(upload_to='mailbox_attachments/%Y/%m/%d/') \ No newline at end of file From 645a723d09424b4a7ba547de2ff1b6f0d71d55ff Mon Sep 17 00:00:00 2001 From: Patrick Craston Date: Tue, 15 Jan 2013 12:11:08 +0000 Subject: [PATCH 2/7] Move Attachment model up --- django_mailbox/models.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/django_mailbox/models.py b/django_mailbox/models.py index 5f0edaa..0e336dd 100755 --- a/django_mailbox/models.py +++ b/django_mailbox/models.py @@ -216,6 +216,9 @@ class UnreadMessageManager(models.Manager): read=None ) +class MessageAttachment(models.Model): + document = models.FileField(upload_to='mailbox_attachments/%Y/%m/%d/') + class Message(models.Model): mailbox = models.ForeignKey(Mailbox, related_name='messages') subject = models.CharField(max_length=255) @@ -311,7 +314,4 @@ class Message(models.Model): return email.message_from_string(self.body) def __unicode__(self): - return self.subject - -class MessageAttachment(models.Model): - document = models.FileField(upload_to='mailbox_attachments/%Y/%m/%d/') \ No newline at end of file + return self.subject \ No newline at end of file From 00c14e981807668b09a5d6a2e71fe8872291acad Mon Sep 17 00:00:00 2001 From: Patrick Craston Date: Tue, 15 Jan 2013 12:21:49 +0000 Subject: [PATCH 3/7] Add admin support for attachments --- django_mailbox/admin.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/django_mailbox/admin.py b/django_mailbox/admin.py index 39e0b02..ad9200a 100644 --- a/django_mailbox/admin.py +++ b/django_mailbox/admin.py @@ -1,7 +1,7 @@ from django.conf import settings from django.contrib import admin -from django_mailbox.models import Message, Mailbox +from django_mailbox.models import MessageAttachment, Message, Mailbox def get_new_mail(mailbox_admin, request, queryset): for mailbox in queryset.all(): @@ -17,6 +17,9 @@ class MailboxAdmin(admin.ModelAdmin): ) actions = [get_new_mail] +class MessageAttachmentAdmin(admin.ModelAdmin): + pass + class MessageAdmin(admin.ModelAdmin): list_display = ( 'subject', @@ -35,4 +38,5 @@ class MessageAdmin(admin.ModelAdmin): if getattr(settings, 'DJANGO_MAILBOX_ADMIN_ENABLED', True): admin.site.register(Message, MessageAdmin) + admin.site.register(MessageAttachmentAdmin, MessageAttachment) admin.site.register(Mailbox, MailboxAdmin) From 3c3e0f3d9b212f534efc7ba43d47441da0b57147 Mon Sep 17 00:00:00 2001 From: Patrick Craston Date: Tue, 15 Jan 2013 12:23:16 +0000 Subject: [PATCH 4/7] Add admin support for attachments --fix typo --- django_mailbox/admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django_mailbox/admin.py b/django_mailbox/admin.py index ad9200a..ae0ccef 100644 --- a/django_mailbox/admin.py +++ b/django_mailbox/admin.py @@ -38,5 +38,5 @@ class MessageAdmin(admin.ModelAdmin): if getattr(settings, 'DJANGO_MAILBOX_ADMIN_ENABLED', True): admin.site.register(Message, MessageAdmin) - admin.site.register(MessageAttachmentAdmin, MessageAttachment) + admin.site.register(MessageAttachment, MessageAttachmentAdmin) admin.site.register(Mailbox, MailboxAdmin) From 2e484aaed8c57066edce5a03b047514b232fa5bd Mon Sep 17 00:00:00 2001 From: Patrick Craston Date: Tue, 15 Jan 2013 12:27:32 +0000 Subject: [PATCH 5/7] Add admin support for attachments --display correctly --- django_mailbox/admin.py | 2 +- django_mailbox/models.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/django_mailbox/admin.py b/django_mailbox/admin.py index ae0ccef..f0b0b89 100644 --- a/django_mailbox/admin.py +++ b/django_mailbox/admin.py @@ -18,7 +18,7 @@ class MailboxAdmin(admin.ModelAdmin): actions = [get_new_mail] class MessageAttachmentAdmin(admin.ModelAdmin): - pass + list_display = ('document',) class MessageAdmin(admin.ModelAdmin): list_display = ( diff --git a/django_mailbox/models.py b/django_mailbox/models.py index 0e336dd..098ff36 100755 --- a/django_mailbox/models.py +++ b/django_mailbox/models.py @@ -219,6 +219,9 @@ class UnreadMessageManager(models.Manager): class MessageAttachment(models.Model): document = models.FileField(upload_to='mailbox_attachments/%Y/%m/%d/') + def __unicode__(self): + return self.document.url + class Message(models.Model): mailbox = models.ForeignKey(Mailbox, related_name='messages') subject = models.CharField(max_length=255) From 2fd9664295e3e075e6af4500a191c39224b7fe6b Mon Sep 17 00:00:00 2001 From: Patrick Craston Date: Tue, 15 Jan 2013 12:28:32 +0000 Subject: [PATCH 6/7] Add south migration for message attachment model --- .../0012_auto__add_messageattachment.py | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 django_mailbox/migrations/0012_auto__add_messageattachment.py diff --git a/django_mailbox/migrations/0012_auto__add_messageattachment.py b/django_mailbox/migrations/0012_auto__add_messageattachment.py new file mode 100644 index 0000000..554483e --- /dev/null +++ b/django_mailbox/migrations/0012_auto__add_messageattachment.py @@ -0,0 +1,67 @@ +# encoding: 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 model 'MessageAttachment' + db.create_table('django_mailbox_messageattachment', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('document', self.gf('django.db.models.fields.files.FileField')(max_length=100)), + )) + db.send_create_signal('django_mailbox', ['MessageAttachment']) + + # Adding M2M table for field attachments on 'Message' + db.create_table('django_mailbox_message_attachments', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('message', models.ForeignKey(orm['django_mailbox.message'], null=False)), + ('messageattachment', models.ForeignKey(orm['django_mailbox.messageattachment'], null=False)) + )) + db.create_unique('django_mailbox_message_attachments', ['message_id', 'messageattachment_id']) + + + def backwards(self, orm): + + # Deleting model 'MessageAttachment' + db.delete_table('django_mailbox_messageattachment') + + # Removing M2M table for field attachments on 'Message' + db.delete_table('django_mailbox_message_attachments') + + + models = { + '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'}, + 'attachments': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['django_mailbox.MessageAttachment']", 'symmetrical': 'False'}), + 'body': ('django.db.models.fields.TextField', [], {}), + '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'}), + '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'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['django_mailbox'] From ad4a1c00f43bbdf797c6983015129e93c37ce234 Mon Sep 17 00:00:00 2001 From: Patrick Craston Date: Tue, 15 Jan 2013 15:48:15 +0000 Subject: [PATCH 7/7] Ignore p7s smime attachments --- django_mailbox/management/commands/getmail.py | 2 +- django_mailbox/models.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/django_mailbox/management/commands/getmail.py b/django_mailbox/management/commands/getmail.py index 2ee8947..6041782 100644 --- a/django_mailbox/management/commands/getmail.py +++ b/django_mailbox/management/commands/getmail.py @@ -11,7 +11,7 @@ class Command(BaseCommand): self.stdout.write('Gathering messages for %s\n' % mailbox.name) messages = mailbox.get_new_mail() for message in messages: - self.stdout.write('Recieved %s (from %s)\n' % ( + self.stdout.write('Received %s (from %s)\n' % ( message.subject, message.from_address )) diff --git a/django_mailbox/models.py b/django_mailbox/models.py index 098ff36..b0325e5 100755 --- a/django_mailbox/models.py +++ b/django_mailbox/models.py @@ -170,6 +170,10 @@ class Mailbox(models.Model): if part.get('Content-Disposition') is None: continue filename = part.get_filename() + # ignore SMIME extension + filename_basename, filename_extension = os.path.splitext(filename) + if filename_extension in ('.p7s',): + continue data = part.get_payload(decode=True) if not data: continue