Billionmail/BillionMail · error
SMTP write: %w
Error message
SMTP write: %w
What it means
This error wraps a failure writing the raw message bytes to the DATA-phase io.WriteCloser returned by smtp.Client.Data(). The message body could not be transmitted over the connection, so delivery of this message fails. Typically caused by the connection being closed or reset mid-DATA by the peer.
Source
Thrown at core/internal/service/mail_service/sending.go:434
// Set the recipients
// RCPT TO
for _, to := range recipients {
if err = e.client.Rcpt(to); err != nil {
return fmt.Errorf("SMTP rcpt: %w", err)
}
}
// Get a writer for the message body
var w io.WriteCloser
w, err = e.client.Data()
if err != nil {
return fmt.Errorf("SMTP data: %w", err)
}
// Write the message
if _, err = w.Write(msg); err != nil {
return fmt.Errorf("SMTP write: %w", err)
}
// Close the writer
if err = w.Close(); err != nil {
return fmt.Errorf("SMTP close writer: %w", err)
}
return nil
}
// isSecure check if TLS connection is needed
func (e *EmailSender) isSecure() bool {
// usually,
// port 465 is used for SMTP with SSL (implicit TLS)
// port 587 is used for SMTP with STARTTLS (explicit TLS)
if e.Port == "465" {
return true
} else if e.Port == "587" {View on GitHub (pinned to fc36c76c05)
Solutions
- Check mail logs for connection loss or size-limit rejections; raise message_size_limit if large mails are intended
- Retry the send on a new connection; the write failure is usually terminal for the session
- Verify stable network path and TLS handshake health between app and SMTP server
- Check for line-dot-escaping issues in msg content that could corrupt the DATA stream
Defensive patterns
Strategy: retry
Validate before calling
if len(msg) > maxSupportedSize { // match server message_size_limit
return errors.New("message exceeds size limit")
} Try / catch
err := sender.Send(msg, recipients)
if err != nil && strings.Contains(err.Error(), "SMTP write") {
// session is dead; reconnect and retry once
conn = reconnect()
err = sender.Send(msg, recipients)
} Prevention
- Keep message sizes under the server's message_size_limit
- Ensure stable network/TLS path to the SMTP server
- Detect dead connections early with TCP keepalives
- Retry on a fresh connection; a failed DATA write cannot be resumed
When it happens
Trigger: w.Write(msg) returned an error because the TCP connection was closed/reset by the server while streaming the message body, a TLS error occurred mid-stream, or the message exceeded size limits and the server aborted.
Common situations: Very large messages exceeding message_size_limit cause the server to drop the connection; unstable network between client and mail server; Postfix anvil or proxy timeouts on slow writers.
Related errors
- SMTP server is required
- SMTP port must be between 1 and 65535
- SMTP password is required
- at least one recipient is required
- %s
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/344f530e7fd4c5ad.
Report an issue: GitHub.