{"record":{"id":"0318bd37bb33bd98","repo":"Billionmail/BillionMail","slug":"base64-decode-failed-w","errorCode":null,"errorMessage":"base64 decode failed: %w","messagePattern":"base64 decode failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/mail_service/sending.go","lineNumber":168,"sourceCode":"\treturn\n}\n\n// PasswordPlainByEmail\nfunc PasswordPlainByEmail(ctx context.Context, email string) (string, error) {\n\tval, err := g.DB().Model(\"mailbox\").Where(\"username\", email).Value(\"password_encode\")\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"query password failed: %w\", err)\n\t}\n\tif val.IsEmpty() {\n\t\treturn \"\", fmt.Errorf(\"password not found for %s\", email)\n\t}\n\trawHex, err := hex.DecodeString(val.String())\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"hex decode failed: %w\", err)\n\t}\n\tplainBytes, err := base64.StdEncoding.DecodeString(string(rawHex))\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"base64 decode failed: %w\", err)\n\t}\n\treturn string(plainBytes), nil\n}\n\n// Close closes the SMTP connection\nfunc (e *EmailSender) Close() {\n\t_ = e.Disconnect()\n}\n\n// Connect establishes an SMTP connection\nfunc (e *EmailSender) Connect() error {\n\te.mutex.Lock()\n\tdefer e.mutex.Unlock()\n\n\tif e.connected && e.client != nil {\n\t\t// Connection already exists\n\t\treturn nil\n\t}","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/mail_service/sending.go#L150-L186","documentation":"After successful hex decoding, the bytes are expected to be base64-encoded plaintext. base64.StdEncoding.DecodeString fails on characters outside the base64 alphabet, wrong padding, or invalid length, yielding 'base64 decode failed' with the underlying error wrapped via %w.","triggerScenarios":"PasswordPlainByEmail decodes a value that was hex-valid but whose payload is not base64 — e.g. the column stores hex(plaintext) instead of hex(base64(plaintext)), or padding was lost.","commonSituations":"Double-encoding mistake when seeding data manually; migration script encoded only once instead of twice; value written by a different tool with a different scheme.","solutions":["Decode the hex payload and check whether it already looks like plaintext — if so, the base64 step was skipped when storing; re-store as hex(base64(pw)).","Reset the mailbox password through the application so it is encoded with the current scheme.","Ensure any import/migration script applies hex(base64(password)), matching the code path in PasswordPlainByEmail.","Inspect padding/length of the base64 payload; malformed padding causes DecodeString failure."],"exampleFix":"// before\nenc := hex.EncodeToString([]byte(password)) // wrong: single encoding\n// after\nb64 := base64.StdEncoding.EncodeToString([]byte(password))\nenc := hex.EncodeToString([]byte(b64))","handlingStrategy":"validation","validationCode":"v, err := g.DB().Model(\"mailbox\").Where(\"username\", email).Value(\"password_encode\")\nif err == nil && !v.IsEmpty() {\n    raw, _ := hex.DecodeString(v.String())\n    if _, berr := base64.StdEncoding.DecodeString(string(raw)); berr != nil {\n        return fmt.Errorf(\"password_encode for %s is hex but not base64; re-store as hex(base64(pw))\", email)\n    }\n}","typeGuard":"func isHexOfBase64(s string) bool {\n    raw, err := hex.DecodeString(s)\n    if err != nil {\n        return false\n    }\n    _, err = base64.StdEncoding.DecodeString(string(raw))\n    return err == nil\n}","tryCatchPattern":"pass, err := PasswordPlainByEmail(ctx, email)\nif err != nil {\n    var b64Err base64.CorruptInputError\n    if errors.As(err, &b64Err) {\n        return fmt.Errorf(\"mailbox %s password mis-encoded (missing base64 layer); reset password\", email)\n    }\n    return err\n}","preventionTips":["Apply the full hex(base64(password)) encoding in any migration/import script.","Add a round-trip test that encodes then decodes a sample password.","Reset passwords that predate an encoding-scheme change."],"tags":["encoding","base64","password","data-format"],"backgroundTag":"invalid-base64-encoding","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}