Skip to content
Advertisement

SwiftMailer silently ignores errors when messages fail delivery

When run from inside controller and when in-memory spooling is configured via spool: { type: memory } swiftmailer seems to work like this:

  • whenever from within controller mailer->send($message) is called -> save message in memory
  • when controller has finished work and symfony Kernel is about to shutdown (somwehere in event kernel.terminate or smth) – check messages saved in memory and _actually submit them to SMTP-server

However this last step seems to silently ignore any errors which may be thrown when peforming submitting of the message to the SMTP server.

I discovered that errors are silently swallowed when I was setting up SMTP from Amazon SES, and have made wrong configuration:

JavaScript

Now, if I attempt to send email using wrong configuration from a symfony Command, just as expected I get Swift_TransportException and error is NOT silently ignored. (From my observations it seems that symfony commands do NOT use memory-spooling and attempt to send messages immediately)

Below is sample of the command (so you’re sure I am doing it right).

JavaScript

And here’s command output when the exception Swift_TransportException is thrown:

JavaScript

Hovewer if I attempt to send email from controller, then I see no error messages. Basically this means that in case there’s an error (misconfiguration or network error or SMTP server down), all the emails I sent will silently disappear without any trace (no exception thrown, no error loggged in dev.log neither in prod.log).

How can I force Swiftmailer to leave trace of failed delivery attempt?

Advertisement

Answer

You might be able to force the delivery of the emails by flushing the spooler manually, which should then allow you to catch the exception and log as needed. I found an example in the docs here (modified for the context of a controller)…

https://symfony.com/doc/2.6/cookbook/console/sending_emails.html

JavaScript

While the example was originally for use in the console environment, I see no reason why it wouldn’t be valid in a controller.

Edit:

Another way to log the exception would be to utilize the Swiftmailer event system. This involves creating a custom plugin (as a service would be best) that implements Swift_Events_TransportExceptionListener, then registering it with the mailer.

For example, the custom plugin class:

JavaScript

Then add this as a service along with the swiftmailer.default.plugin tag. That will automatically register it as a Swiftmailer plugin…

JavaScript

This will log the exception message in the standard log area for dev/prod. However, if the timeout takes very long to occur I think it still may not log correctly if the user clicks away or closes their browser/tab, etc. Perhaps the above along with setting a lower timeout value for Swiftmailer via the mailer_timeout parameter.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement