diff --git a/fetcher/fetcher.go b/fetcher/fetcher.go index 7f8d7fc9d1f248d0accc24e7495b491270e6de4c..75cc0ad4e60f168e8643da37f7056dabf58d5b1b 100644 --- a/fetcher/fetcher.go +++ b/fetcher/fetcher.go @@ -17,6 +17,7 @@ import ( "os" "slices" "strings" + "sync" "time" "github.com/ProtonMail/go-crypto/openpgp" @@ -30,6 +31,28 @@ import ( "golang.org/x/text/transform" ) +// debugIMAPFile holds a single shared file handle for IMAP debug logging, +// opened once via debugIMAPOnce to avoid leaking a descriptor per connection. +var ( + debugIMAPFile *os.File + debugIMAPOnce sync.Once +) + +func getDebugIMAPWriter() io.Writer { + debugIMAPOnce.Do(func() { + if path := os.Getenv("DEBUG_IMAP"); path != "" { + f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600) + if err == nil { + debugIMAPFile = f + } + } + }) + if debugIMAPFile != nil { + return debugIMAPFile + } + return nil +} + // Attachment holds data for an email attachment. type Attachment struct { Filename string @@ -243,10 +266,8 @@ func connectWithOptions(account *config.Account, extraOpts *imapclient.Options) options.UnilateralDataHandler = extraOpts.UnilateralDataHandler options.DebugWriter = extraOpts.DebugWriter } - if path := os.Getenv("DEBUG_IMAP"); path != "" { - if f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600); err == nil { - options.DebugWriter = f - } + if w := getDebugIMAPWriter(); w != nil { + options.DebugWriter = w } var c *imapclient.Client