Introduce idleConn wrapper to prevent wedged connections Add test for silent server timeout behavior Implement proper TLS handshake and greeting handling Set explicit dial and read timeouts
31 lines
1.0 KiB
Go
31 lines
1.0 KiB
Go
package imapx
|
|
|
|
import (
|
|
"net"
|
|
"time"
|
|
)
|
|
|
|
// idleReadTimeout bounds how long a connection may go WITHOUT receiving any
|
|
// bytes from the server before the read is aborted. It is an *idle* timeout,
|
|
// not a total deadline: every successful read pushes it forward, so a slow but
|
|
// live transfer never trips it — only a genuinely dead/mute socket does. This
|
|
// is what stops an account from wedging in "running" forever when a server
|
|
// accepts a command (e.g. a large FETCH) and then goes silent.
|
|
var idleReadTimeout = 120 * time.Second
|
|
|
|
// idleConn wraps a net.Conn and arms a fresh read deadline before every Read.
|
|
// It lives beneath any TLS layer (the raw TCP conn), so the deadline governs
|
|
// the actual blocking network read regardless of encryption.
|
|
type idleConn struct {
|
|
net.Conn
|
|
timeout time.Duration
|
|
}
|
|
|
|
func (c *idleConn) Read(b []byte) (int, error) {
|
|
if c.timeout > 0 {
|
|
// Ignore the error: a closed conn will surface it from Read below.
|
|
_ = c.Conn.SetReadDeadline(time.Now().Add(c.timeout))
|
|
}
|
|
return c.Conn.Read(b)
|
|
}
|