Start at recipient selection
- Creation receipt arrived
- The ticket-created path can address and send to the requester. It does not prove that a later resolution path selects the same actor.
- Observer resolution arrived
- The resolution event, worker and transport reached at least one recipient. It does not prove that every actor received an envelope.
- Requester resolution missing
- First inspect author exclusion, actor identity, anonymization and recipient preferences. Only move to delivery after a requester-specific send attempt exists.
Browser-local routing tool
Locate the requester notification boundary
Select bounded states only. No email address, ticket content, solution, message identifier, user ID, credential, token or mailbox data is requested or transmitted.
- First boundary
- Next action
- Exit condition
- Safety rule
What the current Bileto source shows
Bileto issue 1054 reports the exact split: the requester receives the ticket-creation email, an observer receives the solution email, and the requester does not. The report also notes that the SMTP sender account and requester address are the same.
In reviewed main revision 3981abb122e031db0b9c1838d7c9656b55460a5f, NotificationsSubscriber dispatches creation receipts and message notifications through different handlers. SendMessageEmailHandler adds the requester only when the requester user object is not the message author; it applies the same author exclusion independently to observers and the assignee. The configured MAILER_FROM is applied later, after recipient selection.
That source makes one test especially valuable: compare the resolution message author and requester IDs. If they match, the requester is intentionally omitted before Symfony Mailer sees the message. A separate-agent resolution is the clean control.
Five boundaries that must stay separate
- Business event. The ticket is resolved and one immutable resolution message exists.
- Recipient selection. Requester, observers and assignee are evaluated independently, with every exclusion reason recorded as a bounded role state.
- Dispatch and worker. One idempotent notification command reaches a running handler or a visible failure transport.
- Transport and provider. Each selected recipient produces a send result or bounded exception. A successful observer attempt cannot stand in for a missing requester attempt.
- Receiver and mailbox. Provider acceptance, receiving-server acceptance and inbox visibility remain different outcomes.
Minimal evidence contract
resolution:<opaque-id>
committed: true
authorRole: requester | agent | system
recipientSelection:
requester: selected | excluded_author | excluded_anonymized | excluded_policy
observer: selected | excluded_author | excluded_policy
requesterNotification:
not_selected | queued | sending | provider_accepted
| recipient_accepted | delivered | delayed | bounced | failed
Invariant: one actor's delivery never proves another actor was selected.
Use opaque internal references in private logs and expose only bounded states in public diagnostics. Do not put ticket subjects, addresses, solution text, SMTP credentials or complete provider payloads into an issue.
Controlled tests before changing SMTP
- Create a ticket where requester and resolving agent are different user records. Add one observer and resolve it once.
- Assert the requester and observer are both selected before dispatch, then assert exactly one send attempt for each.
- Create a second ticket where the requester authors the resolution. Assert the current product rule explicitly: either self-notification is excluded or one requester copy is required.
- Make the requester transport attempt fail while the observer succeeds. Prove retries are per recipient and do not resend the observer copy.
- Route notification commands asynchronously. Stop the worker, prove the requester job remains queued, then recover it once without changing ticket state.
- After provider acceptance, preserve a requester-specific message identifier and follow delayed, bounced, blocked or delivered events separately.
Continue from provider acceptance to receiving-server and mailbox evidence without entering an address, ticket or credential.
Primary references
- Bileto issue 1054: requester receives creation but not resolution email
- Bileto notification event subscriber at the reviewed revision
- Bileto per-actor recipient selection at the reviewed revision
- Bileto requester notification test at the reviewed revision
- Symfony Mailer transport, failure and async delivery documentation
- Symfony Messenger queue, retry and failure-transport documentation