diff --git a/core/mail-097f1cf1adf66ab1e18cb70b065e45914c084d52520436c74dab18d5055101cd b/core/mail-097f1cf1adf66ab1e18cb70b065e45914c084d52520436c74dab18d5055101cd new file mode 100644 index 0000000..178f379 --- /dev/null +++ b/core/mail-097f1cf1adf66ab1e18cb70b065e45914c084d52520436c74dab18d5055101cd @@ -0,0 +1,26 @@ +Subject: test +From: test1@test +To: test2@test +Message-ID: <1@test> +Content-Type: multipart/alternative; boundary="abc" + +--abc +Content-Type: text/plain; charset=utf-8 + +test1 + +--abc +Content-Type: image/jpeg; name="test.jpg" +Content-Disposition: inline; filename="test.jpg" +Content-Transfer-Encoding: base64 +Content-ID: <1> +X-Attachment-Id: 1 + +dGVzdGltYWdl + +--abc +Content-Type: text/plain; charset=utf-8 + +test2 + +--abc-- \ No newline at end of file diff --git a/core/mail-3254edd41df7e7f27bf80698b647a51a36ef62f226f33b3e51072fdb900390df b/core/mail-3254edd41df7e7f27bf80698b647a51a36ef62f226f33b3e51072fdb900390df new file mode 100644 index 0000000..db97c0e --- /dev/null +++ b/core/mail-3254edd41df7e7f27bf80698b647a51a36ef62f226f33b3e51072fdb900390df @@ -0,0 +1,5 @@ +Subject: test +From: +To: test2@test +Message-ID: <1@test> + diff --git a/core/mail-3b1343b8f18b2e991acf80395c1338a2fafee4df705c9584058eed0de16afb31 b/core/mail-3b1343b8f18b2e991acf80395c1338a2fafee4df705c9584058eed0de16afb31 new file mode 100644 index 0000000..f420e58 --- /dev/null +++ b/core/mail-3b1343b8f18b2e991acf80395c1338a2fafee4df705c9584058eed0de16afb31 @@ -0,0 +1,8 @@ +Subject: test +From: test1@test +To: test2@test +Message-ID: <1@test> +Content-Type: text/html; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + +hello =C3=A4=C3=B6=C3=BC \ No newline at end of file diff --git a/core/mail-42ee4087f0d74559768fe22003e82df5834974122a50fd5b5e24840acc74356d b/core/mail-42ee4087f0d74559768fe22003e82df5834974122a50fd5b5e24840acc74356d new file mode 100644 index 0000000..3bab076 --- /dev/null +++ b/core/mail-42ee4087f0d74559768fe22003e82df5834974122a50fd5b5e24840acc74356d @@ -0,0 +1,6 @@ +Subject: test +From: test3@test +To: test4@localhost +Message-ID: <1@test> + +test \ No newline at end of file diff --git a/core/mail-4cd6cf91c51b3d75b92d7d5e4334b1f7a24f587ca48ca72a0382f39c3c0be11b b/core/mail-4cd6cf91c51b3d75b92d7d5e4334b1f7a24f587ca48ca72a0382f39c3c0be11b new file mode 100644 index 0000000..49d4282 --- /dev/null +++ b/core/mail-4cd6cf91c51b3d75b92d7d5e4334b1f7a24f587ca48ca72a0382f39c3c0be11b @@ -0,0 +1,6 @@ +Subject: =?UTF-8?Q?suche_M=C3=BCtze?= +From: test3@test +To: test4@test +Message-ID: <1@test> + +Text mit Quoted-Printable-Kodierung: =?utf-8?Q?=C3=A4=C3=B6=C3=BC=C3=9F?= \ No newline at end of file diff --git a/core/mail-5c35987b7a827fed89a3d65142b95ab90452fdd563bf4647fee7d3d215032307 b/core/mail-5c35987b7a827fed89a3d65142b95ab90452fdd563bf4647fee7d3d215032307 new file mode 100644 index 0000000..8595b27 --- /dev/null +++ b/core/mail-5c35987b7a827fed89a3d65142b95ab90452fdd563bf4647fee7d3d215032307 @@ -0,0 +1,7 @@ +Subject: test +From: test1@test +To: test2@test +Message-ID: <1@test> +Content-Type: text/html; charset=iso-8859-1 + +hello äöü \ No newline at end of file diff --git a/core/mail-723cc57085d5747cddd1c2f5bcdcf4b81cc3c215fb255805b938fc08a1603157 b/core/mail-723cc57085d5747cddd1c2f5bcdcf4b81cc3c215fb255805b938fc08a1603157 new file mode 100644 index 0000000..a0a4a77 --- /dev/null +++ b/core/mail-723cc57085d5747cddd1c2f5bcdcf4b81cc3c215fb255805b938fc08a1603157 @@ -0,0 +1,21 @@ +Subject: test +From: test1@test +To: test2@test +Message-ID: <1@test> +Content-Type: multipart/mixed; boundary="abc" + +--abc +Content-Type: text/plain; charset=utf-8 + +test1 + +--abc +Content-Type: image/jpeg; name="test.jpg" +Content-Disposition: attachment; filename="test.jpg" +Content-Transfer-Encoding: base64 +Content-ID: <1> +X-Attachment-Id: 1 + +dGVzdGltYWdl + +--abc-- \ No newline at end of file diff --git a/core/mail-73be0be950bbfdabdcbd7d5298d9133ba285ea99c7e86e172c18bfae1efe6e18 b/core/mail-73be0be950bbfdabdcbd7d5298d9133ba285ea99c7e86e172c18bfae1efe6e18 new file mode 100644 index 0000000..43fd8c6 --- /dev/null +++ b/core/mail-73be0be950bbfdabdcbd7d5298d9133ba285ea99c7e86e172c18bfae1efe6e18 @@ -0,0 +1,11 @@ +Subject: test +From: test1@test +To: test2@test +Message-ID: <1@test> +Content-Type: text/html; charset=utf-8 + +
+
+

test

+
+
\ No newline at end of file diff --git a/core/mail-9d5401a2107e1cbc42d75dae9eff4e24772415b41d5ff6daf5c79c97e398225a b/core/mail-9d5401a2107e1cbc42d75dae9eff4e24772415b41d5ff6daf5c79c97e398225a new file mode 100644 index 0000000..527711e --- /dev/null +++ b/core/mail-9d5401a2107e1cbc42d75dae9eff4e24772415b41d5ff6daf5c79c97e398225a @@ -0,0 +1,6 @@ +Subject: test =?utf-8?Q?=C3=A4?= +From: test3@test +To: test4@test +Message-ID: <1@test> + +Text mit Quoted-Printable-Kodierung: =?utf-8?Q?=C3=A4=C3=B6=C3=BC=C3=9F?= \ No newline at end of file diff --git a/core/mail-a1bdb097374b6062732207f4a87fd41c9bb3d1c230a722bfc4c07f9c8ca68713 b/core/mail-a1bdb097374b6062732207f4a87fd41c9bb3d1c230a722bfc4c07f9c8ca68713 new file mode 100644 index 0000000..479de32 --- /dev/null +++ b/core/mail-a1bdb097374b6062732207f4a87fd41c9bb3d1c230a722bfc4c07f9c8ca68713 @@ -0,0 +1,6 @@ +Subject: =?utf-8?B?dGVzdA==?= +From: test3@test +To: test4@test +Message-ID: <1@test> + +Text mit Base64-Kodierung: =?utf-8?B?w6TDtsO8w58=?= \ No newline at end of file diff --git a/core/mail-a75fd27ca0fb10aeae58c7c28dce16f1413fd846b7ccafed99e6c065bbbc3bee b/core/mail-a75fd27ca0fb10aeae58c7c28dce16f1413fd846b7ccafed99e6c065bbbc3bee new file mode 100644 index 0000000..7376c2b --- /dev/null +++ b/core/mail-a75fd27ca0fb10aeae58c7c28dce16f1413fd846b7ccafed99e6c065bbbc3bee @@ -0,0 +1,6 @@ +Subject: test +From: test1@test +To: test_event@localhost +Message-ID: <1@test> + +test \ No newline at end of file diff --git a/core/mail-c5c0aacdf241ebcd654f3b41a6ffc04c38fccd675c0d3c8bee3c9745773eb143 b/core/mail-c5c0aacdf241ebcd654f3b41a6ffc04c38fccd675c0d3c8bee3c9745773eb143 new file mode 100644 index 0000000..f55a430 --- /dev/null +++ b/core/mail-c5c0aacdf241ebcd654f3b41a6ffc04c38fccd675c0d3c8bee3c9745773eb143 @@ -0,0 +1,5 @@ +From: noreply@test +To: test2@test +Message-ID: <1@test> + +test \ No newline at end of file diff --git a/core/mail-d35ad18b5ce7ed9c2153dccf2a76218833082af12eddaf0a3a0acf5fc719e847 b/core/mail-d35ad18b5ce7ed9c2153dccf2a76218833082af12eddaf0a3a0acf5fc719e847 new file mode 100644 index 0000000..2c2057a --- /dev/null +++ b/core/mail-d35ad18b5ce7ed9c2153dccf2a76218833082af12eddaf0a3a0acf5fc719e847 @@ -0,0 +1,7 @@ +Subject: test +From: test1@test +To: test2@test +Message-ID: <1@test> +Content-Type: text/html; charset=utf-8 + +thank you =?utf-8?Q?=F0=9F=98=8A?= \ No newline at end of file diff --git a/core/mail/protocol.py b/core/mail/protocol.py index 23ae696..69dbd3c 100644 --- a/core/mail/protocol.py +++ b/core/mail/protocol.py @@ -103,7 +103,7 @@ async def send_smtp(message): await aiosmtplib.send(message, hostname="127.0.0.1", port=25, use_tls=False, start_tls=False) -def find_active_issue_thread(in_reply_to, address, subject, event, spam=False): +def find_active_issue_thread(in_reply_to, address, subject, event): from re import match uuid_match = match(r'^ticket\+([a-f0-9-]{36})@', address) if uuid_match: @@ -114,8 +114,7 @@ def find_active_issue_thread(in_reply_to, address, subject, event, spam=False): if reply_to.exists(): return reply_to.first().issue_thread, False else: - issue = IssueThread.objects.create(name=subject, event=event, - initial_state='pending_suspected_spam' if spam else 'pending_new') + issue = IssueThread.objects.create(name=subject, event=event) return issue, True @@ -214,8 +213,6 @@ def receive_email(envelope, log=None): header_to = parsed.get('To') header_in_reply_to = ascii_strip(parsed.get('In-Reply-To')) header_message_id = ascii_strip(parsed.get('Message-ID')) - maybe_spam = parsed.get('X-Spam') - suspected_spam = (maybe_spam and maybe_spam.lower() == 'yes') if match(r'^([a-zA-Z ]*<)?MAILER-DAEMON@', header_from) and envelope.mail_from.strip("<>") == "": log.warning("Ignoring mailer daemon") @@ -235,8 +232,7 @@ def receive_email(envelope, log=None): sender = decode_inline_encodings(sender) target_event = find_target_event(recipient) - active_issue_thread, new = find_active_issue_thread( - header_in_reply_to, recipient, subject, target_event, suspected_spam) + active_issue_thread, new = find_active_issue_thread(header_in_reply_to, recipient, subject, target_event) from hashlib import sha256 random_filename = 'mail-' + sha256(envelope.content).hexdigest() @@ -254,7 +250,7 @@ def receive_email(envelope, log=None): if new: # auto reply if new issue references = collect_references(active_issue_thread) - if not sender.startswith('noreply') and not sender.startswith('no-reply') and not suspected_spam: + if not sender.startswith('noreply'): subject = f"Re: {subject} [#{active_issue_thread.short_uuid()}]" body = '''Your request (#{}) has been received and will be reviewed by our lost&found angels. diff --git a/core/mail/tests/v2/test_mails.py b/core/mail/tests/v2/test_mails.py index 95d35cb..d2f33fe 100644 --- a/core/mail/tests/v2/test_mails.py +++ b/core/mail/tests/v2/test_mails.py @@ -812,44 +812,6 @@ dGVzdGltYWdl self.assertEqual(None, IssueThread.objects.all()[0].assigned_to) aiosmtplib.send.assert_called_once() - def test_mail_spam_header(self): - from aiosmtpd.smtp import Envelope - from asgiref.sync import async_to_sync - import aiosmtplib - aiosmtplib.send = make_mocked_coro() - handler = LMTPHandler() - server = mock.Mock() - session = mock.Mock() - envelope = Envelope() - envelope.mail_from = 'test1@test' - envelope.rcpt_tos = ['test2@test'] - envelope.content = b'''Subject: test -From: test1@test -To: test2@test -Message-ID: <1@test> -X-Spam: Yes - -test''' - result = async_to_sync(handler.handle_DATA)(server, session, envelope) - - self.assertEqual(result, '250 Message accepted for delivery') - self.assertEqual(len(Email.objects.all()), 1) # do not send auto reply if spam is suspected - self.assertEqual(len(IssueThread.objects.all()), 1) - aiosmtplib.send.assert_not_called() - self.assertEqual('test', Email.objects.all()[0].subject) - self.assertEqual('test1@test', Email.objects.all()[0].sender) - self.assertEqual('test2@test', Email.objects.all()[0].recipient) - self.assertEqual('test', Email.objects.all()[0].body) - self.assertEqual(IssueThread.objects.all()[0], Email.objects.all()[0].issue_thread) - self.assertEqual('<1@test>', Email.objects.all()[0].reference) - self.assertEqual(None, Email.objects.all()[0].in_reply_to) - self.assertEqual('test', IssueThread.objects.all()[0].name) - self.assertEqual('pending_suspected_spam', IssueThread.objects.all()[0].state) - self.assertEqual(None, IssueThread.objects.all()[0].assigned_to) - states = StateChange.objects.filter(issue_thread=IssueThread.objects.all()[0]) - self.assertEqual(1, len(states)) - self.assertEqual('pending_suspected_spam', states[0].state) - def test_mail_4byte_unicode_emoji(self): from aiosmtpd.smtp import Envelope from asgiref.sync import async_to_sync diff --git a/core/tickets/models.py b/core/tickets/models.py index 794c8e4..f7ddb7b 100644 --- a/core/tickets/models.py +++ b/core/tickets/models.py @@ -16,7 +16,6 @@ STATE_CHOICES = ( ('pending_physical_confirmation', 'Needs to be confirmed physically'), ('pending_return', 'Needs to be returned'), ('pending_postponed', 'Postponed'), - ('pending_suspected_spam', 'Suspected Spam'), ('waiting_details', 'Waiting for details'), ('waiting_pre_shipping', 'Waiting for Address/Shipping Info'), ('closed_returned', 'Closed: Returned'), @@ -47,11 +46,6 @@ class IssueThread(SoftDeleteModel): event = models.ForeignKey(Event, null=True, on_delete=models.SET_NULL, related_name='issue_threads') manually_created = models.BooleanField(default=False) - def __init__(self, *args, **kwargs): - if 'initial_state' in kwargs: - self._initial_state = kwargs.pop('initial_state') - super().__init__(*args, **kwargs) - def short_uuid(self): return self.uuid[:8] @@ -116,9 +110,8 @@ def set_uuid(sender, instance, **kwargs): @receiver(post_save, sender=IssueThread) def create_issue_thread(sender, instance, created, **kwargs): - if created and instance.state_changes.count() == 0: - initial_state = getattr(instance, '_initial_state', None) - StateChange.objects.create(issue_thread=instance, state=initial_state if initial_state else 'pending_new') + if created: + StateChange.objects.create(issue_thread=instance, state='pending_new') class Comment(models.Model): diff --git a/web/src/views/TicketSearch.vue b/web/src/views/TicketSearch.vue index f5a4a7d..35e7d07 100644 --- a/web/src/views/TicketSearch.vue +++ b/web/src/views/TicketSearch.vue @@ -25,7 +25,7 @@ :columns="['id', 'name', 'last_activity', 'assigned_to', ...(getEventSlug==='all'?['event']:[])]" :keyName="'state'" :sections="['pending_new', 'pending_open','pending_shipping', - 'pending_physical_confirmation','pending_return','pending_postponed','pending_suspected_spam'].map(stateInfo)"> + 'pending_physical_confirmation','pending_return','pending_postponed'].map(stateInfo)"> diff --git a/web/src/views/Tickets.vue b/web/src/views/Tickets.vue index 60d0d1d..069ce0e 100644 --- a/web/src/views/Tickets.vue +++ b/web/src/views/Tickets.vue @@ -26,7 +26,7 @@ :columns="['id', 'name', 'last_activity', 'assigned_to', ...(getEventSlug==='all'?['event']:[])]" :keyName="'state'" :sections="['pending_new', 'pending_open','pending_shipping', - 'pending_physical_confirmation','pending_return','pending_postponed','pending_suspected_spam'].map(stateInfo)"> + 'pending_physical_confirmation','pending_return','pending_postponed'].map(stateInfo)">