Add verified snapshots and harden archive identity

This commit is contained in:
DonVoo 2026-07-17 00:37:02 +02:00
parent c6de214ac8
commit 68b9cee880
9 changed files with 1372 additions and 52 deletions

View file

@ -31,10 +31,13 @@ type RawMessage struct {
// for byte-different messages. Messages without a Message-ID are identified by
// BodySHA256 alone. LegacyMessageID keeps the old raw-IMAP hash addressable
// while existing databases are migrated without re-copying mail.
// LegacyMessageIDs additionally retain historical Message-ID normalizations
// from both the IMAP envelope and the raw RFC-822 header.
type MessageIdentity struct {
MessageID string
BodySHA256 string
LegacyMessageID string
MessageID string
BodySHA256 string
LegacyMessageID string
LegacyMessageIDs []string
}
type MessageHeader struct {
@ -489,19 +492,23 @@ func messageID(body []byte) string {
func identityForRawMessage(m RawMessage) MessageIdentity {
id := normalizeMessageID(m.MessageID)
legacyID := id
legacyID := legacyNormalizeMessageID(m.MessageID)
aliases := []string{legacyID}
if strings.HasPrefix(strings.ToLower(id), "sha256:") {
id = ""
}
if id == "" {
if msg, err := mail.ReadMessage(bytes.NewReader(m.Body)); err == nil {
id = normalizeMessageID(msg.Header.Get("Message-ID"))
if msg, err := mail.ReadMessage(bytes.NewReader(m.Body)); err == nil {
headerID := msg.Header.Get("Message-ID")
aliases = append(aliases, normalizeMessageID(headerID), legacyNormalizeMessageID(headerID))
if id == "" {
id = normalizeMessageID(headerID)
}
}
return MessageIdentity{
MessageID: id,
BodySHA256: bodySHA256(m.Body),
LegacyMessageID: legacyID,
MessageID: id,
BodySHA256: bodySHA256(m.Body),
LegacyMessageID: legacyID,
LegacyMessageIDs: aliases,
}
}
@ -525,6 +532,18 @@ func bodySHA256(raw []byte) string {
}
func normalizeMessageID(id string) string {
id = strings.TrimSpace(id)
if start := strings.IndexByte(id, '<'); start >= 0 {
if relativeEnd := strings.IndexByte(id[start+1:], '>'); relativeEnd >= 0 {
if candidate := strings.TrimSpace(id[start+1 : start+1+relativeEnd]); candidate != "" {
return candidate
}
}
}
return strings.Trim(id, "<>")
}
func legacyNormalizeMessageID(id string) string {
return strings.Trim(strings.TrimSpace(id), "<>")
}