imapclient: clean up function signature of New, allowing for future options too

This commit is contained in:
Mechiel Lukkien
2025-04-11 21:04:13 +02:00
parent af3e9351bc
commit 2c1283f032
6 changed files with 53 additions and 29 deletions

View File

@ -45,7 +45,7 @@ type Conn struct {
xtw *moxio.TraceWriter
log mlog.Log
panic bool
errHandle func(err error) // If set, called for all errors. Can panic. Used for imapserver tests.
tagGen int
record bool // If true, bytes read are added to recordBuf. recorded() resets.
recordBuf []byte
@ -67,28 +67,46 @@ func (e Error) Unwrap() error {
return e.err
}
// Opts has optional fields that influence behaviour of a Conn.
type Opts struct {
Logger *slog.Logger
// Error is called for both IMAP-level and connection-level errors. Is allowed to
// call panic.
Error func(err error)
}
// New creates a new client on conn.
//
// If xpanic is true, functions that would return an error instead panic. For parse
// errors, the resulting stack traces show typically show what was being parsed.
//
// The initial untagged greeting response is read and must be "OK" or
// "PREAUTH". If preauth, the connection is already in authenticated state,
// typically through TLS client certificate. This is indicated in Conn.Preauth.
func New(cid int64, conn net.Conn, xpanic bool) (client *Conn, rerr error) {
log := mlog.New("imapclient", nil).WithCid(cid)
//
// Logging is written to log, in particular IMAP protocol traces are written with
// prefixes "CR: " and "CW: " (client read/write) as quoted strings at levels
// Debug-4, with authentication messages at Debug-6 and (user) data at level
// Debug-8.
func New(conn net.Conn, opts *Opts) (client *Conn, rerr error) {
c := Conn{
conn: conn,
log: log,
panic: xpanic,
CapAvailable: map[Capability]struct{}{},
CapEnabled: map[Capability]struct{}{},
}
c.tr = moxio.NewTraceReader(log, "CR: ", &c)
var clog *slog.Logger
if opts != nil {
c.errHandle = opts.Error
clog = opts.Logger
} else {
clog = slog.Default()
}
c.log = mlog.New("imapclient", clog)
c.tr = moxio.NewTraceReader(c.log, "CR: ", &c)
c.br = bufio.NewReader(c.tr)
// Writes are buffered and write to Conn, which may panic.
c.xtw = moxio.NewTraceWriter(log, "CW: ", &c)
c.xtw = moxio.NewTraceWriter(c.log, "CW: ", &c)
c.xbw = bufio.NewWriter(c.xtw)
defer c.recover(&rerr)
@ -116,10 +134,6 @@ func New(cid int64, conn net.Conn, xpanic bool) (client *Conn, rerr error) {
}
func (c *Conn) recover(rerr *error) {
if c.panic {
return
}
x := recover()
if x == nil {
return
@ -128,6 +142,9 @@ func (c *Conn) recover(rerr *error) {
if !ok {
panic(x)
}
if c.errHandle != nil {
c.errHandle(err)
}
*rerr = err
}
@ -201,11 +218,6 @@ func (c *Conn) xtracewrite(level slog.Level) func() {
}
}
// SetPanic sets whether errors cause a panic instead of returning errors.
func (c *Conn) SetPanic(panic bool) {
c.panic = panic
}
// Close closes the connection, flushing and closing any compression and TLS layer.
//
// You may want to call Logout first. Closing a connection with a mailbox with