From 1b083befb39d8bda526769299b8181b13b7ff855 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Thu, 22 Jan 2026 12:48:35 +0100 Subject: [PATCH] Make tests pass after rebase --- ...9_outgoingmail.py => 0297_outgoingmail.py} | 4 ++-- src/pretix/base/models/mail.py | 6 ++--- src/pretix/base/services/mail.py | 18 +++++++-------- src/pretix/base/services/notifications.py | 23 +++++++++++-------- 4 files changed, 28 insertions(+), 23 deletions(-) rename src/pretix/base/migrations/{0289_outgoingmail.py => 0297_outgoingmail.py} (97%) diff --git a/src/pretix/base/migrations/0289_outgoingmail.py b/src/pretix/base/migrations/0297_outgoingmail.py similarity index 97% rename from src/pretix/base/migrations/0289_outgoingmail.py rename to src/pretix/base/migrations/0297_outgoingmail.py index 4c383592af..2cf669047f 100644 --- a/src/pretix/base/migrations/0289_outgoingmail.py +++ b/src/pretix/base/migrations/0297_outgoingmail.py @@ -8,7 +8,7 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ("pretixbase", "0288_invoice_transmission"), + ("pretixbase", "0296_invoice_invoice_from_state"), ] operations = [ @@ -28,7 +28,7 @@ class Migration(migrations.Migration): ("error_detail", models.TextField(null=True)), ("subject", models.TextField()), ("body_plain", models.TextField()), - ("body_html", models.TextField()), + ("body_html", models.TextField(null=True)), ("sender", models.CharField(max_length=500)), ("headers", models.JSONField(default=dict)), ("to", models.JSONField(default=list)), diff --git a/src/pretix/base/models/mail.py b/src/pretix/base/models/mail.py index cc9e72ab95..1a25055be6 100644 --- a/src/pretix/base/models/mail.py +++ b/src/pretix/base/models/mail.py @@ -1,8 +1,8 @@ # # This file is part of pretix (Community Edition). # -# Copyright (C) 2014-2020 Raphael Michel and contributors -# Copyright (C) 2020-2021 rami.io GmbH and contributors +# Copyright (C) 2014-2020 Raphael Michel and contributors +# Copyright (C) 2020-today pretix GmbH and contributors # # This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General # Public License as published by the Free Software Foundation in version 3 of the License. @@ -84,7 +84,7 @@ class OutgoingMail(models.Model): subject = models.TextField() body_plain = models.TextField() - body_html = models.TextField() + body_html = models.TextField(null=True) sender = models.CharField(max_length=500) headers = models.JSONField(default=dict) to = models.JSONField(default=list) diff --git a/src/pretix/base/services/mail.py b/src/pretix/base/services/mail.py index 3bf039f524..336a7c5a33 100644 --- a/src/pretix/base/services/mail.py +++ b/src/pretix/base/services/mail.py @@ -42,7 +42,7 @@ import smtplib import warnings from email.mime.image import MIMEImage from email.utils import formataddr -from typing import Any, Dict, Sequence, Union +from typing import Any, Dict, Optional, Sequence, Union from urllib.parse import urljoin, urlparse from zoneinfo import ZoneInfo @@ -554,18 +554,18 @@ def mail_send_task(self, *args, outgoing_mail: int) -> bool: retry_after = min(30 + cnt * 10, 1800) outgoing_mail.status = OutgoingMail.STATUS_AWAWITING_RETRY - outgoing_mail.save(upate_fields=["status", "error", "error_detail", "sent"]) + outgoing_mail.save(update_fields=["status", "error", "error_detail", "sent"]) self.retry(max_retries=max_retries, countdown=retry_after) # throws RetryException, ends function flow elif retry_strategy in ("microsoft_concurrency", "quick"): max_retries = 5 retry_after = [10, 30, 60, 300, 900, 900][self.request.retries] outgoing_mail.status = OutgoingMail.STATUS_AWAWITING_RETRY - outgoing_mail.save(upate_fields=["status", "error", "error_detail", "sent"]) + outgoing_mail.save(update_fields=["status", "error", "error_detail", "sent"]) self.retry(max_retries=max_retries, countdown=retry_after) # throws RetryException, ends function flow elif retry_strategy == "slow": outgoing_mail.status = OutgoingMail.STATUS_AWAWITING_RETRY - outgoing_mail.save(upate_fields=["status", "error", "error_detail", "sent"]) + outgoing_mail.save(update_fields=["status", "error", "error_detail", "sent"]) self.retry(max_retries=5, countdown=[60, 300, 600, 1200, 1800, 1800][self.request.retries]) # throws RetryException, ends function flow except MaxRetriesExceededError: @@ -591,7 +591,7 @@ def mail_send_task(self, *args, outgoing_mail: int) -> bool: # If we reach this, it's a non-retryable error outgoing_mail.status = OutgoingMail.STATUS_FAILED outgoing_mail.sent = now() - outgoing_mail.save(upate_fields=["status", "error", "error_detail", "sent"]) + outgoing_mail.save(update_fields=["status", "error", "error_detail", "sent"]) for i in invoices_to_mark_transmitted: i.set_transmission_failed(provider="email_pdf", data={ "reason": "exception", @@ -615,7 +615,7 @@ def mail_send_task(self, *args, outgoing_mail: int) -> bool: outgoing_mail.error_detail = None outgoing_mail.actual_attachments = actual_attachments outgoing_mail.sent = now() - outgoing_mail.save(upate_fields=["status", "error", "error_detail", "sent", "actual_attachments"]) + outgoing_mail.save(update_fields=["status", "error", "error_detail", "sent", "actual_attachments"]) for i in invoices_to_mark_transmitted: if i.transmission_status != Invoice.TRANSMISSION_STATUS_COMPLETED: i.transmission_date = now() @@ -624,7 +624,7 @@ def mail_send_task(self, *args, outgoing_mail: int) -> bool: i.transmission_info = { "sent": [ { - "recipients": to, + "recipients": outgoing_mail.to, "datetime": now().isoformat(), } ] @@ -636,7 +636,7 @@ def mail_send_task(self, *args, outgoing_mail: int) -> bool: elif i.transmission_provider == "email_pdf": i.transmission_info["sent"].append( { - "recipients": to, + "recipients": outgoing_mail.to, "datetime": now().isoformat(), } ) @@ -650,7 +650,7 @@ def mail_send_task(self, *args, outgoing_mail: int) -> bool: "transmission_provider": "email_pdf", "transmission_type": "email", "data": { - "recipients": [to], + "recipients": outgoing_mail.to, }, } ) diff --git a/src/pretix/base/services/notifications.py b/src/pretix/base/services/notifications.py index 5a75dfafbe..b63eefaeca 100644 --- a/src/pretix/base/services/notifications.py +++ b/src/pretix/base/services/notifications.py @@ -26,7 +26,9 @@ from django.utils.timezone import override from django_scopes import scope, scopes_disabled from pretix.base.i18n import language -from pretix.base.models import LogEntry, NotificationSetting, User +from pretix.base.models import ( + LogEntry, NotificationSetting, OutgoingMail, User, +) from pretix.base.notifications import Notification, get_all_notification_types from pretix.base.services.mail import mail_send_task from pretix.base.services.tasks import ProfiledTask, TransactionAwareTask @@ -153,16 +155,19 @@ def send_notification_mail(notification: Notification, user: User): tpl_plain = get_template('pretixbase/email/notification.txt') body_plain = tpl_plain.render(ctx) - mail_send_task.apply_async(kwargs={ - 'to': [user.email], - 'subject': '[{}] {}: {}'.format( + m = OutgoingMail.objects.create( + user=user, + to=[user.email], + subject='[{}] {}: {}'.format( settings.PRETIX_INSTANCE_NAME, notification.event.settings.mail_prefix or notification.event.slug.upper(), notification.title ), - 'body': body_plain, - 'html': body_html, - 'sender': settings.MAIL_FROM_NOTIFICATIONS, - 'headers': {}, - 'user': user.pk + body_plain=body_plain, + body_html=body_html, + sender=settings.MAIL_FROM_NOTIFICATIONS, + headers={}, + ) + mail_send_task.apply_async(kwargs={ + 'outgoing_mail': m.pk, })