Skip to content

feat(inbound): wire Message_Id_Util parse + verify into InboundEmailService#33

Open
mpge wants to merge 1 commit intofeat/email-service-wireupfrom
feat/inbound-reply-to-verify
Open

feat(inbound): wire Message_Id_Util parse + verify into InboundEmailService#33
mpge wants to merge 1 commit intofeat/email-service-wireupfrom
feat/inbound-reply-to-verify

Conversation

@mpge
Copy link
Copy Markdown
Member

@mpge mpge commented Apr 24, 2026

Summary

Wires Message_Id_Util (added in #31) + Email_Threading::get_inbound_secret (added in #32) into InboundEmailService::find_ticket_by_email so inbound mail routes to the correct ticket via canonical Message-ID parsing + signed Reply-To verification.

Resolution order

  1. In-Reply-To parsed via Message_Id_Util::parse_ticket_id_from_message_id — cold-start path, no DB lookup required.
  2. References parsed via Message_Id_Util, each id in order.
  3. Signed Reply-To on message['toEmail'] (reply+{id}.{hmac8}@...) verified via Message_Id_Util::verify_reply_to. Survives clients that strip our threading headers; forged signatures are rejected.
  4. Subject line reference tag (legacy).
  5. inbound_emails.message_id lookup for any header id (weakest fallback).

Extracts the header-id collection into a candidate_header_message_ids() helper so branches 1-2 and 5 share the same In-Reply-To + References parsing logic.

Dependencies

Test plan

  • 7 new WP integration tests cover every resolution strategy, forged-signature rejection, blank-secret skip path, and no-match fallback (run via WP test harness)
  • CI green (won't trigger against stacked base until rebased)

…ervice

Wires Message_Id_Util (#31) + Email_Threading::get_inbound_secret (#32)
into InboundEmailService::find_ticket_by_email so inbound mail routes
to the correct ticket via canonical Message-ID parsing + signed
Reply-To verification.

Resolution order (first match wins):
  1. In-Reply-To parsed via Message_Id_Util — cold-start path, no
     DB lookup required.
  2. References parsed via Message_Id_Util, each id in order.
  3. Signed Reply-To on message['toEmail']
     (reply+{id}.{hmac8}@...) verified via Message_Id_Util. Survives
     clients that strip our threading headers; forged signatures are
     rejected.
  4. Subject line reference tag (legacy).
  5. inbound_emails.message_id lookup for any header id (weakest
     fallback).

Extracts the header-id collection into a
candidate_header_message_ids() helper so branches 1-2 and 5 share
the same In-Reply-To + References parsing logic.

7 new WP integration tests cover every resolution strategy, the
forged-signature rejection, the blank-secret skip path, and the
no-match fallback.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant