Add IMAP connection timeout handling
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
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user