fix: Date/Message-ID/From-name on ticket emails, richer body (1.6.1-aio.9)
A tester's ticket email landed in spam. A mail-tester run against demo scored 8.3/10 with SPF, DKIM and DMARC all passing through the VPS relay, so the deductions were all in the message: MISSING_DATE (1.4), HTML_IMAGE_ONLY_04 (0.3), MISSING_MID (0.1) — and Gmail/Outlook weigh a missing Date/Message-ID as "machine-generated" far more than that. - `build_ticket_email` sets Date, a Message-ID under the sender domain, and a From display name from `lnbits_site_title`. - The body now carries the event name, dates, location, name on ticket, ticket id and the door instruction, so the HTML part is no longer a QR with a handful of words. Upstream candidate: lnbits core `send_email` has the same omissions. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYwoAkZZmXMMmaBp4WGUBo
This commit is contained in:
parent
8b423f185a
commit
3a8e0ff591
4 changed files with 137 additions and 26 deletions
69
tests/test_ticket_email.py
Normal file
69
tests/test_ticket_email.py
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
from datetime import datetime, timezone
|
||||
|
||||
from lnbits.settings import settings
|
||||
|
||||
from ..models import Event, Ticket
|
||||
from ..services import _ticket_notification_payload, build_ticket_email
|
||||
|
||||
|
||||
def _event(**overrides) -> Event:
|
||||
data = {
|
||||
"id": "evt1",
|
||||
"wallet": "w",
|
||||
"name": "Test Event",
|
||||
"info": "",
|
||||
"closing_date": "2030-01-01",
|
||||
"event_start_date": "2030-01-01T16:00:00+01:00",
|
||||
"event_end_date": "2030-01-01T20:00:00+01:00",
|
||||
"location": "The Chateau",
|
||||
"amount_tickets": 10,
|
||||
"price_per_ticket": 5,
|
||||
"time": datetime.now(timezone.utc),
|
||||
}
|
||||
data.update(overrides)
|
||||
return Event(**data)
|
||||
|
||||
|
||||
def _ticket(**overrides) -> Ticket:
|
||||
now = datetime.now(timezone.utc)
|
||||
data = {
|
||||
"id": "tkt1",
|
||||
"wallet": "w",
|
||||
"event": "evt1",
|
||||
"name": "Ada",
|
||||
"email": "ada@example.com",
|
||||
"registered": False,
|
||||
"paid": True,
|
||||
"time": now,
|
||||
"reg_timestamp": now,
|
||||
}
|
||||
data.update(overrides)
|
||||
return Ticket(**data)
|
||||
|
||||
|
||||
def test_email_carries_date_message_id_and_display_name(monkeypatch):
|
||||
monkeypatch.setattr(settings, "lnbits_site_title", "Oyez!")
|
||||
msg = build_ticket_email(
|
||||
"tickets@example.org", ["ada@example.com"], "Subj", "text", "<p>html</p>"
|
||||
)
|
||||
assert msg["Date"]
|
||||
assert msg["Message-ID"].endswith("@example.org>")
|
||||
assert msg["From"] == "Oyez! <tickets@example.org>"
|
||||
parts = [p.get_content_type() for p in msg.get_payload()]
|
||||
assert parts == ["text/plain", "text/html"]
|
||||
|
||||
|
||||
def test_payload_includes_event_details_and_qr(monkeypatch):
|
||||
monkeypatch.setattr(settings, "lnbits_baseurl", "https://lnbits.example/")
|
||||
subject, text, html = _ticket_notification_payload(_ticket(), _event())
|
||||
assert "Test Event" in subject
|
||||
for needle in (
|
||||
"Event: Test Event",
|
||||
"Where: The Chateau",
|
||||
"Name on ticket: Ada",
|
||||
"Ticket ID: tkt1",
|
||||
"at the door",
|
||||
):
|
||||
assert needle in text
|
||||
assert "/events/api/v1/qr/tkt1" in text
|
||||
assert "<img" in html and "Ticket ID: tkt1" in html
|
||||
Loading…
Add table
Add a link
Reference in a new issue