Billionmail/BillionMail · error
unexpected server response
Error message
unexpected server response
What it means
customAuth implements smtp.Auth for PLAIN. Its Next method refuses any server challenge (more == true), because PLAIN sends credentials once in Start and expects no further challenge. If the server keeps the SASL dialogue open, the client rejects it as 'unexpected server response'.
Solutions
- Verify username/password are correct — servers often re-challenge on bad credentials.
- Check the server's advertised AUTH mechanisms (EHLO) and use LOGIN auth if PLAIN isn't the negotiated mechanism.
- Ensure the connection uses TLS if the server only accepts AUTH after STARTTLS.
- If needed, implement a LOGIN customAuth instead of relying on this PLAIN-only implementation.
Example fix
// before
auth := &customAuth{Username: user, Password: pass}
// after
// confirm PLAIN is supported, else fall back
if serverAuths["PLAIN"] {
auth = &customAuth{Username: user, Password: pass}
} else {
auth = smtp.Plain("", user, pass) // or a LOGIN implementation
} Defensive patterns
Strategy: try-catch
Validate before calling
conn, _ := smtp.Dial(host + ":" + port)
defer conn.Close()
conn.Extension("AUTH") // returns mechanisms map; require "PLAIN"
conn.StartTLS(&tls.Config{ServerName: host}) Try / catch
if _, _, err := auth.Start(serverInfo); err == nil {
if _, err := auth.Next(nil, true); err != nil && err.Error() == "unexpected server response" {
// server re-challenged: wrong mechanism or bad credentials
return fmt.Errorf("PLAIN auth rejected by %s; check credentials and AUTH mechanism", host)
}
} Prevention
- EHLO first and confirm PLAIN is among advertised AUTH mechanisms.
- Always authenticate over TLS; some servers misbehave on plaintext AUTH.
- Test credentials with swaks/openssl s_client before wiring them in.
When it happens
Trigger: SMTP server answers the PLAIN auth with an additional challenge (334 prompt) instead of accepting, e.g. server expects a different mechanism (LOGIN/XOAUTH2) or rejects credentials while continuing the exchange.
Common situations: Authenticating to a server configured for LOGIN rather than PLAIN; wrong credentials causing the server to re-prompt; relay/MTA with non-standard SASL behavior.
Related errors
- Email Sender not configured
- failed to connect to SMTP server
- failed to send alert email to
- API key validation failed
- at least one recipient is required
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/37215c4bfa5c983e.
Report an issue: GitHub.
Appendix: source
Thrown at core/internal/service/mail_service/sending.go:113
Port string `json:"port" v:"required"` // SMTP server port
Password string `json:"password" v:"required"` // SMTP password
SNI string `json:"sni"` // SNI for TLS
client *smtp.Client // persistent SMTP client connection
mutex sync.Mutex // mutex for thread safety
connected bool // connection status
}
type customAuth struct {
Username, Password string
}
func (a *customAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
return "PLAIN", []byte("\x00" + a.Username + "\x00" + a.Password), nil
}
func (a *customAuth) Next(fromServer []byte, more bool) ([]byte, error) {
if more {
return nil, errors.New("unexpected server response")
}
return nil, nil
}
func NewEmailSender() *EmailSender {
e := &EmailSender{
Host: "localhost",
Port: "25",
connected: false,
}
if public.IsRunningInContainer() {
e.Host = "postfix"
// e.Port = "587"
// e.SNI, _ = public.DockerEnv("BILLIONMAIL_HOSTNAME")
}
return eView on GitHub (pinned to fc36c76c05)