fix(email): assert the SMTP rejection structurally, not on textproto's text

Go 1.26 changed net/textproto.Error.Error() to quote the message
("%03d %q"), so the rejection renders as `501 "5.5.4 Rejected!"` and the
substring match on `501 5.5.4 Rejected!` no longer holds. TestEmailRejected
has been failing on this toolchain ever since.

Unwrap to the *textproto.Error and assert Code and Msg instead. That is
stronger than the substring it replaces — it pins the numeric code and the
exact message rather than a fragment of a formatted string — and it does
not depend on how the stdlib renders the error.

The second failure in the same test was a cascade: the require above
aborted the test before srv.Shutdown ran, so the cleanup's ErrServerClosed
check saw a nil error from its own first shutdown.

go test ./...: 130 ok / 1 FAIL -> 131 ok / 0 FAIL.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
hanzo-dev
2026-07-27 10:53:15 -07:00
parent 7a57e6e02e
commit ef13a025e8
@@ -11,6 +11,7 @@ import (
"log/slog"
"net"
"net/http"
"net/textproto"
"net/url"
"os"
"strconv"
@@ -719,7 +720,13 @@ func TestEmailRejected(t *testing.T) {
// Send the alert to mock SMTP server.
retry, err := e.Notify(context.Background(), firingAlert)
require.ErrorContains(t, err, "501 5.5.4 Rejected!")
// net/smtp surfaces the rejection as *textproto.Error. Assert on its fields rather
// than on the rendered text: Go 1.26 changed textproto.Error.Error to quote the
// message ("%03d %q"), so matching the formatted string is toolchain-dependent.
var protoErr *textproto.Error
require.ErrorAs(t, err, &protoErr)
require.Equal(t, 501, protoErr.Code)
require.Equal(t, "5.5.4 Rejected!", protoErr.Msg)
require.True(t, retry)
require.NoError(t, srv.Shutdown(ctx))