diff --git a/.gitignore b/.gitignore index 3f6128e..9b355bf 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ include/* dummy_project/* .cache/ .tox/ +messages diff --git a/django_mailbox/models.py b/django_mailbox/models.py index d5fb3da..116c0de 100644 --- a/django_mailbox/models.py +++ b/django_mailbox/models.py @@ -4,7 +4,7 @@ """ Models declaration for application ``django_mailbox``. """ - +import gzip from email.encoders import encode_base64 from email.message import Message as EmailMessage from email.utils import formatdate, parseaddr @@ -16,13 +16,14 @@ import mimetypes import os.path import sys import uuid +from tempfile import NamedTemporaryFile import six from six.moves.urllib.parse import parse_qs, unquote, urlparse import django from django.conf import settings as django_settings -from django.core.files.base import ContentFile +from django.core.files.base import ContentFile, File from django.core.mail.message import make_msgid from django.db import models from django.utils.translation import ugettext_lazy as _ @@ -345,11 +346,7 @@ class Mailbox(models.Model): settings = utils.get_settings() if settings['store_original_message']: - msg.eml.save( - '%s.eml' % uuid.uuid4(), - ContentFile(message.as_string()), - save=False - ) + self._process_save_original_message(message, msg) msg.mailbox = self if 'subject' in message: msg.subject = ( @@ -385,6 +382,25 @@ class Mailbox(models.Model): msg.save() return msg + def _process_save_original_message(self, message, msg): + settings = utils.get_settings() + if settings['compress_original_message']: + with NamedTemporaryFile(suffix=".eml.gz") as fp_tmp: + with gzip.GzipFile(fileobj=fp_tmp, mode="w") as fp: + fp.write(message.as_string().encode('utf-8')) + msg.eml.save( + "%s.eml.gz" % (uuid.uuid4(), ), + File(fp_tmp), + save=False + ) + + else: + msg.eml.save( + '%s.eml' % uuid.uuid4(), + ContentFile(message.as_string()), + save=False + ) + def get_new_mail(self, condition=None): """Connect to this transport and fetch new messages.""" new_mail = [] @@ -692,8 +708,12 @@ class Message(models.Model): """ if self.eml: - self.eml.open() - body = self.eml.file.read() + if self.eml.name.endswith('.gz'): + body = gzip.GzipFile(fileobj=self.eml).read() + else: + self.eml.open() + body = self.eml.file.read() + self.eml.close() else: body = self.get_body() if six.PY3: diff --git a/django_mailbox/tests/test_process_email.py b/django_mailbox/tests/test_process_email.py index de123c2..0284754 100644 --- a/django_mailbox/tests/test_process_email.py +++ b/django_mailbox/tests/test_process_email.py @@ -1,16 +1,18 @@ +import gzip import os.path import sys +import copy import mock import six from django_mailbox.models import Mailbox, Message from django_mailbox.utils import convert_header_to_unicode +from django_mailbox import utils from django_mailbox.tests.base import EmailMessageTestCase from django.utils.encoding import force_text from django.core.mail import EmailMessage - __all__ = ['TestProcessEmail'] @@ -410,3 +412,60 @@ class TestProcessEmail(EmailMessageTestCase): self.assertEqual(size, len(force_text(msg.get_email_object().as_string()))) + + def test_message_saved(self): + message = self._get_email_object('generic_message.eml') + + default_settings = utils.get_settings() + + with mock.patch('django_mailbox.utils.get_settings') as get_settings: + altered = copy.deepcopy(default_settings) + altered['store_original_message'] = True + get_settings.return_value = altered + + msg = self.mailbox.process_incoming_message(message) + + actual_email_object = msg.get_email_object() + + self.assertNotEquals(msg.eml, None) + + self.assertTrue(msg.eml.name.endswith('.eml')) + + with open(msg.eml.name, 'rb') as f: + self.assertEqual(f.read(), + self._get_email_as_text('generic_message.eml')) + + def test_message_saving_ignored(self): + message = self._get_email_object('generic_message.eml') + + default_settings = utils.get_settings() + + with mock.patch('django_mailbox.utils.get_settings') as get_settings: + altered = copy.deepcopy(default_settings) + altered['store_original_message'] = False + get_settings.return_value = altered + + msg = self.mailbox.process_incoming_message(message) + + self.assertEquals(msg.eml, None) + + def test_message_compressed(self): + message = self._get_email_object('generic_message.eml') + + default_settings = utils.get_settings() + + with mock.patch('django_mailbox.utils.get_settings') as get_settings: + altered = copy.deepcopy(default_settings) + altered['compress_original_message'] = True + altered['store_original_message'] = True + get_settings.return_value = altered + + msg = self.mailbox.process_incoming_message(message) + + actual_email_object = msg.get_email_object() + print(msg.eml.name) + self.assertTrue(msg.eml.name.endswith('.eml.gz')) + + with gzip.open(msg.eml.name, 'rb') as f: + self.assertEqual(f.read(), + self._get_email_as_text('generic_message.eml')) \ No newline at end of file diff --git a/django_mailbox/utils.py b/django_mailbox/utils.py index 17a4b37..f33f3bb 100644 --- a/django_mailbox/utils.py +++ b/django_mailbox/utils.py @@ -54,6 +54,16 @@ def get_settings(): 'DJANGO_MAILBOX_STORE_ORIGINAL_MESSAGE', False ), + 'compress_original_message': getattr( + settings, + 'DJANGO_MAILBOX_COMPRESS_ORIGINAL_MESSAGE', + False + ), + 'original_message_compression': getattr( + settings, + 'DJANGO_MAILBOX_ORIGINAL_MESSAGE_COMPRESSION', + 6 + ), 'default_charset': getattr( settings, 'DJANGO_MAILBOX_default_charset',