Billionmail/BillionMail · error
failed to update postfix master config: %v
Error message
failed to update postfix master config: %v
What it means
After reading master.cf, SetPostfixMasterSSL uses gregex.ReplaceString to uncomment '-o smtpd_tls_auth_only=yes'. This error is returned when the regex engine itself fails (invalid pattern or replacement), before any write occurs.
Source
Thrown at core/internal/service/mail_service/certificate.go:170
if err := c.restartPostfix(); err != nil {
return err
}
return nil
}
// SetPostfixMasterSSL enables SSL for Postfix Master
func (c *Certificate) SetPostfixMasterSSL() error {
// Read Postfix Master configuration
content, err := public.ReadFile(consts.POSTFIX_MASTER_CONF)
if err != nil {
return fmt.Errorf("failed to read postfix master config: %v", err)
}
content, err = gregex.ReplaceString(`\n*#\s*-o\s+smtpd_tls_auth_only=yes`, "\n -o smtpd_tls_auth_only=yes", content)
if err != nil {
return fmt.Errorf("failed to update postfix master config: %v", err)
}
content, err = gregex.ReplaceString(`\n*#\s*-o\s+smtpd_tls_wrappermode=yes`, "\\n -o smtpd_tls_wrappermode=yes", content)
if err != nil {
return fmt.Errorf("failed to update postfix master config: %v", err)
}
// Update Postfix Master configuration
if err := os.WriteFile(c.PostfixMasterConf, []byte(content), 0755); err != nil {
return fmt.Errorf("failed to write postfix master config: %v", err)
}
return nil
}
// SetDovecotSSL configures SSL certificate for Dovecot
func (c *Certificate) SetDovecotSSL(csrPem, keyPem string) error {View on GitHub (pinned to fc36c76c05)
Solutions
- Upgrade/verify the GoFrame gregex dependency version
- Replace the two regex calls with plain strings.Replace for these fixed strings, eliminating regex errors entirely
- Reproduce with a small test calling gregex.ReplaceString with the same pattern
Example fix
// before
content, err = gregex.ReplaceString(`\n*#\s+-o\s+smtpd_tls_auth_only=yes`, "\n -o smtpd_tls_auth_only=yes", content)
if err != nil {
return fmt.Errorf("failed to update postfix master config: %v", err)
}
// after
content = strings.ReplaceAll(content, "# -o smtpd_tls_auth_only=yes", " -o smtpd_tls_auth_only=yes") Defensive patterns
Strategy: try-catch
Try / catch
if err := certService.SetPostfixMasterSSL(); err != nil {
if strings.Contains(err.Error(), "failed to update postfix master config") {
log.Errorf("regex rewrite of master.cf failed: %s", err)
return fmt.Errorf("could not enable smtpd_tls_auth_only; pin/upgrade gregex: %w", err)
}
return err
} Prevention
- Prefer strings.ReplaceAll over regex for fixed strings in master.cf
- Pin and test the GoFrame version in CI
- Add a unit test that runs the replacement against a sample master.cf
When it happens
Trigger: gregex.ReplaceString returning an error on the pattern `\n*#\s+-o\s+smtpd_tls_auth_only=yes` — practically rare since the pattern is static; typically only seen if the GoFrame regex dependency misbehaves.
Common situations: Corrupted or incompatible gregex/GoFrame version after an upgrade; panic-level bug surfaced as error from the regex call.
Related errors
- Failed to get configuration
- supplier configuration not found
- Prefix validation error: %w
- failed to read postfix master config: %v
- failed to read postfix config: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/6601aff70d2ccb6b.
Report an issue: GitHub.