Added a mutex lock and unlock around the Send function to prevent concurrent access issues and ensure thread safety. This change helps avoid race conditions when multiple goroutines attempt to send messages simultaneously.
Refactor `DialWithContext` to delegate client creation to `SMTPClientFromDialWithContext`. Add new methods `SendWithSMTPClient`, `CloseWithSMTPClient`, and `ResetWithSMTPClient` to handle specific actions on `smtp.Client`. Simplify `auth`, `sendSingleMsg`, and `tls` methods by passing client as parameters.
Structured the initialization of SendError on connection errors to improve code readability and maintainability. This change affects the error handling in both client_120.go and client_119.go by spreading the error details across multiple lines.
Added support for Enhanced Status Codes (ESC) when checking the SMTP client's extensions. The SendError struct now includes the error code and enhanced status code for improved diagnostics.
Updated the documentation for the Send method in client_119.go and client_120.go to provide clearer explanations, include detailed descriptions of parameters, and specify return values. Ensured consistency across files by elaborating on error handling and connection checks.
Enhanced the documentation of the `Send` function to explicitly describe the behavior when the Client has no active connection and the handling of multiple message transmissions. This ensures developers understand the error handling mechanism and the association of `SendError` with each message.
Consolidated the message sending logic into a single `sendSingleMsg` function to reduce duplication and improve code maintainability. This change simplifies the `Send` method in multiple Go version files by removing redundant code and calling the new helper function instead.
Renamed the variable 'failed' to 'hasError' to better reflect its purpose and improve code readability. This change helps in understanding that the variable indicates the presence of an error rather than a generic failure.
Changed from range over messages to range with index to correctly update sendError field in the original messages slice. This prevents shadowing issues and ensures proper error logging for each message.
Extracted message sending functionality into a new helper function `sendSingleMsg`. This improves the code readability and maintainability by reducing the complexity of the main loop and encapsulating error handling per message.
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.
Updated variable names in the client_120.go file to enhance readability and clarity. This observes best practices for naming conventions in Go, producing cleaner code that's easier to maintain and troubleshoot. Changes primarily consist of replacing abbreviations with full descriptive names.
The commit introduces improved variable names in the SMTP client code that are more expressive and better describe the function they perform. This is combined with corrections to some code comments. It's aimed to increase code readability and maintainability. Updates are made across the client_119.go and client.go files to ensure consistent naming conventions.
This update introduces a new property, `isDelivered`, in the message struct to track if a message has been successfully sent or not. Additionally, this also includes a new helper function `IsDelivered` to easily retrieve the status. This feature enhances the tracking capabilities of outgoing messages across different client files.
This PR refactors the the DSN (RFC 1891) SMTP client handling, that was introduced in f4cdc61dd0.
While most of the Client options stay the same, the whole workaround logic for the SMTP client has been removed and added as part of the SMTP client instead.
This was we got rid of the Client's own `mail()`, `rcpt()`, `dsnRcpt()`, `dsnMail()` methods as well as the copies of the `cmd()` and `validateLine()` methods. The Client is now using the proper `Mail()` and `Rcpt()` methods of the SMTP client instead.
As proposed by @iwittkau the `SendError` type now has a `IsTemp()` method as well indicating to the user if the delivery error is retryable or not.
Since we want to use it in the error response from the Client functions like `Send` or `DialAndSend` we need to return the SendError type not only as part of the `*Msg` but also as return value for these methods. Hence, the changes made for #85 been overhauled to return the new error type instead. In the pre Go1.20 version of the `Send()` method we need to return an accumulated version of the SendError type, since we don't have `errors.Join()` and therefore, if more than one error occurred during the delivery we return an ambiguous error reason since we can't tell which of the captured errors is main error. For more details the user can always check the `*Msg.SendError`
Did a complete overhaul of the senderror.go.
- the list of `errors.New()` has been replaced with constant itoa error reasons as `SendErrReason`. Instead, the `Error()` method now reports the corresponding error message based on the reason.
- The `SendError` received a `Is()` method so that we can use `errors.Is()` for very specific error checking. I.e. we can check for `&SendErrors{Reason: ErrSMTPMailFrom, isTemp: true}`. This provides much more flexibility in the error checking capabilities
- A `isTemp` field has been added to the `SendError` type, indicating whether the received error is temporary and can be retried or not. Accordingly, the `*Msg` now has a `SendErrorIsTemp()` method indicating the same. The decision is based on the first 3 characters returned from the SMTP server. If the error code is within the 4xx range, the error is seen as temporary
- A test for the SendError type has been added
Since the send error indicate an error during the mail delivery, in my opinion it should be reset when a re-send is initiated, so that the senderror field always represents the latest delivery error. The send error should be checked after mail delivery and before a retry is started.
This PR introduces the `SendError` type which implements the error interface.
A new `senderror` field has been added to the `Msg` as well, so introduce this type to it.
I've also added different error variables that indicate the different things that can go wrong during mail delivery. These variables can be checked for, for each `Msg` using the `errors.As` method
The `Error()` method of `SendError` will return a detailed error string on why the `Msg` could not be delivered.
Additionally, `HasSendError()` and `SendError()` methods have been added to `Msg`. While `HasSendError()` simply returns a bool in case a `Msg` failed during delivery, the `SendError()` will return the full `SendError` error interface.
`Client.Send()` provides the possibility to send multiple `*Msg` in one go. If one of the `*Msg` caused an error with the sending mail server, we were returning completely, while not processing any `*Msg` that came after the failing message.
This PR fixes this behaviour by processing each message first and then return a accumulated error in case any of the `*Msg` processing failed
Additionally, this PR separates the `Client.Send()` method into two different versions. One that makes use of the new `errors.Join()` functionality that is introduced with Go 1.20 and one that handles it the old way for any supported version lower than Go 1.20