BuildReferencesChain returns the References chain to write on a reply, per RFC 5322 § 3.6.4: - If the parent has a References header, return: parent.References ++ [parentMsgID] - Else if the parent has an In-Reply-To header, return: parent.InReplyTo ++ [parentMsgID] - Else return: [parentMsgID] (th
(rawMessage []byte, parentMsgID string)
| 87 | // has In-Reply-To pointing at a Message-ID that recipients outside the |
| 88 | // subset have never seen, and Gmail/other clients fork the thread. |
| 89 | func BuildReferencesChain(rawMessage []byte, parentMsgID string) []string { |
| 90 | if parentMsgID == "" { |
| 91 | return nil |
| 92 | } |
| 93 | |
| 94 | var prior []string |
| 95 | if len(rawMessage) > 0 { |
| 96 | if msg, err := mail.ReadMessage(bytes.NewReader(rawMessage)); err == nil { |
| 97 | if refs := strings.TrimSpace(msg.Header.Get("References")); refs != "" { |
| 98 | prior = parseMessageIDList(refs) |
| 99 | } else if irt := strings.TrimSpace(msg.Header.Get("In-Reply-To")); irt != "" { |
| 100 | // In-Reply-To SHOULD contain a single id, but some clients |
| 101 | // pack multiple. Treat it the same way as References as a |
| 102 | // pragmatic recovery — better than dropping prior context. |
| 103 | prior = parseMessageIDList(irt) |
| 104 | } |
| 105 | } |
| 106 | // Parse failures fall through silently — better to send a reply |
| 107 | // with a shorter chain than to fail the whole send. The reply |
| 108 | // will still thread for participants who saw the parent. |
| 109 | } |
| 110 | |
| 111 | chain := make([]string, 0, len(prior)+1) |
| 112 | for _, id := range prior { |
| 113 | // Drop the parent if it was already in the prior chain — append it |
| 114 | // once at the end so the chain ends with the immediate parent |
| 115 | // (which mirrors what In-Reply-To points at). |
| 116 | if id != parentMsgID { |
| 117 | chain = append(chain, id) |
| 118 | } |
| 119 | } |
| 120 | chain = append(chain, parentMsgID) |
| 121 | return chain |
| 122 | } |
| 123 | |
| 124 | // parseMessageIDList splits a References / In-Reply-To header value into |
| 125 | // individual message-ids. The header format is one or more <local@domain> |