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.
This commit is contained in:
Winni Neessen 2024-07-16 13:07:20 +02:00
parent 32a5603496
commit 0ea9631855
Signed by: wneessen
GPG key ID: 5F3AF39B820C119D
2 changed files with 28 additions and 19 deletions

View file

@ -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)
}
}

View file

@ -56,10 +56,11 @@ const (
// SendError is an error wrapper for delivery errors of the Msg
type SendError struct {
Reason SendErrReason
isTemp bool
affectedMsg *Msg
errlist []error
isTemp bool
rcpt []string
Reason SendErrReason
}
// SendErrReason represents a comparable reason on why the delivery failed