Skip to content

Error Registry

Winni Neessen edited this page Sep 12, 2025 · 1 revision

As of version 0.7.0, go-mail provides a custom error handling registry for the SMTP client, which allows users to handle protocol specific errors, i. e. for SMTP servers with non-RFC-complient responses.

This page provides a currated list of tested error registry handlers for known errors.

Known problematic providers/servers

Tencent (smtp.qq.com)

Problem description

In some cases, qq.com is known for sending back arbitrary binary data after issuing a QUIT command. Instead of the expected 221 Bye. response, the server will first send a sequence of binary bytes before finally issuing back the 221 Bye. response. Since the SMTP client makes use of net/textproto the binary data will cause a short response error and respectivly cause the QUIT command to throw and error. The provided error handler will inject itself into the QUIT command and check if the error holds the specific byte sequence. If the byte sequence matches, it will consume those bytes and return back to the SMTP client to handle the standard response.

Error handler code

// QQMailQuitErrorHandler handles the common error for smtp.qq.com that returns arbitrary binary data after
// the QUIT command, before returning the expected "221 Bye" response
type QQMailQuitErrorHandler struct{}

func (q *QQMailQuitErrorHandler) HandleError(_, _ string, conn *textproto.Conn, err error) error {
        var tpErr textproto.ProtocolError
        if errors.As(err, &tpErr) {
                if len(tpErr.Error()) < 16 {
                        return err
                }
                if !bytes.Equal([]byte(tpErr.Error()[16:]), []byte("\x00\x00\x00\x1a\x00\x00\x00")) {
                        return err
                }
                _, _ = io.ReadFull(conn.R, make([]byte, 8))
                return nil
        }
        return err
}

Registering and using the error handler

client, err := mail.NewClient("smtp.qq.com", mail.WithPort(465), mail.WithSSL())
if err != nil {
	log.Fatalf("failed to create client: %s\n", err)
}

qqMailQuitErrorHandler := &QQMailQuitErrorHandler{}
client.ErrorHandlerRegistry.RegisterHandler("smtp.qq.com", "QUIT", qqMailQuitErrorHandler)
Clone this wiki locally