add event mail addresses to the /events endpoints

This commit is contained in:
j3d1 2024-11-06 00:03:35 +01:00
parent 55cef1128e
commit f44da341b4
10 changed files with 90 additions and 13 deletions

View file

@ -0,0 +1,20 @@
# Generated by Django 4.2.7 on 2024-11-03 18:30
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('inventory', '0004_alter_event_created_at_alter_item_created_at'),
('mail', '0004_alter_emailattachment_file'),
]
operations = [
migrations.AlterField(
model_name='eventaddress',
name='event',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='addresses', to='inventory.event'),
),
]

View file

@ -31,7 +31,7 @@ class Email(SoftDeleteModel):
class EventAddress(models.Model):
id = models.AutoField(primary_key=True)
event = models.ForeignKey(Event, models.SET_NULL, null=True)
event = models.ForeignKey(Event, models.SET_NULL, null=True, related_name='addresses')
address = models.CharField(max_length=255)

View file

@ -1,4 +1,5 @@
import logging
from re import match
import aiosmtplib
from channels.layers import get_channel_layer
@ -10,6 +11,10 @@ from notify_sessions.models import SystemEvent
from tickets.models import IssueThread
class SpecialMailException(Exception):
pass
def find_quoted_printable(s, marker):
positions = [i for i in range(len(s)) if s.lower().startswith('=?utf-8?' + marker + '?', i)]
for pos in positions:
@ -180,13 +185,13 @@ def receive_email(envelope, log=None):
header_in_reply_to = parsed.get('In-Reply-To')
header_message_id = parsed.get('Message-ID')
if header_from != envelope.mail_from:
log.warning("Header from does not match envelope from")
log.info(f"Header from: {header_from}, envelope from: {envelope.mail_from}")
if match(r'^([a-zA-Z ]*<)?MAILER-DAEMON@', header_from) and envelope.mail_from.strip("<>") == "":
log.warning("Ignoring mailer daemon")
raise SpecialMailException("Ignoring mailer daemon")
if header_to != envelope.rcpt_tos[0]:
log.warning("Header to does not match envelope to")
log.info(f"Header to: {header_to}, envelope to: {envelope.rcpt_tos[0]}")
if Email.objects.filter(reference=header_message_id).exists(): # break before issue thread is created
log.warning("Email already exists")
raise Exception("Email already exists")
recipient = envelope.rcpt_tos[0].lower() if envelope.rcpt_tos else header_to.lower()
sender = envelope.mail_from if envelope.mail_from else header_from
@ -233,7 +238,7 @@ Your c3lf (Cloakroom + Lost&Found) Team'''.format(active_issue_thread.short_uuid
active_issue_thread.state = 'pending_open'
active_issue_thread.save()
return email, new, reply
return email, new, reply, active_issue_thread
class LMTPHandler:
@ -255,7 +260,7 @@ class LMTPHandler:
content = None
try:
content = envelope.content
email, new, reply = await receive_email(envelope, log)
email, new, reply, thread = await receive_email(envelope, log)
log.info(f"Created email {email.id}")
systemevent = await database_sync_to_async(SystemEvent.objects.create)(type='email received',
reference=email.id)
@ -263,14 +268,20 @@ class LMTPHandler:
channel_layer = get_channel_layer()
await channel_layer.group_send(
'general', {"type": "generic.event", "name": "send_message_to_frontend", "event_id": systemevent.id,
"message": "email received"}
)
"message": "email received"})
log.info(f"Sent message to frontend")
if new and reply:
log.info('Sending message to %s' % reply['To'])
await send_smtp(reply)
log.info("Sent auto reply")
return '250 Message accepted for delivery'
except SpecialMailException as e:
import uuid
random_filename = 'special-' + str(uuid.uuid4())
with open(random_filename, 'wb') as f:
f.write(content)
log.warning(f"Special mail exception: {e} saved to {random_filename}")
return '250 Message accepted for delivery'
except Exception as e:
from hashlib import sha256

View file

@ -760,7 +760,6 @@ dGVzdGltYWdl
response = self.client.post(f'/api/2/tickets/{issue_thread.id}/reply/', {
'message': 'test'
})
aiosmtplib.send.assert_called_once()
self.assertEqual(response.status_code, 201)
self.assertEqual(5, len(Email.objects.all()))
self.assertEqual(5, len(Email.objects.filter(issue_thread=issue_thread)))
@ -776,6 +775,7 @@ dGVzdGltYWdl
self.assertEqual('test subject', IssueThread.objects.all()[0].name)
self.assertEqual('pending_new', IssueThread.objects.all()[0].state)
self.assertEqual(None, IssueThread.objects.all()[0].assigned_to)
aiosmtplib.send.assert_called_once()
def test_mail_4byte_unicode_emoji(self):
from aiosmtpd.smtp import Envelope