Which email was this a reply to? Reconstructing a thread with missing messages

Two messages can have the same subject without either replying to the other. A reply can also have a completely different subject from its parent. If you have permission to examine a set of original email files, start with a narrower question: which earlier message does this file actually name as its parent, and do I have a copy?

Two blue envelopes in a wooden tray with an empty compartment, and a separate orange envelope
Illustration generated for this article. An empty slot represents a referenced message whose file is unavailable.

Give every file its own row

Work on copies of the original messages, typically exported as .eml. A screenshot of a conversation or a quoted passage in a forwarded message does not give you the original headers for each message it shows. Keep the filename and a hash of the original bytes; two exports can have the same message identifier without being identical files.

Look above the first blank line in the raw message. A header can continue on the next indented line; read its continuation too. Copy the full values, including the domain in each identifier. Three fields answer different questions:

  • Message-ID: What identifier does this message use for itself?
  • In-Reply-To: Which message ID or IDs does this message name as its direct parent or parents? Match each against the Message-ID column of your file inventory.
  • References: Which identifiers were carried along as thread history? Preserve their order. In an ordinary single-parent reply, the reply usually inherits the parent’s references and appends the parent’s own ID. The entire list is not a set of direct parents.

Reply-To serves a different purpose: it suggests where a response should be sent. It cannot tell you which message was answered. For the separate question of sender authentication and mail relays, see how to read an email header.

A missing parent you can name but cannot read

Fictional exercise. We generated four local email files and parsed their headers. The letters below stand for distinct IDs in the reserved domain case.example. C stands for <missing.3@case.example>; no file in the set has that Message-ID.

File / IDSubjectIn-Reply-ToReferences, in order
ALoading bayAbsentAbsent
BDelivery windowAA
DRe: Delivery windowCA, B, C
ELoading bayAbsentAbsent

Draw one solid line from B to A: B names A, and you have a file with A’s ID, despite the change of subject. D names C, so put an empty box marked C next to D. Joining D straight to B would erase the one parent D actually names. The reference to B is useful context, but it does not supply C’s words. Leave E without a line: the repeated subject gives you a search lead, not a header match. A blank field also cannot prove that a message began a conversation.

Report the gap in a way someone else can check

For each declared parent, record one of three findings: one matching file, no matching file in this set, or multiple candidate files. Keep files with conflicting IDs or circular links visible for review. If only References survives, note a possible relationship separately and say which field suggested it. A mail app can group messages differently; for example, Gmail documents splitting conversations when the subject changes.

A useful request for more evidence is specific: “D’s In-Reply-To names <missing.3@case.example>. Does the authorized export contain a message with that Message-ID?” This identifies what would close the gap. The headers alone do not establish who typed the messages, whether they arrived, or why C is absent.

Field definitions and reply construction: RFC 5322, identification fields. To reproduce a header inventory from saved bytes, Python documents BytesParser and its parsing policies.

By OSINT Jet · Primary sources reviewed 7 November 2026.