[8.x] Fix failover mailer when used with Mailgun & SES mailers #40254
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
#38344 introduced the
failover
mailer into the framework, with the idea being that if a mail fails to send via one mailer, alternative mailer(s) will be tried.It seems that the first-party HTTP based mailers / transport included with the framework (Mailgun & SES) don't trigger an attempt to send using an alternative mailer if the API request fails - the exception from the underlying library isn't caught (a
GuzzleException
for Mailgun andAwsException
for SES).The issue seems to be that the
send()
method in the underlying\Swift_Transport_FailoverTransport
class only catchesSwift_TransportException
exceptions, which trigger the failover logic. Other exceptions aren't handed.Steps To Reproduce (with Mailgun):
config/mail.php
:Ensure your attempt to send via Mailgun will fail (e.g. use incorrect credentials / block requests to the API domain on your local network).
Attempt to send a mail - you'll get a
ClientException
exception, rather than the alternative failoverlog
mailer being used.Solution
The upstream
swiftmailer/swiftamiler
package is no longer maintained, so we can't suggest a PR to catch other exceptions in the failover logic. Plus this feels more like an issue with the Laravel transport classes not throwing the correct exceptions.This PR simply catches any
\GuzzleHttp\Exception\GuzzleException
(Mailgun) /\Aws\Exception\AwsException
(SES) exceptions and then throws a newSwift_TransportException
instead (with the original passed in via$previous
).I haven't added any tests as there don't appear to be any for the
MailgunTransport
class, and wasn't sure of the best way of mocking a failure for SES - however I'm happy to add tests if anyone can assist!