forked from mirror/django-mailbox
Support for Django 5.0 and python 3.12 + Fix CI (#277)
* Upgrade to last Django & Python supported versions * flake8 fixes * Add CI * Add final version of Django 5.0
This commit is contained in:
parent
462fdd3e49
commit
7fde5f7165
16 changed files with 119 additions and 89 deletions
|
|
@ -5,3 +5,5 @@ from django.utils.translation import gettext_lazy as _
|
|||
class MailBoxConfig(AppConfig):
|
||||
name = 'django_mailbox'
|
||||
verbose_name = _("Mail Box")
|
||||
|
||||
default_auto_field = "django.db.models.AutoField"
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import email
|
|||
import logging
|
||||
import mimetypes
|
||||
import os.path
|
||||
import sys
|
||||
import uuid
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
|
|
@ -42,7 +41,7 @@ class MailboxQuerySet(models.QuerySet):
|
|||
for mailbox in self.all():
|
||||
logger.debug('Receiving mail for %s' % mailbox)
|
||||
count += sum(1 for i in mailbox.get_new_mail())
|
||||
logger.debug('Received %d %s.', count, 'mails' if count != 1 else 'mail')
|
||||
logger.debug('Received %d %s.', count, 'mail(s)')
|
||||
|
||||
|
||||
class MailboxManager(models.Manager):
|
||||
|
|
@ -123,6 +122,13 @@ class Mailbox(models.Model):
|
|||
objects = MailboxManager()
|
||||
active_mailboxes = ActiveMailboxManager()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Mailbox')
|
||||
verbose_name_plural = _('Mailboxes')
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def _protocol_info(self):
|
||||
return urlparse(self.uri)
|
||||
|
|
@ -448,13 +454,12 @@ class Mailbox(models.Model):
|
|||
|
||||
def get_new_mail(self, condition=None):
|
||||
"""Connect to this transport and fetch new messages."""
|
||||
new_mail = []
|
||||
connection = self.get_connection()
|
||||
if not connection:
|
||||
return
|
||||
for message in connection.get_message(condition):
|
||||
msg = self.process_incoming_message(message)
|
||||
if not msg is None:
|
||||
if msg is not None:
|
||||
yield msg
|
||||
self.last_polling = now()
|
||||
if django.VERSION >= (1, 5): # Django 1.5 introduces update_fields
|
||||
|
|
@ -483,14 +488,6 @@ class Mailbox(models.Model):
|
|||
)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Mailbox')
|
||||
verbose_name_plural = _('Mailboxes')
|
||||
|
||||
|
||||
class IncomingMessageManager(models.Manager):
|
||||
def get_queryset(self):
|
||||
return super().get_queryset().filter(
|
||||
|
|
@ -757,7 +754,7 @@ class Message(models.Model):
|
|||
"""Returns an `email.message.EmailMessage` instance representing the
|
||||
contents of this message and all attachments.
|
||||
|
||||
See [email.message.EmailMessage]_ for more information as to what methods
|
||||
See [email.message.EmailMessage]_ for more information like what methods
|
||||
and properties are available on `email.message.EmailMessage` instances.
|
||||
|
||||
.. note::
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
from django.dispatch.dispatcher import Signal
|
||||
|
||||
message_received = Signal(providing_args=['message'])
|
||||
message_received = Signal() # providing_args=['message']
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import gzip
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
import copy
|
||||
from unittest import mock
|
||||
|
|
@ -9,7 +8,7 @@ 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.utils.encoding import force_str
|
||||
from django.core.mail import EmailMessage
|
||||
|
||||
__all__ = ['TestProcessEmail']
|
||||
|
|
@ -367,12 +366,12 @@ class TestProcessEmail(EmailMessageTestCase):
|
|||
email_object = self._get_email_object(
|
||||
'message_with_long_content.eml',
|
||||
)
|
||||
size = len(force_text(email_object.as_string()))
|
||||
size = len(force_str(email_object.as_string()))
|
||||
|
||||
msg = self.mailbox.process_incoming_message(email_object)
|
||||
|
||||
self.assertEqual(size,
|
||||
len(force_text(msg.get_email_object().as_string())))
|
||||
len(force_str(msg.get_email_object().as_string())))
|
||||
|
||||
def test_message_saved(self):
|
||||
message = self._get_email_object('generic_message.eml')
|
||||
|
|
@ -386,7 +385,7 @@ class TestProcessEmail(EmailMessageTestCase):
|
|||
|
||||
msg = self.mailbox.process_incoming_message(message)
|
||||
|
||||
self.assertNotEquals(msg.eml, None)
|
||||
self.assertNotEqual(msg.eml, None)
|
||||
|
||||
self.assertTrue(msg.eml.name.endswith('.eml'))
|
||||
|
||||
|
|
@ -408,7 +407,7 @@ class TestProcessEmail(EmailMessageTestCase):
|
|||
|
||||
msg = self.mailbox.process_incoming_message(message)
|
||||
|
||||
self.assertEquals(msg.eml, None)
|
||||
self.assertEqual(msg.eml, None)
|
||||
|
||||
def test_message_compressed(self):
|
||||
message = self._get_email_object('generic_message.eml')
|
||||
|
|
|
|||
|
|
@ -1,34 +1,25 @@
|
|||
from distutils.version import LooseVersion
|
||||
from unittest import mock
|
||||
|
||||
from django.core.management import call_command, CommandError
|
||||
from django.test import TestCase
|
||||
import django
|
||||
|
||||
|
||||
class CommandsTestCase(TestCase):
|
||||
def test_processincomingmessage_no_args(self):
|
||||
"""Check that processincomingmessage works with no args"""
|
||||
|
||||
|
||||
mailbox_name = None
|
||||
# Mock handle so that the test doesn't hang waiting for input. Note that we are only testing
|
||||
# the argument parsing here -- functionality should be tested elsewhere
|
||||
with mock.patch('django_mailbox.management.commands.processincomingmessage.Command.handle') as handle:
|
||||
# Don't care about the return value
|
||||
handle.return_value = None
|
||||
|
||||
|
||||
call_command('processincomingmessage')
|
||||
args, kwargs = handle.call_args
|
||||
|
||||
# Make sure that we called with the right arguments
|
||||
try:
|
||||
self.assertEqual(kwargs['mailbox_name'], mailbox_name)
|
||||
except KeyError:
|
||||
# Handle Django 1.7
|
||||
# It uses optparse instead of argparse, so instead of being
|
||||
# set to None, mailbox_name is simply left out altogether
|
||||
# Thus we expect an empty tuple here
|
||||
self.assertEqual(args, tuple())
|
||||
|
||||
self.assertEqual(kwargs['mailbox_name'], mailbox_name)
|
||||
|
||||
def test_processincomingmessage_with_arg(self):
|
||||
"""Check that processincomingmessage works with mailbox_name given"""
|
||||
|
|
@ -37,29 +28,14 @@ class CommandsTestCase(TestCase):
|
|||
|
||||
with mock.patch('django_mailbox.management.commands.processincomingmessage.Command.handle') as handle:
|
||||
handle.return_value = None
|
||||
|
||||
|
||||
call_command('processincomingmessage', mailbox_name)
|
||||
args, kwargs = handle.call_args
|
||||
try:
|
||||
self.assertEqual(kwargs['mailbox_name'], mailbox_name)
|
||||
except (AssertionError, KeyError):
|
||||
# Handle Django 1.7
|
||||
# It uses optparse instead of argparse, so instead of being
|
||||
# in kwargs, mailbox_name is in args
|
||||
self.assertEqual(args[0], mailbox_name)
|
||||
|
||||
self.assertEqual(kwargs['mailbox_name'], mailbox_name)
|
||||
|
||||
def test_processincomingmessage_too_many_args(self):
|
||||
"""Check that processincomingmessage raises an error if too many args"""
|
||||
# Only perform this test for Django versions greater than 1.7.*. This
|
||||
# is because, with optparse, too many arguments doesn't result in an
|
||||
# error, which means this test is worthless anyway
|
||||
# For the "compatibility" versions, unexpected arguments aren't handled
|
||||
# very well, and result in a TypeError
|
||||
if (LooseVersion(django.get_version()) >= LooseVersion('1.8') and
|
||||
LooseVersion(django.get_version()) < LooseVersion('1.10')):
|
||||
with self.assertRaises(TypeError):
|
||||
call_command('processincomingmessage', 'foo_mailbox', 'invalid_arg')
|
||||
# In 1.10 and later a proper CommandError should be raised
|
||||
elif LooseVersion(django.get_version()) >= LooseVersion('1.10'):
|
||||
with self.assertRaises(CommandError):
|
||||
call_command('processincomingmessage', 'foo_mailbox', 'invalid_arg')
|
||||
|
||||
with self.assertRaises(CommandError):
|
||||
call_command('processincomingmessage', 'foo_mailbox', 'invalid_arg')
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from django_mailbox.transports import ImapTransport, Pop3Transport
|
|||
FAKE_UID_SEARCH_ANSWER = (
|
||||
'OK',
|
||||
[
|
||||
b'18 19 20 21 22 23 24 25 26 27 28 29 ' +
|
||||
b'18 19 20 21 22 23 24 25 26 27 28 29 ' +
|
||||
b'30 31 32 33 34 35 36 37 38 39 40 41 42 43 44'
|
||||
]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,4 +9,3 @@ class EmailTransport:
|
|||
message = email.message_from_bytes(contents)
|
||||
|
||||
return message
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import sys
|
||||
|
||||
|
||||
from .base import EmailTransport
|
||||
|
||||
|
|
|
|||
|
|
@ -63,4 +63,3 @@ class Office365Transport(EmailTransport):
|
|||
|
||||
o365message.delete()
|
||||
return
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue