Swift Mailer Delivery Status

Swiftmailer has nothing to do with the actual delivery of the mail. It just hands things over to whatever SMTP server you specified, and it's that server that takes care of the delivery. You need to check the SMTP server's logs to see what happened to the mail. It may get stuck in the outgoing queue because the server's swamped. It may get stuck in a queue because the receiving end is unreachable or is using grey-listing, etc... Swiftmailer's job ends once it gets acknowledgement from the SMTP server that the mail's been queued.


Rather old post, but as of Swiftmailer 4+ and aside from getting the result status from the send method call. If you're wanting to debug your mailer and see what is happening during the transport, you can use the Logger Plugins, or even create your own Plugin. https://swiftmailer.symfony.com/docs/plugins.html

$mailer = \Swift_Mailer::newInstance(
    \Swift_SmtpTransport::newInstance('tls://smtp.gmail.com', 465)
);
$logger = new \Swift_Plugins_Loggers_ArrayLogger;
//$logger = new \Swift_Plugins_Loggers_EchoLogger; //echo messages in real-time
$mailer->registerPlugin(new \Swift_Plugins_LoggerPlugin($logger));

foreach ($recipients as $recipient) {
    //...

    $mailer->send(/*...*/);
}

echo $logger->dump(); //not needed if using EchoLogger plugin

Which will output the transport message for each send call, that looks like

++ Starting Swift_SmtpTransport 
<< 220 smtp.gmail.com ESMTP x12sm4143221vkc.19 - gsmtp 
>> EHLO server.example.com 
<< 250-smtp.gmail.com at your service, [192.168.1.1] 250-SIZE 35882577 250-8BITMIME 250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH 250-ENHANCEDSTATUSCODES 250-PIPELINING 250-CHUNKING 250 SMTPUTF8 
>> AUTH LOGIN 
<< 334 AbcDefGhIjKlMnop 
>> AbcDefGhIjKlMnop== 
<< 334 AbcDefGhIjKlMnop 
>> AbcDefGhIjKlMnop== 
<< 235 2.7.0 Accepted 
++ Swift_SmtpTransport started 
>> MAIL FROM: 
<< 250 2.1.0 OK x12sm4143221vkc.19 - gsmtp 
>> RCPT TO:<[email protected]> 
<< 250 2.1.5 OK x12sm4143221vkc.19 - gsmtp 
>> DATA 
<< 354 Go ahead x12sm4143221vkc.19 - gsmtp 
>> . 
<< 250 2.0.0 OK 1468948643 x12sm4143221vkc.19 - gsmtp

There are at least three layers of checks that SwiftMailer supports, that will report several types of delivery failures.

1) Always check the return code from SwiftMailer's send() or batchSend() commands for a non-zero result. From the documentation:

//Send the message
$numSent = $mailer->send($message);

printf("Sent %d messages\n", $numSent);

/* Note that often that only the boolean equivalent of the
   return value is of concern (zero indicates FALSE)

if ($mailer->send($message))
{
  echo "Sent\n";
}
else
{
  echo "Failed\n";
}

2) Use the failures-by-reference feature to know if specific address(es) were rejected or couldn't complete:

//Pass a variable name to the send() method
if (!$mailer->send($message, $failures))
{
  echo "Failures:";
  print_r($failures);
}

/*
Failures:
Array (
  0 => [email protected],
  1 => [email protected]
)
*/

3) In a few situations you might want to enable return receipts as well, which confirm that an email reader displayed the message. They often are disabled or ignored by users or their email apps, but if you get a receipt, it is highly confirmatory. Note also that this might occur many days after sending so it's not a real-time synchronous test like the two above.

$message->setReadReceiptTo('[email protected]');

However, since there are so many variables and layers of systems involved in SMTP delivery, it is not generally possible to be absolutely sure messages were delivered. The best you can do is make sure you're using the first two checks above. If you're using YOUR own server for the SMTP service, then you ALSO need to be watching your logs and queues as Marc B mentioned.

One other example that emphasizes the need to get familiar with whatever underlying email system you're using. I've just started using the Swift_AWSTransport by John Hobbs for Amazon Web Services SES. SES has the ability to return an XML response with diagnostic information for each message sent through it. Though SwiftMailer doesn't inherently understand how to use that XML response, I have found it invaluable for troubleshooting delivery. I mention it because I found that in some cases, checks #1 and #2 above will appear successful to SwiftMailer, yet SES didn't like something about my message formatting. I'm therefore looking into parsing that XML as an additional check.