mirror of
https://github.com/mjl-/mox.git
synced 2025-07-10 07:54:40 +03:00
in smtpclient, when delivering with pipelining, don't return a unhelpful read error when the remote server closes the connection early after writing an error response
e.g. when outlook.com puts your IP on a blocklist, it will respond with 550 to MAIL FROM, then closes the connection (without responding to the remaining commands). we were reading the 550 response, not yet acting on it, then reading the response to RCPT TO. that read failed, and we would return that error. now, we will properly return the 550 (permanent error, instead of the temporary read error) from the first MAIL FROM (but we do still always try to read the response for RCPT TO and DATA).
This commit is contained in:
@ -510,6 +510,30 @@ func TestErrors(t *testing.T) {
|
||||
panic(fmt.Errorf("got %#v, expected ErrStatus with Permanent", err))
|
||||
}
|
||||
})
|
||||
|
||||
// Remote closes connection after 550 response to MAIL FROM in pipelined
|
||||
// connection. Should result in permanent error, not temporary read error.
|
||||
// E.g. outlook.com that has your IP blocklisted.
|
||||
run(t, func(s xserver) {
|
||||
s.writeline("220 mox.example")
|
||||
s.readline("EHLO")
|
||||
s.writeline("250-mox.example")
|
||||
s.writeline("250 PIPELINING")
|
||||
s.readline("MAIL FROM:")
|
||||
s.writeline("550 ok")
|
||||
}, func(conn net.Conn) {
|
||||
c, err := New(ctx, log, conn, TLSOpportunistic, "", "")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
msg := ""
|
||||
err = c.Deliver(ctx, "postmaster@other.example", "mjl@mox.example", int64(len(msg)), strings.NewReader(msg), false, false)
|
||||
var xerr Error
|
||||
if err == nil || !errors.Is(err, ErrStatus) || !errors.As(err, &xerr) || !xerr.Permanent {
|
||||
panic(fmt.Errorf("got %#v, expected ErrStatus with Permanent", err))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
type xserver struct {
|
||||
|
Reference in New Issue
Block a user