{"record":{"id":"4e3fd586a1cf1602","repo":"usememos/memos","slug":"smtp-server-does-not-support-starttls","errorCode":null,"errorMessage":"SMTP server does not support STARTTLS","messagePattern":"SMTP server does not support STARTTLS","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/email/client.go","lineNumber":103,"sourceCode":"\tdialer := &net.Dialer{Timeout: smtpOperationTimeout}\n\tconn, err := dialer.Dial(\"tcp\", serverAddr)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"failed to connect to SMTP server: %s\", serverAddr)\n\t}\n\tdefer conn.Close()\n\tif err := conn.SetDeadline(time.Now().Add(smtpOperationTimeout)); err != nil {\n\t\treturn errors.Wrap(err, \"failed to set SMTP connection deadline\")\n\t}\n\n\tclient, err := smtp.NewClient(conn, c.config.SMTPHost)\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to create SMTP client\")\n\t}\n\tdefer client.Quit()\n\n\tif c.config.UseTLS {\n\t\tif ok, _ := client.Extension(\"STARTTLS\"); !ok {\n\t\t\treturn errors.New(\"SMTP server does not support STARTTLS\")\n\t\t}\n\t\tif err := client.StartTLS(c.createTLSConfig()); err != nil {\n\t\t\treturn errors.Wrap(err, \"failed to start SMTP STARTTLS\")\n\t\t}\n\t}\n\n\treturn c.sendWithClient(client, auth, recipients, body)\n}\n\n// sendWithSSL sends email using SSL/TLS (port 465).\nfunc (c *Client) sendWithSSL(auth smtp.Auth, recipients []string, body string) error {\n\tserverAddr := c.config.GetServerAddress()\n\n\t// Create TLS connection\n\ttlsConfig := c.createTLSConfig()\n\tdialer := &net.Dialer{Timeout: smtpOperationTimeout}\n\tconn, err := tls.DialWithDialer(dialer, \"tcp\", serverAddr, tlsConfig)\n\tif err != nil {","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/usememos/memos/blob/14d757ce1fb31c78590f374bc042f8dbedbc20d7/internal/email/client.go#L85-L121","documentation":"Returned by Client's STARTTLS path (sendWithTLS in internal/email/client.go) when UseTLS is true but the server's EHLO response does not advertise the STARTTLS extension. The client refuses to send credentials and message body over a plaintext connection, so it aborts before authenticating.","triggerScenarios":"UseTLS=true against a server that only offers plaintext (port 25 relay without TLS) or that requires implicit TLS on 465; the EHLO extension list genuinely lacks STARTTLS. Also appears when a firewall/misconfigured proxy strips the extension or when the wrong port is used (465 expects SSL, not STARTTLS).","commonSituations":"Using UseTLS with port 465 instead of UseSSL; self-hosted relay (e.g., a local null client) with TLS disabled; corporate smarthost that only supports TLS on a different port; copy-pasted config mixing the STARTTLS and SSL flags.","solutions":["If the server is port 465 (implicit TLS), set UseSSL=true and UseTLS=false.","If using port 587, confirm the server actually supports STARTTLS: openssl s_client -starttls smtp -connect host:587 or 'swaks -tls'.","If the relay truly has no TLS, set UseTLS=false only over a trusted network (plaintext credentials otherwise).","Check for middleboxes/proxies stripping EHLO extensions and use the TLS-capable port the provider documents."],"exampleFix":"// before (465 with STARTTLS flag)\ncfg := email.Config{SMTPHost: \"smtp.example.com\", SMTPPort: 465, UseTLS: true}\n\n// after (465 uses implicit SSL)\ncfg := email.Config{SMTPHost: \"smtp.example.com\", SMTPPort: 465, UseSSL: true}","handlingStrategy":"validation","validationCode":"// Go — pick the TLS mode from the port before sending\nif cfg.SMTPPort == 465 {\n  cfg.UseSSL, cfg.UseTLS = true, false\n}\nif cfg.UseTLS {\n  // cheap capability probe avoids a wasted dial+auth attempt\n  conn, err := net.DialTimeout(\"tcp\", cfg.GetServerAddress(), 5*time.Second)\n  if err == nil {\n    conn.Close()\n  }\n}","typeGuard":null,"tryCatchPattern":"if err := client.Send(...); err != nil {\n  if strings.Contains(err.Error(), \"STARTTLS\") {\n    // either flip to UseSSL on 465, or pick a TLS-capable port; do NOT silently downgrade\n    return errors.Wrap(err, \"SMTP TLS mismatch: use UseSSL for port 465 or a STARTTLS-capable port\")\n  }\n  return err\n}","preventionTips":["Map flags to ports: 587 => UseTLS, 465 => UseSSL, and never both.","Verify with 'openssl s_client -starttls smtp -connect host:port' before deploying.","Never fall back to plaintext automatically when STARTTLS is missing — treat it as a config error."],"tags":["smtp","starttls","email","tls","configuration","go"],"backgroundTag":null,"analyzedSha":"14d757ce1fb31c78590f374bc042f8dbedbc20d7","analyzedAt":"2026-08-15T09:27:36.538Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}