From 0ea963185534c9cfa2f1d329257f3f56a5358e80 Mon Sep 17 00:00:00 2001 From: Winni Neessen Date: Tue, 16 Jul 2024 13:07:20 +0200 Subject: [PATCH] Refactor error handling in message delivery process The error handling process in sending messages has been refactored for better accuracy and efficiency. Instead of immediately joining errors and returning, they are now collected in a slice and joined in a deferred function to ensure all errors are captured before being returned. Furthermore, the SendError structure has been updated to include a reference to the affected message, providing better context for each error. --- client_120.go | 38 +++++++++++++++++++++++--------------- senderror.go | 9 +++++---- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/client_120.go b/client_120.go index ed80fee..3a867d9 100644 --- a/client_120.go +++ b/client_120.go @@ -18,25 +18,33 @@ func (c *Client) Send(messages ...*Msg) (returnErr error) { returnErr = &SendError{Reason: ErrConnCheck, errlist: []error{err}, isTemp: isTempError(err)} return } - for _, message := range messages { + + var errs []error + defer func() { + returnErr = errors.Join(errs...) + }() + + for msgid, message := range messages { message.sendError = nil if message.encoding == NoEncoding { if ok, _ := c.smtpClient.Extension("8BITMIME"); !ok { message.sendError = &SendError{Reason: ErrNoUnencoded, isTemp: false} - returnErr = errors.Join(returnErr, message.sendError) + errs = append(errs, message.sendError) continue } } from, err := message.GetSender(false) if err != nil { - message.sendError = &SendError{Reason: ErrGetSender, errlist: []error{err}, isTemp: isTempError(err)} - returnErr = errors.Join(returnErr, message.sendError) + message.sendError = &SendError{Reason: ErrGetSender, errlist: []error{err}, isTemp: isTempError(err), + affectedMsg: messages[msgid]} + errs = append(errs, message.sendError) continue } rcpts, err := message.GetRecipients() if err != nil { - message.sendError = &SendError{Reason: ErrGetRcpts, errlist: []error{err}, isTemp: isTempError(err)} - returnErr = errors.Join(returnErr, message.sendError) + message.sendError = &SendError{Reason: ErrGetRcpts, errlist: []error{err}, isTemp: isTempError(err), + affectedMsg: messages[msgid]} + errs = append(errs, message.sendError) continue } @@ -47,9 +55,9 @@ func (c *Client) Send(messages ...*Msg) (returnErr error) { } if err = c.smtpClient.Mail(from); err != nil { message.sendError = &SendError{Reason: ErrSMTPMailFrom, errlist: []error{err}, isTemp: isTempError(err)} - returnErr = errors.Join(returnErr, message.sendError) + errs = append(errs, message.sendError) if resetSendErr := c.smtpClient.Reset(); resetSendErr != nil { - returnErr = errors.Join(returnErr, resetSendErr) + errs = append(errs, resetSendErr) } continue } @@ -70,40 +78,40 @@ func (c *Client) Send(messages ...*Msg) (returnErr error) { } if failed { if resetSendErr := c.smtpClient.Reset(); resetSendErr != nil { - returnErr = errors.Join(returnErr, resetSendErr) + errs = append(errs, resetSendErr) } message.sendError = rcptSendErr - returnErr = errors.Join(returnErr, message.sendError) + errs = append(errs, message.sendError) continue } writer, err := c.smtpClient.Data() if err != nil { message.sendError = &SendError{Reason: ErrSMTPData, errlist: []error{err}, isTemp: isTempError(err)} - returnErr = errors.Join(returnErr, message.sendError) + errs = append(errs, message.sendError) continue } _, err = message.WriteTo(writer) if err != nil { message.sendError = &SendError{Reason: ErrWriteContent, errlist: []error{err}, isTemp: isTempError(err)} - returnErr = errors.Join(returnErr, message.sendError) + errs = append(errs, message.sendError) continue } message.isDelivered = true if err = writer.Close(); err != nil { message.sendError = &SendError{Reason: ErrSMTPDataClose, errlist: []error{err}, isTemp: isTempError(err)} - returnErr = errors.Join(returnErr, message.sendError) + errs = append(errs, message.sendError) continue } if err = c.Reset(); err != nil { message.sendError = &SendError{Reason: ErrSMTPReset, errlist: []error{err}, isTemp: isTempError(err)} - returnErr = errors.Join(returnErr, message.sendError) + errs = append(errs, message.sendError) continue } if err = c.checkConn(); err != nil { message.sendError = &SendError{Reason: ErrConnCheck, errlist: []error{err}, isTemp: isTempError(err)} - returnErr = errors.Join(returnErr, message.sendError) + errs = append(errs, message.sendError) } } diff --git a/senderror.go b/senderror.go index dfe7502..72500cd 100644 --- a/senderror.go +++ b/senderror.go @@ -56,10 +56,11 @@ const ( // SendError is an error wrapper for delivery errors of the Msg type SendError struct { - Reason SendErrReason - isTemp bool - errlist []error - rcpt []string + affectedMsg *Msg + errlist []error + isTemp bool + rcpt []string + Reason SendErrReason } // SendErrReason represents a comparable reason on why the delivery failed