Mail-Graveyard/backend/04-imap-source_test.go

107 lines
3.8 KiB
Go

package backend
import (
"strings"
"testing"
"github.com/emersion/go-imap/v2"
)
func TestSanitizeIMAPFlagsDropsRecentAndWildcard(t *testing.T) {
got := sanitizeIMAPFlags([]imap.Flag{imap.FlagSeen, imap.Flag(`\Recent`), imap.FlagWildcard, imap.FlagAnswered})
if len(got) != 2 || got[0] != imap.FlagSeen || got[1] != imap.FlagAnswered {
t.Fatalf("sanitizeIMAPFlags returned %#v", got)
}
}
func TestMessageIDFallsBackToBodyHash(t *testing.T) {
body := []byte("From: a@example.com\r\nSubject: Test\r\n\r\nBody")
id := messageID(body)
if !strings.HasPrefix(id, "sha256:") {
t.Fatalf("expected sha256 fallback, got %q", id)
}
if id != messageID(body) {
t.Fatal("messageID hash fallback is not stable")
}
}
func TestNormalizeMessageIDExtractsBracketedIDBeforeBrokenComment(t *testing.T) {
tests := map[string]string{
"<normal@example.com>": "normal@example.com",
"bracketless@example.com": "bracketless@example.com",
" <5486CB7400AF1FB7@mr001msb.fastweb.it> (added by postmaster) ": "5486CB7400AF1FB7@mr001msb.fastweb.it",
"comment <embedded@example.com> trailing": "embedded@example.com",
}
for input, want := range tests {
if got := normalizeMessageID(input); got != want {
t.Errorf("normalizeMessageID(%q)=%q, want %q", input, got, want)
}
}
}
func TestIdentityKeepsOldMalformedHeaderNormalizationAsAlias(t *testing.T) {
tests := []struct {
header string
clean string
legacy string
}{
{
header: `<476BDFDB019289BE@mail21.bluewin.ch> (added by postmaster@bluewin.ch)`,
clean: `476BDFDB019289BE@mail21.bluewin.ch`,
legacy: `476BDFDB019289BE@mail21.bluewin.ch> (added by postmaster@bluewin.ch)`,
},
{
header: `<22578196653698419217.BB8A0E8F48F3F290@dr-gold.de>+D271B1409C3C6028`,
clean: `22578196653698419217.BB8A0E8F48F3F290@dr-gold.de`,
legacy: `22578196653698419217.BB8A0E8F48F3F290@dr-gold.de>+D271B1409C3C6028`,
},
}
for _, tt := range tests {
body := []byte("Message-ID: " + tt.header + "\r\nSubject: malformed ID\r\n\r\nbody")
identity := identityForRawMessage(RawMessage{MessageID: messageID(body), Body: body})
if identity.MessageID != tt.clean {
t.Fatalf("MessageID=%q, want %q", identity.MessageID, tt.clean)
}
found := false
for _, alias := range identity.LegacyMessageIDs {
if alias == tt.legacy {
found = true
break
}
}
if !found {
t.Fatalf("legacy alias %q missing from %#v", tt.legacy, identity.LegacyMessageIDs)
}
}
}
func TestBodySHA256IsStableAcrossMboxNormalization(t *testing.T) {
raw := []byte("From: a@example.com\r\nSubject: Test\r\n\r\nFirst\r\nFrom escaped\r\n\r\n")
record := mboxRecord(RawMessage{Body: raw})
parts := splitMboxRecordsWithOffsets(record)
if len(parts) != 1 {
t.Fatalf("mbox parts=%d, want 1", len(parts))
}
if got, want := bodySHA256(parts[0].Message), bodySHA256(raw); got != want {
t.Fatalf("mbox hash=%s, raw hash=%s", got, want)
}
}
func TestIdentityUsesMessageIDAndBodyHash(t *testing.T) {
first := identityForRawMessage(RawMessage{MessageID: "<same@example.com>", Body: []byte("Message-ID: <same@example.com>\r\n\r\nfirst")})
second := identityForRawMessage(RawMessage{MessageID: "<same@example.com>", Body: []byte("Message-ID: <same@example.com>\r\n\r\nsecond")})
if first.MessageID != second.MessageID {
t.Fatalf("message IDs differ: %#v %#v", first, second)
}
if first.BodySHA256 == second.BodySHA256 {
t.Fatalf("different bodies have same identity hash: %#v %#v", first, second)
}
}
func TestIdentityWithoutMessageIDKeepsLegacyRawHash(t *testing.T) {
body := []byte("From: a@example.com\r\n\r\nbody")
identity := identityForRawMessage(RawMessage{MessageID: messageID(body), Body: body})
if identity.MessageID != "" || identity.BodySHA256 == "" || !strings.HasPrefix(identity.LegacyMessageID, "sha256:") {
t.Fatalf("unexpected identity: %#v", identity)
}
}