{"record":{"id":"31403ea5cf0e49bd","repo":"Billionmail/BillionMail","slug":"invalid-dkim-record-format","errorCode":null,"errorMessage":"Invalid DKIM record format","messagePattern":"Invalid DKIM record format","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/domains/domains.go","lineNumber":670,"sourceCode":"\n\t// If the raw public key is read, format it into DNS TXT record format\n\tif !strings.Contains(dkimRecord, \"v=DKIM1\") && !strings.Contains(dkimRecord, \"k=rsa\") && !strings.Contains(dkimRecord, \"p=\") {\n\t\t// Remove possible header/footer markers and newlines\n\t\tdkimRecord = strings.ReplaceAll(dkimRecord, \"-----BEGIN PUBLIC KEY-----\", \"\")\n\t\tdkimRecord = strings.ReplaceAll(dkimRecord, \"-----END PUBLIC KEY-----\", \"\")\n\t\tdkimRecord = strings.ReplaceAll(dkimRecord, \"\\n\", \"\")\n\t\tdkimRecord = strings.TrimSpace(dkimRecord)\n\t\tdkimRecord = fmt.Sprintf(\"v=DKIM1; k=rsa; p=%s\", dkimRecord)\n\t} else {\n\t\tvar ms [][]string\n\t\tms, err = gregex.MatchAllString(`\"([^\"\\r\\n]+)\"`, dkimRecord)\n\t\tif err != nil {\n\t\t\terr = fmt.Errorf(\"Failed to parse DKIM record: %v\", err)\n\t\t\treturn\n\t\t}\n\n\t\tif len(ms) < 2 {\n\t\t\terr = fmt.Errorf(\"Invalid DKIM record format\")\n\t\t\treturn\n\t\t}\n\n\t\ts := \"\"\n\t\tfor _, v := range ms {\n\t\t\tif len(v) < 2 {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\ts += v[1]\n\t\t}\n\n\t\tdkimRecord = s\n\t}\n\n\trecord = v1.DNSRecord{\n\t\tType:  \"TXT\",\n\t\tHost:  selector + \"._domainkey\",\n\t\tValue: dkimRecord,","sourceCodeStart":652,"sourceCodeEnd":688,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/domains/domains.go#L652-L688","documentation":"Thrown when the quoted-segment regex matches fewer than 2 segments in the DKIM record text, meaning the content does not contain a properly wrapped multi-part DKIM record (quote-wrapped chunks including the p= key). The library expects rspamd's record format of multiple quoted lines.","triggerScenarios":"The dkimRecord string read from the key/record file has zero or one quoted section — e.g. file contains a raw base64 key (no quotes), an empty file, a single-line record, or hand-edited content without the standard quoted wrapping.","commonSituations":"Admin replaced the key file with a bare public key, a script wrote the key without quote-wrapping, key file truncated or empty after failed generation, or rspamd version emitting a differently formatted record.","solutions":["Regenerate the DKIM keys/config via RepairDKIMSigningConfig so the record is written in the expected quoted format","If storing a raw base64 key, ensure it is quote-wrapped per the expected format, or place it on the code path that prepends v=DKIM1; k=rsa; p= directly","Inspect the file at dkimPubPath and compare with a healthy domain's record format","Restore the file from a backup if it was hand-edited"],"exampleFix":"// before: bare key in record file fails the quoted parse\nMIIBIjANBgkqh...\n// after: expected quoted format\n\"v=DKIM1; k=rsa;\"\n\"p=MIIBIjANBgkqh...\"","handlingStrategy":"validation","validationCode":"if strings.Count(dkimRecord, \"\\\"\") < 4 {\n    return fmt.Errorf(\"DKIM record not quote-wrapped in expected format — regenerate via RepairDKIMSigningConfig\")\n}","typeGuard":"func isQuotedDKIMRecord(s string) bool {\n    return strings.Count(s, \"\\\"\") >= 4 && strings.Contains(s, \"p=\")\n}","tryCatchPattern":"if len(ms) < 2 {\n    log.Printf(\"invalid DKIM record format: %q — expected multiple quoted segments\", truncate(dkimRecord, 80))\n    return fmt.Errorf(\"Invalid DKIM record format\")\n}","preventionTips":["Store DKIM records only through the library's write path, preserving quoted wrapping","Snapshot key files before manual maintenance so a bad edit is recoverable","Diff a healthy domain's record format when troubleshooting"],"tags":["dkim","format","parsing","dns"],"backgroundTag":"invalid-dkim-record-format","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}