From 51eec742067496067b368bc752ce17b68fee927f Mon Sep 17 00:00:00 2001 From: nimjor <76883392+nimjor@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:46:06 -0500 Subject: [PATCH] Smtp logger (#3339) * allow passing Logger instance in config * pass main app logger to smtp config * implement smtp.Logger in smtpsrv to make logs go through app.cfg.Logger https://github.com/target/goalert/issues/3335 * filter out TCP ECONNRESET error messages * early return instead of negation; add TODO --------- Co-authored-by: Jordan Nimlos --- app/initsmtpsrv.go | 1 + smtpsrv/config.go | 2 ++ smtpsrv/server.go | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/app/initsmtpsrv.go b/app/initsmtpsrv.go index dc92a57f86..b8f02fb741 100644 --- a/app/initsmtpsrv.go +++ b/app/initsmtpsrv.go @@ -24,6 +24,7 @@ func (app *App) initSMTPServer(ctx context.Context) error { TLSConfig: app.cfg.TLSConfigSMTP, MaxRecipients: app.cfg.SMTPMaxRecipients, BackgroundContext: app.LogBackgroundContext, + Logger: app.cfg.Logger, AuthorizeFunc: func(ctx context.Context, id string) (context.Context, error) { tok, _, err := authtoken.Parse(id, nil) if err != nil { diff --git a/smtpsrv/config.go b/smtpsrv/config.go index d9a7f74998..de425c37d9 100644 --- a/smtpsrv/config.go +++ b/smtpsrv/config.go @@ -5,6 +5,7 @@ import ( "crypto/tls" "github.com/target/goalert/alert" + "github.com/target/goalert/util/log" ) // Config is used to configure the SMTP server. @@ -15,6 +16,7 @@ type Config struct { MaxRecipients int BackgroundContext func() context.Context + Logger *log.Logger AuthorizeFunc func(ctx context.Context, id string) (context.Context, error) CreateAlertFunc func(ctx context.Context, a *alert.Alert) error diff --git a/smtpsrv/server.go b/smtpsrv/server.go index b5267e633b..411bfa66e6 100644 --- a/smtpsrv/server.go +++ b/smtpsrv/server.go @@ -2,12 +2,43 @@ package smtpsrv import ( "context" + "errors" + "fmt" "net" + "strings" "time" "github.com/emersion/go-smtp" + "github.com/target/goalert/util/log" ) +// SMTPLogger implements the smtp.Logger interface using the main app Logger. +type SMTPLogger struct { + logger *log.Logger +} + +// Printf adheres to smtp.Server's Logger interface. +func (l *SMTPLogger) Printf(format string, v ...interface{}) { + s := fmt.Sprintf(format, v...) + // TODO: Uses string compare to filter out errors caused by TCP health checks, + // remove once https://github.com/emersion/go-smtp/issues/236 has been fixed. + if strings.Contains(s, "read: connection reset by peer") { + return + } + l.logger.Error(context.Background(), errors.New(s)) +} + +// Print adheres to smtp.Server's Logger interface. +func (l *SMTPLogger) Println(v ...interface{}) { + s := fmt.Sprint(v...) + // TODO: Uses string compare to filter out errors caused by TCP health checks, + // remove once https://github.com/emersion/go-smtp/issues/236 has been fixed. + if strings.Contains(s, "read: connection reset by peer") { + return + } + l.logger.Error(context.Background(), errors.New(s)) +} + // Server implements an SMTP server that creates alerts. type Server struct { cfg Config @@ -19,6 +50,7 @@ func NewServer(cfg Config) *Server { s := &Server{cfg: cfg} srv := smtp.NewServer(s) + srv.ErrorLog = &SMTPLogger{logger: cfg.Logger} srv.Domain = cfg.Domain srv.ReadTimeout = 10 * time.Second srv.WriteTimeout = 10 * time.Second