diff --git a/modoboa/webmail/factories.py b/modoboa/webmail/factories.py new file mode 100644 index 000000000..51c9d4f1a --- /dev/null +++ b/modoboa/webmail/factories.py @@ -0,0 +1,19 @@ +"""Webmail factories.""" + +import factory + +from modoboa.admin import factories as admin_factories + +from modoboa.webmail import models + + +class ScheduledMessageFactory(factory.django.DjangoModelFactory): + """Scheduled message factory.""" + + class Meta: + model = models.ScheduledMessage + + account = factory.SubFactory(admin_factories.UserFactory) + sender = "sender@test.com" + subject = "Scheduled Message" + to = "recipient@domain.test" diff --git a/modoboa/webmail/jobs.py b/modoboa/webmail/jobs.py index 0d6147d89..9a14a835f 100644 --- a/modoboa/webmail/jobs.py +++ b/modoboa/webmail/jobs.py @@ -21,6 +21,6 @@ def send_scheduled_messages(): ) queue = django_rq.get_queue("modoboa") for message in messages: - message.state = constants.SchedulingState.SENDING + message.status = constants.SchedulingState.SENDING message.save() queue.enqueue(send_scheduled_message, message_id=message.id) diff --git a/modoboa/webmail/tests/test_viewsets.py b/modoboa/webmail/tests/test_viewsets.py index 358d7880b..5a23744b9 100644 --- a/modoboa/webmail/tests/test_viewsets.py +++ b/modoboa/webmail/tests/test_viewsets.py @@ -5,15 +5,21 @@ import shutil import tempfile from unittest import mock +from dateutil.relativedelta import relativedelta +from freezegun import freeze_time +from rq import SimpleWorker + from django.core import mail from django.urls import reverse from django.utils import timezone +import django_rq from oauth2_provider.models import get_access_token_model, get_application_model from modoboa.core import models as core_models from modoboa.admin import factories as admin_factories from modoboa.lib.tests import ModoAPITestCase +from modoboa.webmail import factories, jobs, models from modoboa.webmail.lib.attachments import ComposeSessionManager from modoboa.webmail.mocks import IMAP4Mock @@ -368,3 +374,79 @@ class ComposeSessionViewSetTestCase(WebmailTestCase): self.assertEqual(response.status_code, 204) self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].from_email, '"Antoine Nguyen" ') + + def test_schedule_and_send(self): + self.authenticate() + uid = self._create_compose_session() + # Upload an attachment + url = reverse("v2:webmail-compose-session-attachments", args=[uid]) + with self.settings(MEDIA_ROOT=self.workdir): + self.client.post(url, {"attachment": get_gif()}) + # Schedule the message too early + scheduled_datetime = timezone.now() + url = reverse("v2:webmail-compose-session-send", args=[uid]) + response = self.client.post( + url, + { + "sender": self.user.email, + "to": ["test@example.test"], + "subject": "test", + "body": "Test", + "scheduled_datetime": scheduled_datetime.isoformat(), + }, + format="json", + ) + self.assertEqual(response.status_code, 400) + self.assertIn("scheduled_datetime", response.json()) + + scheduled_datetime = timezone.now() + relativedelta(hours=1) + response = self.client.post( + url, + { + "sender": self.user.email, + "to": ["test@example.test"], + "subject": "test", + "body": "Test", + "scheduled_datetime": scheduled_datetime.isoformat(), + }, + format="json", + ) + self.assertEqual(response.status_code, 204) + self.assertEqual(len(mail.outbox), 0) + self.assertEqual(models.ScheduledMessage.objects.count(), 1) + self.assertEqual(models.MessageAttachment.objects.count(), 1) + + with freeze_time(scheduled_datetime + relativedelta(minutes=1)): + jobs.send_scheduled_messages() + queue = django_rq.get_queue("modoboa") + worker = SimpleWorker([queue], connection=queue.connection) + worker.work(burst=True) + + self.assertEqual(len(mail.outbox), 1) + self.assertEqual(models.ScheduledMessage.objects.count(), 0) + self.assertEqual(models.MessageAttachment.objects.count(), 0) + + +class ScheduledMessageViewSetTestCase(WebmailTestCase): + + def setUp(self): + super().setUp() + self.message = factories.ScheduledMessageFactory( + account=self.user, scheduled_datetime=timezone.now() + ) + + def test_delete(self): + self.authenticate() + url = reverse("v2:webmail-scheduled-message-detail", args=[self.message.id]) + response = self.client.delete(url) + self.assertEqual(response.status_code, 204) + self.assertEqual(models.ScheduledMessage.objects.count(), 0) + + def test_update(self): + self.authenticate() + url = reverse("v2:webmail-scheduled-message-detail", args=[self.message.id]) + data = {"scheduled_datetime": timezone.now() + relativedelta(days=1)} + response = self.client.patch(url, data, format="json") + self.assertEqual(response.status_code, 200) + self.message.refresh_from_db() + self.assertEqual(self.message.imap_uid, 11)