This commit is contained in:
j3d1 2023-12-07 00:58:04 +01:00
parent 29e7c4d283
commit 55577adde8
5 changed files with 104 additions and 7 deletions

View file

@ -3,6 +3,7 @@ from unittest import mock
from django.test import TestCase, Client
from core.settings import MAIL_DOMAIN
from inventory.models import Event
from mail.models import Email
from mail.protocol import LMTPHandler
@ -133,3 +134,41 @@ class LMTPHandlerTestCase(TestCase): # TODO replace with less hacky test
self.assertEqual(IssueThread.objects.all()[0].name, 'test')
self.assertEqual(IssueThread.objects.all()[0].state, 'new')
self.assertEqual(IssueThread.objects.all()[0].assigned_to, None)
def test_mail_reply(self):
issue_thread = IssueThread.objects.create(
name="test",
)
mail1 = Email.objects.create(
subject='test subject',
body='test',
sender='test1@test',
recipient='test2@' + MAIL_DOMAIN,
issue_thread=issue_thread,
)
mail1_reply = Email.objects.create(
subject='Re: test subject',
body='Thank you for your message.',
sender='test2@' + MAIL_DOMAIN,
recipient='test1@test',
in_reply_to=mail1.reference,
issue_thread=issue_thread,
)
import aiosmtplib
aiosmtplib.send = make_mocked_coro()
client = Client()
response = client.post(f'/api/2/tickets/{issue_thread.id}/reply/', {
'message': 'test'
})
self.assertEqual(response.status_code, 201)
self.assertEqual(len(Email.objects.all()), 3)
self.assertEqual(len(IssueThread.objects.all()), 1)
aiosmtplib.send.assert_called_once()
self.assertEqual(Email.objects.all()[2].subject, 'Re: test subject')
self.assertEqual(Email.objects.all()[2].sender, 'test2@' + MAIL_DOMAIN)
self.assertEqual(Email.objects.all()[2].recipient, 'test1@test')
self.assertEqual(Email.objects.all()[2].body, 'test')
self.assertEqual(Email.objects.all()[2].issue_thread, issue_thread)
self.assertTrue(Email.objects.all()[2].reference.startswith("<"))
self.assertTrue(Email.objects.all()[2].reference.endswith("@localhost>"))
self.assertEqual(Email.objects.all()[2].in_reply_to, mail1.reference)

View file

@ -1,6 +1,15 @@
from rest_framework import routers, viewsets, serializers
import logging
from tickets.models import IssueThread, Comment, StateChange
from django.urls import path
from rest_framework.decorators import api_view, permission_classes, authentication_classes
from rest_framework import routers, viewsets, serializers, status
from rest_framework.response import Response
from asgiref.sync import async_to_sync
from core.settings import MAIL_DOMAIN
from mail.models import Email
from mail.protocol import send_smtp, make_reply, collect_references
from tickets.models import IssueThread
class IssueSerializer(serializers.ModelSerializer):
@ -48,7 +57,32 @@ class IssueViewSet(viewsets.ModelViewSet):
authentication_classes = []
@api_view(['POST'])
@permission_classes([])
@authentication_classes([])
def reply(request, pk):
issue = IssueThread.objects.get(pk=pk)
# email = issue.reply(request.data['body']) # TODO evaluate if this is a useful abstraction
references = collect_references(issue)
most_recent = Email.objects.filter(issue_thread=issue, recipient__endswith='@' + MAIL_DOMAIN).order_by(
'-timestamp').first()
mail = Email.objects.create(
issue_thread=issue,
sender=most_recent.recipient,
recipient=most_recent.sender,
subject=f'Re: {most_recent.subject}',
body=request.data['message'],
in_reply_to=most_recent.reference,
)
log = logging.getLogger('mail.log')
async_to_sync(send_smtp)(make_reply(mail, references), log)
return Response({'status': 'ok'}, status=status.HTTP_201_CREATED)
router = routers.SimpleRouter()
router.register(r'tickets', IssueViewSet, basename='issues')
urlpatterns = router.urls
urlpatterns = router.urls + [
path('tickets/<int:pk>/reply/', reply, name='reply'),
]