Compare commits

..

1 Commits

Author SHA1 Message Date
Raphael Michel
bbdcf343f5 Outgoing mail: Decode unicode in From headers 2026-01-30 13:43:45 +01:00
12 changed files with 754 additions and 738 deletions

View File

@@ -294,28 +294,14 @@ def metric_values():
channel = app.broker_connection().channel()
if hasattr(channel, 'client') and channel.client is not None:
client = channel.client
priority_steps = settings.CELERY_BROKER_TRANSPORT_OPTIONS.get("priority_steps", [0])
sep = settings.CELERY_BROKER_TRANSPORT_OPTIONS.get("sep", ":")
for q in settings.CELERY_TASK_QUEUES:
queue_lengths = []
queue_delays = []
for prio in priority_steps:
if prio:
qname = f"{q.name}{sep}{prio}"
else:
qname = q.name
queue_length = client.llen(qname)
queue_lengths.append(queue_length)
oldest_queue_item = client.lindex(qname, -1)
if oldest_queue_item:
ldata = json.loads(oldest_queue_item)
oldest_item_age = time.time() - ldata.get('created', 0)
queue_delays.append(oldest_item_age)
metrics['pretix_celery_tasks_queued_count']['{queue="%s"}' % q.name] = sum(queue_lengths)
if queue_delays:
metrics['pretix_celery_tasks_queued_age_seconds']['{queue="%s"}' % q.name] = max(queue_delays)
llen = client.llen(q.name)
lfirst = client.lindex(q.name, -1)
metrics['pretix_celery_tasks_queued_count']['{queue="%s"}' % q.name] = llen
if lfirst:
ldata = json.loads(lfirst)
dt = time.time() - ldata.get('created', 0)
metrics['pretix_celery_tasks_queued_age_seconds']['{queue="%s"}' % q.name] = dt
else:
metrics['pretix_celery_tasks_queued_age_seconds']['{queue="%s"}' % q.name] = 0

View File

@@ -1231,8 +1231,8 @@ class ManualPayment(BasePaymentProvider):
def is_allowed(self, request: HttpRequest, total: Decimal=None):
return 'pretix.plugins.manualpayment' in self.event.plugins and super().is_allowed(request, total)
def order_change_allowed(self, order: Order, request=None):
return 'pretix.plugins.manualpayment' in self.event.plugins and super().order_change_allowed(order, request)
def order_change_allowed(self, order: Order):
return 'pretix.plugins.manualpayment' in self.event.plugins and super().order_change_allowed(order)
@property
def public_name(self):

View File

@@ -321,7 +321,7 @@ def mail(email: Union[str, Sequence[str]], subject: str, template: Union[str, La
body_plain=body_plain,
body_html=body_html,
sender=sender,
headers=headers or {},
headers=headers,
should_attach_tickets=attach_tickets,
should_attach_ical=attach_ical,
should_attach_other_files=attach_other_files or [],
@@ -763,7 +763,7 @@ def mail_send(to: List[str], subject: str, body: str, html: Optional[str], sende
body_plain=body,
body_html=html,
sender=sender,
headers=headers or {},
headers=headers,
should_attach_tickets=attach_tickets,
should_attach_ical=attach_ical,
should_attach_other_files=attach_other_files or [],

View File

@@ -95,7 +95,6 @@ class OrganizerSlugBanlistValidator(BanlistValidator):
'csp_report',
'widget',
'lead',
'scheduling',
]

View File

@@ -19,7 +19,7 @@
<dl class="dl-horizontal">
<dt>{% trans "From" context "email" %}</dt>
<dd>{{ mail.sender }}</dd>
<dd>{{ sender }}</dd>
<dt>{% trans "To" context "email" %}</dt>
<dd>{{ mail.to|join:", " }}</dd>
{% if mail.cc %}

View File

@@ -21,6 +21,8 @@
#
import base64
import logging
from email.header import decode_header, make_header
from email.utils import parseaddr
from django.conf import settings
from django.contrib import messages
@@ -124,6 +126,12 @@ class OutgoingMailDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequir
ctx = super().get_context_data(**kwargs)
if self.object.body_html:
ctx['data_url'] = "data:text/html;charset=utf-8;base64," + base64.b64encode(self.object.body_html.encode()).decode()
from_name, from_email = parseaddr(self.object.sender)
if from_name:
from_name = make_header(decode_header(from_name))
ctx['sender'] = "{} <{}>".format(from_name, from_email) if from_name else from_email
return ctx

View File

@@ -148,7 +148,4 @@ def pycountry_add(db, **kw):
continue
value = value.lower()
index = db.indices.setdefault(key, {})
if key in ["country_code"]:
index.setdefault(value, set()).add(obj)
else:
index[value] = obj
index.setdefault(value, set()).add(obj)

View File

@@ -1510,10 +1510,7 @@ class OrderChangeMixin:
'max_count': iao.max_count,
'iao': iao,
'items': [i for i in items if not i.require_voucher],
'items_missing': {
k: v for k, v in current_addon_products_missing.items()
if v and k[0].category_id == iao.addon_category_id
},
'items_missing': {k: v for k, v in current_addon_products_missing.items() if v},
})
return positions

View File

@@ -97,8 +97,7 @@ class UnlockHashView(EventViewMixin, View):
def get(self, request, *args, **kwargs):
hashes = request.session.get('pretix_unlock_hashes', [])
if kwargs.get('hash') not in hashes:
hashes.append(kwargs.get('hash'))
hashes.append(kwargs.get('hash'))
request.session['pretix_unlock_hashes'] = hashes
if 'voucher' in request.GET:

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
"scripts": {},
"dependencies": {
"@babel/core": "^7.28.5",
"@babel/preset-env": "^7.29.0",
"@babel/preset-env": "^7.28.5",
"@rollup/plugin-babel": "^6.1.0",
"@rollup/plugin-node-resolve": "^16.0.3",
"vue": "^2.7.16",

View File

@@ -170,6 +170,7 @@ def test_queue_state_sent(env):
subject='Test',
body_plain='Test',
sender='sender@example.com',
headers={},
)
assert m.status == OutgoingMail.STATUS_QUEUED
mail_send_task.apply(kwargs={
@@ -187,6 +188,7 @@ def test_queue_state_permanent_failure(env):
subject='Test',
body_plain='Test',
sender='sender@example.com',
headers={},
)
assert m.status == OutgoingMail.STATUS_QUEUED
mail_send_task.apply(kwargs={
@@ -208,6 +210,7 @@ def test_queue_state_retry_failure(env, monkeypatch):
subject='Test',
body_plain='Test',
sender='sender@example.com',
headers={},
)
assert m.status == OutgoingMail.STATUS_QUEUED
mail_send_task.apply(kwargs={
@@ -233,6 +236,7 @@ def test_queue_state_foreign_key_handling():
subject='Test',
body_plain='Test',
sender='sender@example.com',
headers={},
)
mail_sent = OutgoingMail.objects.create(
organizer=o,
@@ -241,6 +245,7 @@ def test_queue_state_foreign_key_handling():
subject='Test',
body_plain='Test',
sender='sender@example.com',
headers={},
status=OutgoingMail.STATUS_SENT,
)