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

  1. Check mail logs for connection loss or size-limit rejections; raise message_size_limit if large mails are intended
  2. Retry the send on a new connection; the write failure is usually terminal for the session
  3. Verify stable network path and TLS handshake health between app and SMTP server
  4. 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

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


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/344f530e7fd4c5ad. Report an issue: GitHub.