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 = 60 * 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) }