Billionmail/BillionMail · warning

Failed to parse DKIM record: %v

Error message

Failed to parse DKIM record: %v

What it means

Thrown when the regex extracting quoted segments from the DKIM TXT record (grex: `"([^"]+)"`) fails to compile/match due to a regex engine error. This happens while normalizing an existing multi-line DKIM record read from rspamd back into a single-line record.

Source

Thrown at core/internal/service/domains/domains.go:665

	}

	// Format DKIM record
	// Expected format is a pre-formatted TXT record value like "v=DKIM1; k=rsa; p=MIIBIjANBg..."
	dkimRecord := strings.TrimSpace(dkimPub)

	// If the raw public key is read, format it into DNS TXT record format
	if !strings.Contains(dkimRecord, "v=DKIM1") && !strings.Contains(dkimRecord, "k=rsa") && !strings.Contains(dkimRecord, "p=") {
		// Remove possible header/footer markers and newlines
		dkimRecord = strings.ReplaceAll(dkimRecord, "-----BEGIN PUBLIC KEY-----", "")
		dkimRecord = strings.ReplaceAll(dkimRecord, "-----END PUBLIC KEY-----", "")
		dkimRecord = strings.ReplaceAll(dkimRecord, "\n", "")
		dkimRecord = strings.TrimSpace(dkimRecord)
		dkimRecord = fmt.Sprintf("v=DKIM1; k=rsa; p=%s", dkimRecord)
	} else {
		var ms [][]string
		ms, err = gregex.MatchAllString(`"([^"\r\n]+)"`, dkimRecord)
		if err != nil {
			err = fmt.Errorf("Failed to parse DKIM record: %v", err)
			return
		}

		if len(ms) < 2 {
			err = fmt.Errorf("Invalid DKIM record format")
			return
		}

		s := ""
		for _, v := range ms {
			if len(v) < 2 {
				continue
			}
			s += v[1]
		}

		dkimRecord = s
	}

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Inspect the DKIM key/record file content for corruption and regenerate keys via RepairDKIMSigningConfig
  2. Verify the content is plain ASCII with standard quoted record sections
  3. Upgrade/align GoFrame version if gregex behavior changed unexpectedly
  4. Add a pre-read sanity check that the file content looks like a DKIM record before regex parsing

Example fix

// before
ms, err = gregex.MatchAllString(`"([^
]+)"`, dkimRecord)
// after: guard with a quick sanity check
if !strings.Contains(dkimRecord, "v=DKIM1") && !strings.Contains(dkimRecord, "p=") {
    return fmt.Errorf("file does not look like a DKIM record; regenerate keys")
}
ms, err = gregex.MatchAllString(`"([^
]+)"`, dkimRecord)
Defensive patterns

Strategy: validation

Validate before calling

raw, _ := os.ReadFile(dkimPubPath)
if utf8.Valid(raw) && (strings.Contains(string(raw), "v=DKIM1") || strings.Contains(string(raw), "p=")) {
    // safe to regex-parse
}

Type guard

func looksLikeDKIMRecord(s string) bool {
    return strings.Contains(s, "v=DKIM1") || strings.Contains(s, "p=")
}

Try / catch

ms, err := gregex.MatchAllString(`"([^
]+)"`, dkimRecord)
if err != nil {
    log.Printf("DKIM record regex failure: %v — content may be corrupt; regenerate keys", err)
    return err
}

Prevention

When it happens

Trigger: gregex.MatchAllString returns an error on the raw dkimRecord content — effectively only on malformed regex invocation or pathological input handled by the engine; normal empty/no-match input yields len(ms)<2 (error 305) instead.

Common situations: Corrupted or binary content in the DKIM key file being parsed as a record, extremely long lines stressing the regex engine, or a GoFrame/gregex version regression in MatchAllString behavior.

Understand the failure class

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/11932bf1b6d19663. Report an issue: GitHub.