{"record":{"id":"ee5905df09a29ecc","repo":"Billionmail/BillionMail","slug":"smtp-auth-w","errorCode":null,"errorMessage":"SMTP auth: %w","messagePattern":"SMTP auth: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/mail_service/sending.go","lineNumber":226,"sourceCode":"\tconn, err := tls.Dial(\"tcp\", net.JoinHostPort(e.Host, e.Port), &tls.Config{\n\t\tMinVersion:         tls.VersionTLS12,\n\t\tInsecureSkipVerify: true,\n\t\tServerName:         e.SNI,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"TLS dial: %w\", err)\n\t}\n\n\tclient, err := smtp.NewClient(conn, e.Host)\n\tif err != nil {\n\t\tconn.Close()\n\t\treturn fmt.Errorf(\"new SMTP client: %w\", err)\n\t}\n\n\tauth := smtp.PlainAuth(\"\", e.UserName, e.Password, e.Host)\n\tif err = client.Auth(auth); err != nil {\n\t\tclient.Close()\n\t\treturn fmt.Errorf(\"SMTP auth: %w\", err)\n\t}\n\n\te.client = client\n\n\treturn nil\n}\n\n// connectPlain establishes a plain SMTP connection\nfunc (e *EmailSender) connectPlain() error {\n\tclient, err := smtp.Dial(net.JoinHostPort(e.Host, e.Port))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"SMTP dial: %w\", err)\n\t}\n\n\t// Check if STARTTLS is needed\n\tif e.Port == \"587\" {\n\t\tif err = client.StartTLS(&tls.Config{\n\t\t\tMinVersion:         tls.VersionTLS12,","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/mail_service/sending.go#L208-L244","documentation":"This error is returned when client.Auth(smtp.PlainAuth(...)) fails during connectWithSSL — the server rejected authentication with a 5xx reply (e.g. 535 authentication failed) or the AUTH mechanism is unsupported. The client is closed before returning so the connection is not leaked. The wrapped error carries the SMTP server response text, which names the exact cause.","triggerScenarios":"Connect() on a secure (implicit TLS) EmailSender where e.UserName/e.Password are wrong, the server does not advertise PLAIN auth, or the server requires a different mechanism (LOGIN, XOAUTH2, CRAM-MD5).","commonSituations":"Expired or revoked SMTP password / app password (Gmail requires app passwords with 2FA); username must be the full email address but only the local part was configured; provider disabled basic auth entirely (e.g. Microsoft deprecating basic AUTH); account locked or sending IP blocked.","solutions":["Read the wrapped server reply (e.g. '535 5.7.8 Bad credentials') and fix the credentials in the sender configuration.","Use the full email address as the username; for Gmail/Yahoo use an app-specific password.","Check the server's advertised AUTH mechanisms in the EHLO response (openssl s_client -connect host:465 or swaks --auth) and match the mechanism.","If the server requires LOGIN auth, implement/switch to an smtp.Auth that speaks LOGIN (the codebase's customAuth does this for port 25; adapt as needed)."],"exampleFix":"// before\nauth := smtp.PlainAuth(\"\", e.UserName, e.Password, e.Host)\nif err = client.Auth(auth); err != nil {\n    client.Close()\n    return fmt.Errorf(\"SMTP auth: %w\", err)\n}\n// after\nauth := smtp.PlainAuth(\"\", e.UserName, e.Password, e.Host)\nif err = client.Auth(auth); err != nil {\n    client.Close()\n    if strings.Contains(err.Error(), \"535\") {\n        return fmt.Errorf(\"SMTP auth: invalid credentials for %s (check password/app-password): %w\", e.Host, err)\n    }\n    return fmt.Errorf(\"SMTP auth: %w\", err)\n}","handlingStrategy":"validation","validationCode":"func validateCredentials(user, pass, host, port string) error {\n    conn, err := smtp.Dial(net.JoinHostPort(host, port))\n    if err != nil {\n        return err\n    }\n    defer conn.Close()\n    if err := conn.StartTLS(&tls.Config{ServerName: host}); err != nil {\n        return err\n    }\n    ok, mechs := conn.Extension(\"AUTH\")\n    if !ok {\n        return fmt.Errorf(\"server %s does not advertise AUTH\", host)\n    }\n    _ = mechs // check it includes PLAIN/LOGIN before configuring\n    return conn.Auth(smtp.PlainAuth(\"\", user, pass, host))\n}","typeGuard":"func isAuthRejected(err error) bool {\n    var protoErr *textproto.Error\n    return errors.As(err, &protoErr) && protoErr.Code >= 500 && protoErr.Code < 600\n}","tryCatchPattern":"if err := sender.Send(msg, rcpts); err != nil {\n    if strings.Contains(err.Error(), \"SMTP auth\") {\n        // do not blind-retry: credentials are wrong; surface to config UI\n        return ErrBadCredentials\n    }\n}","preventionTips":["Store and test credentials at config time, not first send.","Use the full email address as the SMTP username; use app passwords for Gmail/Yahoo.","Confirm the server's AUTH mechanisms include PLAIN before relying on smtp.PlainAuth."],"tags":["smtp","auth","credentials","tls"],"backgroundTag":"smtp-auth-failed","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"}