package imapserver import ( "crypto/tls" "net" goimapserver "github.com/emersion/go-imap/v2/imapserver" ) func newSessionFunc(backend *Backend) func(*goimapserver.Conn) (goimapserver.Session, *goimapserver.GreetingData, error) { return func(c *goimapserver.Conn) (goimapserver.Session, *goimapserver.GreetingData, error) { host, _, err := net.SplitHostPort(c.NetConn().RemoteAddr().String()) if err != nil { host = c.NetConn().RemoteAddr().String() } return backend.NewSession(host), nil, nil } } // NewPlainServer mirrors smtpserver.NewPlainServer: no TLS at all, so STARTTLS is // never offered. InsecureAuth is required here or LOGIN would always fail with // [PRIVACYREQUIRED] on this listener. func NewPlainServer(backend *Backend) *goimapserver.Server { return goimapserver.New(&goimapserver.Options{ NewSession: newSessionFunc(backend), InsecureAuth: true, }) } // NewTLSServer mirrors smtpserver.NewTLSServer: implicit TLS, the whole connection is // encrypted from the first byte. Call ListenAndServeTLS (not ListenAndServe) to run // it — TLSConfig here only takes effect for that method. // // InsecureAuth is set here too, same as smtpserver.NewTLSServer's AllowInsecureAuth: // this server is only ever Serve()'d behind abuseguard's and idletimeout's listener/conn // wrapper types, so go-imap's own isTLS check (conn.go: c.conn.(*tls.Conn)) sees our // wrapper instead of the real *tls.Conn and always reports false. Without this, go-imap // advertises LOGINDISABLED and refuses LOGIN even though the connection is already // encrypted by construction (it's the dedicated implicit-TLS listener) — clients // configured for SSL/TLS (not STARTTLS), like Thunderbird on port 993, can never // authenticate. func NewTLSServer(backend *Backend, tlsConfig *tls.Config) *goimapserver.Server { return goimapserver.New(&goimapserver.Options{ NewSession: newSessionFunc(backend), TLSConfig: tlsConfig, InsecureAuth: true, }) }